mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-28 20:02:00 +03:00
codership/wsrep-lib#104 Error voting support
- 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:
@ -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
|
||||
|
@ -41,6 +41,10 @@ namespace wsrep
|
||||
{
|
||||
return (id_ < other.id_);
|
||||
}
|
||||
bool operator==(const client_id& other) const
|
||||
{
|
||||
return (id_ == other.id_);
|
||||
}
|
||||
private:
|
||||
type id_;
|
||||
};
|
||||
|
@ -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";
|
||||
|
@ -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_;
|
||||
|
@ -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_;
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user