1
0
mirror of https://github.com/codership/wsrep-lib.git synced 2025-07-28 20:02:00 +03:00
- populate and pass real error description buffer to provider in case
   of applying error
 - return 0 from server_state::on_apply() if error voting confirmed
   consistency
 - remove fragments and rollback after fragment applying failure
 - always release streaming applier on commit or rollback
This commit is contained in:
Alexey Yurchenko
2019-04-30 19:00:48 +03:00
parent fd66bdef0b
commit 0f676bd893
22 changed files with 470 additions and 187 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Codership Oy <info@codership.com>
* Copyright (C) 2018-2019 Codership Oy <info@codership.com>
*
* This file is part of wsrep-lib.
*
@ -38,13 +38,22 @@ namespace wsrep
, size_(size)
{ }
const_buffer(const const_buffer& b)
: ptr_(b.ptr())
, size_(b.size())
{ }
const void* ptr() const { return ptr_; }
const void* data() const { return ptr_; }
const char* data() const { return static_cast<const char*>(ptr_); }
size_t size() const { return size_; }
const_buffer& operator=(const const_buffer& b)
{
ptr_ = b.ptr();
size_ = b.size();
return *this;
}
private:
// const_buffer(const const_buffer&);
// const_buffer& operator=(const const_buffer&);
const void* ptr_;
size_t size_;
};
@ -57,16 +66,36 @@ namespace wsrep
: buffer_()
{ }
void resize(size_t s) { buffer_.resize(s); }
void clear()
{
// using swap to ensure deallocation
std::vector<char>().swap(buffer_);
}
void push_back(const char* begin, const char* end)
{
buffer_.insert(buffer_.end(), begin, end);
}
const char* data() const { return &buffer_[0]; }
template <class C> void push_back(const C& c)
{
std::copy(c.begin(), c.end(), std::back_inserter(buffer_));
}
size_t size() const { return buffer_.size(); }
char* data() { return &buffer_[0]; }
const char* data() const { return &buffer_[0]; }
mutable_buffer& operator= (const mutable_buffer& other)
{
buffer_ = other.buffer_;
return *this;
}
private:
std::vector<char> buffer_;
};
}
#endif // WSREP_BUFFER_HPP

View File

@ -41,6 +41,10 @@ namespace wsrep
{
return (id_ < other.id_);
}
bool operator==(const client_id& other) const
{
return (id_ == other.id_);
}
private:
type id_;
};

View File

@ -90,6 +90,8 @@ namespace wsrep
*/
enum mode
{
/** undefined mode */
m_undefined,
/** Locally operating client session. */
m_local,
/** High priority mode */
@ -247,6 +249,8 @@ namespace wsrep
/**
* Perform cleanup after applying a transaction.
*
* @param err Applying error (empty for no error)
*/
void after_applying()
{
@ -508,6 +512,15 @@ namespace wsrep
transaction_.adopt(transaction);
}
/**
* Adopt (store) transaction applying error for further processing.
*/
void adopt_apply_error(wsrep::mutable_buffer& err)
{
assert(mode_ == m_high_priority);
transaction_.adopt_apply_error(err);
}
/**
* Clone enough state from another transaction so that replaing will
* be possible with a transaction contained in this client state.
@ -546,15 +559,15 @@ namespace wsrep
*
* @return Zero on success, non-zero otherwise.
*/
int enter_toi(const wsrep::key_array& key_array,
const wsrep::const_buffer& buffer,
int flags);
int enter_toi_local(const wsrep::key_array& key_array,
const wsrep::const_buffer& buffer,
int flags);
/**
* Enter applying total order critical section.
* Enter applier TOI mode
*
* @param ws_meta Write set meta data
*/
int enter_toi(const wsrep::ws_meta& ws_meta);
void enter_toi_mode(const wsrep::ws_meta& ws_meta);
/**
* Return true if the client_state is under TOI operation.
@ -573,10 +586,20 @@ namespace wsrep
{
return toi_mode_;
}
/**
* Leave total order isolation critical section.
* (for local mode clients)
*
* @param err definition of the error that happened during the
* execution of TOI operation (empty for no error)
*/
int leave_toi();
int leave_toi_local(const wsrep::mutable_buffer& err);
/**
* Leave applier TOI mode.
*/
void leave_toi_mode();
/**
* Begin rolling schema upgrade operation.
@ -770,7 +793,7 @@ namespace wsrep
, client_service_(client_service)
, id_(id)
, mode_(mode)
, toi_mode_()
, toi_mode_(m_undefined)
, state_(s_none)
, state_hist_()
, transaction_(*this)
@ -804,6 +827,9 @@ namespace wsrep
enum wsrep::provider::status status =
wsrep::provider::success);
void enter_toi_common();
void leave_toi_common();
wsrep::thread::id owning_thread_id_;
wsrep::thread::id current_thread_id_;
bool has_rollbacker_;
@ -864,6 +890,7 @@ namespace wsrep
{
switch (mode)
{
case wsrep::client_state::m_undefined: return "undefined";
case wsrep::client_state::m_local: return "local";
case wsrep::client_state::m_high_priority: return "high priority";
case wsrep::client_state::m_toi: return "toi";

View File

@ -48,6 +48,13 @@ namespace wsrep
{
return undefined_;
}
bool operator==(const gtid& other) const
{
return (
seqno_ == other.seqno_ &&
id_ == other.id_
);
}
private:
static const wsrep::gtid undefined_;
wsrep::id id_;

View File

@ -41,7 +41,7 @@ namespace wsrep
virtual ~high_priority_service() { }
int apply(const ws_handle& ws_handle, const ws_meta& ws_meta,
const const_buffer& data)
const const_buffer& data)
{
return server_state_.on_apply(*this, ws_handle, ws_meta, data);
}
@ -70,9 +70,13 @@ namespace wsrep
* new transaction before applying a write set and must
* either commit to make changes persistent or roll back.
*
* @params ws_meta Write set meta data
* @params ws Write set buffer
* @params err Buffer to store error data
*/
virtual int apply_write_set(const wsrep::ws_meta&,
const wsrep::const_buffer&) = 0;
virtual int apply_write_set(const wsrep::ws_meta& ws_meta,
const wsrep::const_buffer& ws,
wsrep::mutable_buffer& err) = 0;
/**
* Append a fragment into fragment storage. This will be
@ -141,9 +145,14 @@ namespace wsrep
*
* TOI operation is a standalone operation and should not
* be executed as a part of a transaction.
*
* @params ws_meta Write set meta data
* @params ws Write set buffer
* @params err Buffer to store error data
*/
virtual int apply_toi(const wsrep::ws_meta&,
const wsrep::const_buffer&) = 0;
virtual int apply_toi(const wsrep::ws_meta& ws_meta,
const wsrep::const_buffer& ws,
wsrep::mutable_buffer& err) = 0;
/**
* Actions to take after applying a write set was completed.
@ -175,11 +184,19 @@ namespace wsrep
*
* @params ws_handle Write set handle
* @params ws_meta Write set meta data
* @params err Optional applying error data buffer, may be modified
*
* @return Zero in case of success, non-zero on failure
*/
virtual int log_dummy_write_set(const ws_handle& ws_handle,
const ws_meta& ws_meta) = 0;
const ws_meta& ws_meta,
wsrep::mutable_buffer& err) = 0;
/**
* Adopt (store) apply error description for further reporting
* to provider, source buffer may be modified.
*/
virtual void adopt_apply_error(wsrep::mutable_buffer& err) = 0;
virtual bool is_replaying() const = 0;
@ -189,6 +206,7 @@ namespace wsrep
* Debug facility to crash the server at given point.
*/
virtual void debug_crash(const char* crash_point) = 0;
protected:
wsrep::server_state& server_state_;
bool must_exit_;

View File

@ -56,6 +56,14 @@ namespace wsrep
wsrep::transaction_id transaction_id() const
{ return transaction_id_; }
wsrep::client_id client_id() const { return client_id_; }
bool operator==(const stid& other) const
{
return (
server_id_ == other.server_id_ &&
transaction_id_ == other.transaction_id_ &&
client_id_ == other.client_id_
);
}
private:
wsrep::id server_id_;
wsrep::transaction_id transaction_id_;
@ -84,6 +92,13 @@ namespace wsrep
void* opaque() const { return opaque_; }
bool operator==(const ws_handle& other) const
{
return (
transaction_id_ == other.transaction_id_ &&
opaque_ == other.opaque_
);
}
private:
wsrep::transaction_id transaction_id_;
void* opaque_;
@ -134,9 +149,21 @@ namespace wsrep
return stid_.transaction_id();
}
bool ordered() const { return !gtid_.is_undefined(); }
wsrep::seqno depends_on() const { return depends_on_; }
int flags() const { return flags_; }
bool operator==(const ws_meta& other) const
{
return (
gtid_ == other.gtid_ &&
stid_ == other.stid_ &&
depends_on_ == other.depends_on_ &&
flags_ == other.flags_
);
}
private:
wsrep::gtid gtid_;
wsrep::stid stid_;
@ -300,7 +327,8 @@ namespace wsrep
virtual enum status commit_order_enter(const wsrep::ws_handle&,
const wsrep::ws_meta&) = 0;
virtual int commit_order_leave(const wsrep::ws_handle&,
const wsrep::ws_meta&) = 0;
const wsrep::ws_meta&,
const wsrep::mutable_buffer& err) = 0;
virtual int release(wsrep::ws_handle&) = 0;
/**
@ -325,7 +353,8 @@ namespace wsrep
/**
* Leave total order isolation critical section
*/
virtual enum status leave_toi(wsrep::client_id) = 0;
virtual enum status leave_toi(wsrep::client_id,
const wsrep::mutable_buffer& err) = 0;
/**
* Perform a causal read on cluster.

View File

@ -27,6 +27,7 @@
#include "streaming_context.hpp"
#include "lock.hpp"
#include "sr_key_set.hpp"
#include "buffer.hpp"
#include <cassert>
#include <vector>
@ -198,6 +199,12 @@ namespace wsrep
{ return streaming_context_; }
wsrep::streaming_context& streaming_context()
{ return streaming_context_; }
void adopt_apply_error(wsrep::mutable_buffer& buf)
{
apply_error_buf_ = std::move(buf);
}
const wsrep::mutable_buffer& apply_error() const
{ return apply_error_buf_; }
private:
transaction(const transaction&);
transaction operator=(const transaction&);
@ -214,6 +221,7 @@ namespace wsrep
int certify_fragment(wsrep::unique_lock<wsrep::mutex>&);
int certify_commit(wsrep::unique_lock<wsrep::mutex>&);
int append_sr_keys_for_commit();
int release_commit_order(wsrep::unique_lock<wsrep::mutex>&);
void streaming_rollback(wsrep::unique_lock<wsrep::mutex>&);
void clear_fragments();
void cleanup();
@ -240,6 +248,7 @@ namespace wsrep
size_t fragments_certified_for_statement_;
wsrep::streaming_context streaming_context_;
wsrep::sr_key_set sr_keys_;
wsrep::mutable_buffer apply_error_buf_;
};
static inline const char* to_c_string(enum wsrep::transaction::state state)