mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-28 20:02:00 +03:00
Started documenting client context.
This commit is contained in:
@ -229,6 +229,8 @@ TAB_SIZE = 4
|
||||
# newlines.
|
||||
|
||||
ALIASES =
|
||||
ALIASES = "startuml=\if DontIgnorePlantUMLCode"
|
||||
ALIASES += "enduml=\endif"
|
||||
|
||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||
# A mapping has the form "name=value". For example adding "class=itcl::class"
|
||||
|
@ -10,6 +10,71 @@ trrep::provider& trrep::client_context::provider() const
|
||||
return server_context_.provider();
|
||||
}
|
||||
|
||||
int trrep::client_context::before_command()
|
||||
{
|
||||
assert(state_ == s_idle);
|
||||
if (server_context_.rollback_mode() == trrep::server_context::rm_sync)
|
||||
{
|
||||
|
||||
/*!
|
||||
* \todo Wait until the possible synchronous rollback
|
||||
* has been finished.
|
||||
*/
|
||||
trrep::unique_lock<trrep::mutex> lock(mutex_);
|
||||
while (transaction_.state() == trrep::transaction_context::s_aborting)
|
||||
{
|
||||
// cond_.wait(lock);
|
||||
}
|
||||
}
|
||||
state_ = s_exec;
|
||||
if (transaction_.state() == trrep::transaction_context::s_must_abort)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trrep::client_context::after_command()
|
||||
{
|
||||
int ret(0);
|
||||
trrep::unique_lock<trrep::mutex> lock(mutex_);
|
||||
if (transaction_.state() == trrep::transaction_context::s_must_abort)
|
||||
{
|
||||
lock.unlock();
|
||||
rollback(transaction_);
|
||||
lock.lock();
|
||||
ret = 1;
|
||||
}
|
||||
state_ = s_idle;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int trrep::client_context::before_statement()
|
||||
{
|
||||
#if 0
|
||||
/*!
|
||||
* \todo It might be beneficial to implement timed wait for
|
||||
* server synced state.
|
||||
*/
|
||||
if (allow_dirty_reads_ == false &&
|
||||
server_context_.state() != trrep::server_context::s_synced)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif // 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trrep::client_context::after_statement()
|
||||
{
|
||||
#if 0
|
||||
/*!
|
||||
* \todo Check for replay state, do rollback if requested.
|
||||
*/
|
||||
#endif // 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: This should be pure virtual method, implemented by
|
||||
// DBMS integration or mock classes only.
|
||||
int trrep::client_context::replay(
|
||||
|
@ -2,10 +2,44 @@
|
||||
// Copyright (C) 2018 Codership Oy <info@codership.com>
|
||||
//
|
||||
|
||||
/*! \file client_context.hpp
|
||||
*
|
||||
* Client Context
|
||||
* ==============
|
||||
*
|
||||
* This file provides abstraction for integrating DBMS client
|
||||
* with replication system.
|
||||
*
|
||||
* Client Modes
|
||||
* ============
|
||||
*
|
||||
* Local
|
||||
* -----
|
||||
*
|
||||
* Replicating
|
||||
* -----------
|
||||
*
|
||||
* Applier
|
||||
* --------
|
||||
*
|
||||
* Client State
|
||||
* ============
|
||||
*
|
||||
* Client state is mainly relevant for the operation if the Server
|
||||
* supports synchronous rollback mode only. In this case the transactions
|
||||
* of the the idle clients (controls is in application which is using the
|
||||
* DBMS system) which encounter Brute Force Abort (BFA) must be rolled
|
||||
* back either by applier or a background process. If the client
|
||||
* state is executing, the control is inside the DBMS system and
|
||||
* the rollback process should be performed by the client which
|
||||
* drives the transaction.
|
||||
*/
|
||||
|
||||
#ifndef TRREP_CLIENT_CONTEXT_HPP
|
||||
#define TRREP_CLIENT_CONTEXT_HPP
|
||||
|
||||
#include "server_context.hpp"
|
||||
#include "transaction_context.hpp"
|
||||
#include "mutex.hpp"
|
||||
#include "lock.hpp"
|
||||
#include "data.hpp"
|
||||
@ -36,51 +70,179 @@ namespace trrep
|
||||
wsrep_conn_id_t id_;
|
||||
};
|
||||
|
||||
/*! \class Client Context
|
||||
*
|
||||
* Client Contex abstract interface.
|
||||
*/
|
||||
class client_context
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Client mode enumeration.
|
||||
* \todo m_toi total order isolation mode
|
||||
*/
|
||||
enum mode
|
||||
{
|
||||
m_local, // Operates in local only mode, no replication
|
||||
m_replicating, // Generates write sets for replication
|
||||
m_applier // Applying write sets from provider
|
||||
/*! Operates in local only mode, no replication. */
|
||||
m_local,
|
||||
/*! Generates write sets for replication by the provider. */
|
||||
m_replicating,
|
||||
/*! Applies write sets from the provider. */
|
||||
m_applier
|
||||
};
|
||||
|
||||
/*!
|
||||
* Client state enumeration.
|
||||
*
|
||||
*/
|
||||
enum state
|
||||
{
|
||||
/*!
|
||||
* Client is idle, the control is in the application which
|
||||
* uses the DBMS system.
|
||||
*/
|
||||
s_idle,
|
||||
/*!
|
||||
* The control of the client processing is inside the DBMS
|
||||
* system.
|
||||
*/
|
||||
s_exec,
|
||||
/*!
|
||||
* The client session is terminating.
|
||||
*/
|
||||
s_quitting
|
||||
};
|
||||
|
||||
|
||||
virtual ~client_context() { }
|
||||
// Accessors
|
||||
|
||||
/*!
|
||||
* Get reference to the client mutex.
|
||||
*
|
||||
* \return Reference to the client mutex.
|
||||
*/
|
||||
trrep::mutex& mutex() { return mutex_; }
|
||||
|
||||
/*!
|
||||
* Get server context associated the the client session.
|
||||
*
|
||||
* \return Reference to server context.
|
||||
*/
|
||||
trrep::server_context& server_context() const
|
||||
{ return server_context_; }
|
||||
|
||||
/*!
|
||||
* Get reference to the Provider which is associated
|
||||
* with the client context.
|
||||
*
|
||||
* \return Reference to the provider.
|
||||
* \throw trrep::runtime_error if no providers are associated
|
||||
* with the client context.
|
||||
*/
|
||||
trrep::provider& provider() const;
|
||||
|
||||
/*!
|
||||
* Get Client identifier.
|
||||
*
|
||||
* \return Client Identifier
|
||||
*/
|
||||
client_id id() const { return id_; }
|
||||
|
||||
/*!
|
||||
* Get Client mode.
|
||||
*
|
||||
* \todo Enforce mutex protection if called from other threads.
|
||||
*
|
||||
* \return Client mode.
|
||||
*/
|
||||
enum mode mode() const { return mode_; }
|
||||
|
||||
/*!
|
||||
* Get Client state.
|
||||
*
|
||||
* \todo Enforce mutex protection if called from other threads.
|
||||
*
|
||||
* \return Client state
|
||||
*/
|
||||
enum state state() const { return state_; }
|
||||
|
||||
/*!
|
||||
* Virtual method to return true if the client operates
|
||||
* in two phase commit mode.
|
||||
*
|
||||
* \return True if two phase commit is required, false otherwise.
|
||||
*/
|
||||
virtual bool do_2pc() const = 0;
|
||||
//
|
||||
//
|
||||
//
|
||||
virtual void before_command() { }
|
||||
|
||||
virtual void after_command() { }
|
||||
/*!
|
||||
* Virtual method which should be called before the client
|
||||
* starts processing the command received from the application.
|
||||
* This method will wait until the possible synchronous
|
||||
* rollback for associated transaction has finished.
|
||||
* The method has a side effect of changing the client
|
||||
* context state to executing.
|
||||
*
|
||||
* If overridden, the implementation should call base
|
||||
* class method before any implementation specific operations.
|
||||
*
|
||||
* \return Zero in case of success, non-zero in case of the
|
||||
* associated transaction was BF aborted.
|
||||
*/
|
||||
virtual int before_command();
|
||||
|
||||
virtual int before_statement() { return 0; }
|
||||
/*!
|
||||
* Virtual method which should be called before returning
|
||||
* the control back to application which uses the DBMS system.
|
||||
* This method will check if the transaction associated to
|
||||
* the connection has been aborted. This method has a side effect
|
||||
* of changing the client state to idle.
|
||||
*
|
||||
* If overridden, the implementation should call base
|
||||
* class metods after any implementation specifict operations.
|
||||
*/
|
||||
virtual int after_command();
|
||||
|
||||
virtual int after_statement() { return 0; }
|
||||
/*!
|
||||
* Before statement execution operations.
|
||||
*
|
||||
* Check if server is synced and if dirty reads are allowed.
|
||||
*
|
||||
* If the method is overridden by the implementation, base class
|
||||
* method should be called before any implementation specifc
|
||||
* operations.
|
||||
*
|
||||
* \return Zero in case of success, non-zero if the statement
|
||||
* is not allowed to be executed due to read or write
|
||||
* isolation requirements.
|
||||
*/
|
||||
virtual int before_statement();
|
||||
|
||||
/*!
|
||||
* After statement execution operations.
|
||||
*
|
||||
* * Check for must_replay state
|
||||
* * Do rollback if requested
|
||||
*
|
||||
* If overridden by the implementation, base class method
|
||||
* should be called after any implementation specific operations.
|
||||
*/
|
||||
virtual int after_statement();
|
||||
|
||||
/*!
|
||||
* Append SR fragment to the transaction.
|
||||
*/
|
||||
virtual int append_fragment(trrep::transaction_context&,
|
||||
uint32_t, const trrep::data&)
|
||||
{ return 0; }
|
||||
|
||||
/*!
|
||||
* Commit the transaction.
|
||||
*/
|
||||
virtual int commit(trrep::transaction_context&) = 0;
|
||||
|
||||
/*!
|
||||
* Rollback the transaction.
|
||||
*/
|
||||
virtual int rollback(trrep::transaction_context&) = 0;
|
||||
|
||||
virtual void will_replay(trrep::transaction_context&) { }
|
||||
@ -114,9 +276,9 @@ namespace trrep
|
||||
abort();
|
||||
}
|
||||
protected:
|
||||
//
|
||||
// Client context constuctor
|
||||
//
|
||||
/*!
|
||||
* Client context constuctor
|
||||
*/
|
||||
client_context(trrep::mutex& mutex,
|
||||
trrep::server_context& server_context,
|
||||
const client_id& id,
|
||||
@ -126,6 +288,8 @@ namespace trrep
|
||||
, id_(id)
|
||||
, mode_(mode)
|
||||
, state_(s_idle)
|
||||
, transaction_(*this)
|
||||
, allow_dirty_reads_()
|
||||
{ }
|
||||
|
||||
private:
|
||||
@ -136,6 +300,12 @@ namespace trrep
|
||||
client_id id_;
|
||||
enum mode mode_;
|
||||
enum state state_;
|
||||
trrep::transaction_context transaction_;
|
||||
/*!
|
||||
* \todo This boolean should be converted to better read isolation
|
||||
* semantics.
|
||||
*/
|
||||
bool allow_dirty_reads_;
|
||||
};
|
||||
|
||||
|
||||
|
16
src/compiler.hpp
Normal file
16
src/compiler.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright (C) 2018 Codership Oy <info@codership.com>
|
||||
//
|
||||
|
||||
|
||||
/*! \file compiler.hpp
|
||||
*
|
||||
* Compiler specific options.
|
||||
*/
|
||||
|
||||
#define TRREP_UNUSED __attribute__((unused))
|
||||
#if __cplusplus >= 201103L
|
||||
#define TRREP_OVERRIDE override
|
||||
#else
|
||||
#define TRREP_OVERRIDE
|
||||
#endif // __cplusplus >= 201103L
|
@ -109,7 +109,8 @@ public:
|
||||
const std::string& name,
|
||||
const std::string& id,
|
||||
const std::string& address)
|
||||
: trrep::server_context(name, id, address, name + "_data",
|
||||
: trrep::server_context(mutex_,
|
||||
name, id, address, name + "_data",
|
||||
trrep::server_context::rm_async)
|
||||
, simulator_(simulator)
|
||||
, mutex_()
|
||||
@ -179,6 +180,7 @@ public:
|
||||
cond_.notify_all();
|
||||
}
|
||||
|
||||
bool sst_before_init() const override { return false; }
|
||||
std::string on_sst_request()
|
||||
{
|
||||
return id();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "mock_client_context.hpp"
|
||||
#include "mock_provider.hpp"
|
||||
|
||||
#include "compiler.hpp"
|
||||
|
||||
namespace trrep
|
||||
{
|
||||
@ -18,7 +19,8 @@ namespace trrep
|
||||
mock_server_context(const std::string& name,
|
||||
const std::string& id,
|
||||
enum trrep::server_context::rollback_mode rollback_mode)
|
||||
: trrep::server_context(name, id, "", "./", rollback_mode)
|
||||
: trrep::server_context(mutex_, name, id, "", "./", rollback_mode)
|
||||
, mutex_()
|
||||
, provider_()
|
||||
, last_client_id_(0)
|
||||
{ }
|
||||
@ -30,19 +32,21 @@ namespace trrep
|
||||
trrep::client_context::m_local);
|
||||
}
|
||||
|
||||
void on_connect() { }
|
||||
void wait_until_connected() { }
|
||||
void on_view(const trrep::view&) { }
|
||||
void on_sync() { }
|
||||
std::string on_sst_request() { return ""; }
|
||||
void on_connect() TRREP_OVERRIDE { }
|
||||
void wait_until_connected() TRREP_OVERRIDE { }
|
||||
void on_view(const trrep::view&) TRREP_OVERRIDE { }
|
||||
void on_sync() TRREP_OVERRIDE { }
|
||||
bool sst_before_init() const TRREP_OVERRIDE { return false; }
|
||||
std::string on_sst_request() TRREP_OVERRIDE { return ""; }
|
||||
void on_sst_donate_request(const std::string&,
|
||||
const wsrep_gtid_t&,
|
||||
bool) { }
|
||||
void sst_received(const wsrep_gtid_t&) { }
|
||||
bool) TRREP_OVERRIDE { }
|
||||
void sst_received(const wsrep_gtid_t&) TRREP_OVERRIDE { }
|
||||
// void on_apply(trrep::transaction_context&) { }
|
||||
// void on_commit(trrep::transaction_context&) { }
|
||||
|
||||
private:
|
||||
trrep::default_mutex mutex_;
|
||||
mutable trrep::mock_provider provider_;
|
||||
unsigned long long last_client_id_;
|
||||
};
|
||||
|
@ -51,13 +51,22 @@
|
||||
* In asynchronous mode the BFA victim transaction is just marked
|
||||
* to be aborted or in case of fully optimistic concurrency control,
|
||||
* the conflict is detected at commit.
|
||||
*
|
||||
* SST
|
||||
* ===
|
||||
*
|
||||
* Depending on SST type (physical or logical), the server storage
|
||||
* engine initialization must be done before or after SST happens.
|
||||
* In case of physical SST method (typically rsync, filesystem snapshot)
|
||||
* the SST happens before the storage engine is initialized, in case
|
||||
* of logical backup typically after the storage engine initialization.
|
||||
*/
|
||||
|
||||
#ifndef TRREP_SERVER_CONTEXT_HPP
|
||||
#define TRREP_SERVER_CONTEXT_HPP
|
||||
|
||||
#include "exception.hpp"
|
||||
|
||||
#include "mutex.hpp"
|
||||
#include "wsrep_api.h"
|
||||
|
||||
#include <string>
|
||||
@ -78,9 +87,57 @@ namespace trrep
|
||||
class server_context
|
||||
{
|
||||
public:
|
||||
|
||||
/*! Rollback Mode enumeration
|
||||
/*!
|
||||
* Server state enumeration.
|
||||
*
|
||||
* \todo Fix UML generation
|
||||
*
|
||||
* Server state diagram if the sst_before_init() returns false.
|
||||
*
|
||||
* [*] --> disconnected
|
||||
* disconnected --> initializing
|
||||
* initializing --> initialized
|
||||
* initialized --> connected
|
||||
* connected --> joiner
|
||||
* joiner --> joined
|
||||
* joined --> synced
|
||||
* synced --> donor
|
||||
* donor --> joined
|
||||
*
|
||||
* Server state diagram if the sst_before_init() returns true.
|
||||
*
|
||||
* [*] --> disconnected
|
||||
* disconnected --> connected
|
||||
* connected --> joiner
|
||||
* joiner --> initializing
|
||||
* initializing --> initialized
|
||||
* initialized --> joined
|
||||
* joined --> synced
|
||||
* synced --> donor
|
||||
* donor --> joined
|
||||
*/
|
||||
enum state
|
||||
{
|
||||
/*! Server is in disconnected state. */
|
||||
s_disconnected,
|
||||
/*! Server is initializing */
|
||||
s_initializing,
|
||||
/*! Server has been initialized */
|
||||
s_initialized,
|
||||
/*! Server is connected to the cluster */
|
||||
s_connected,
|
||||
/*! Server is receiving SST */
|
||||
s_joiner,
|
||||
/*! Server has received SST succesfully but has not synced
|
||||
with rest of the cluster yet. */
|
||||
s_joined,
|
||||
/*! Server is donating state snapshot transfer */
|
||||
s_donor,
|
||||
/*! Server has synced with the cluster */
|
||||
s_synced
|
||||
};
|
||||
/*!
|
||||
* Rollback Mode enumeration
|
||||
*/
|
||||
enum rollback_mode
|
||||
{
|
||||
@ -90,29 +147,6 @@ namespace trrep
|
||||
rm_sync
|
||||
};
|
||||
|
||||
/*! Server Context constructor
|
||||
*
|
||||
* \param name Human Readable Server Name.
|
||||
* \param id Server Identifier String, UUID or some unique
|
||||
* identifier.
|
||||
* \param address Server address in form of IPv4 address, IPv6 address
|
||||
* or hostname.
|
||||
* \param working_dir Working directory for replication specific
|
||||
* data files.
|
||||
* \param rollback_mode Rollback mode which server operates on.
|
||||
*/
|
||||
server_context(const std::string& name,
|
||||
const std::string& id,
|
||||
const std::string& address,
|
||||
const std::string& working_dir,
|
||||
enum rollback_mode rollback_mode)
|
||||
: provider_()
|
||||
, name_(name)
|
||||
, id_(id)
|
||||
, address_(address)
|
||||
, working_dir_(working_dir)
|
||||
, rollback_mode_(rollback_mode)
|
||||
{ }
|
||||
|
||||
virtual ~server_context();
|
||||
/*!
|
||||
@ -136,6 +170,13 @@ namespace trrep
|
||||
*/
|
||||
const std::string& address() const { return address_; }
|
||||
|
||||
/*!
|
||||
* Get the rollback mode which server is operating in.
|
||||
*
|
||||
* \return Rollback mode.
|
||||
*/
|
||||
enum rollback_mode rollback_mode() const { return rollback_mode_; }
|
||||
|
||||
/*!
|
||||
* Create client context which acts only locally, i.e. does
|
||||
* not participate in replication. However, local client
|
||||
@ -207,6 +248,12 @@ namespace trrep
|
||||
*/
|
||||
virtual void on_sync() = 0;
|
||||
|
||||
/*!
|
||||
* Virtual method to return true if the configured SST
|
||||
* method requires SST to be performed before DBMS storage
|
||||
* engine initialization, false otherwise.
|
||||
*/
|
||||
virtual bool sst_before_init() const = 0;
|
||||
/*!
|
||||
* Virtual method which will be called on *joiner* when the provider
|
||||
* requests the SST request information. This method should
|
||||
@ -275,11 +322,40 @@ namespace trrep
|
||||
virtual bool statement_allowed_for_streaming(
|
||||
const trrep::client_context& client_context,
|
||||
const trrep::transaction_context& transaction_context) const;
|
||||
protected:
|
||||
/*! Server Context constructor
|
||||
*
|
||||
* \param mutex Mutex provided by the DBMS implementation.
|
||||
* \param name Human Readable Server Name.
|
||||
* \param id Server Identifier String, UUID or some unique
|
||||
* identifier.
|
||||
* \param address Server address in form of IPv4 address, IPv6 address
|
||||
* or hostname.
|
||||
* \param working_dir Working directory for replication specific
|
||||
* data files.
|
||||
* \param rollback_mode Rollback mode which server operates on.
|
||||
*/
|
||||
server_context(trrep::mutex& mutex,
|
||||
const std::string& name,
|
||||
const std::string& id,
|
||||
const std::string& address,
|
||||
const std::string& working_dir,
|
||||
enum rollback_mode rollback_mode)
|
||||
: mutex_(mutex)
|
||||
, provider_()
|
||||
, name_(name)
|
||||
, id_(id)
|
||||
, address_(address)
|
||||
, working_dir_(working_dir)
|
||||
, rollback_mode_(rollback_mode)
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
||||
server_context(const server_context&);
|
||||
server_context& operator=(const server_context&);
|
||||
|
||||
trrep::mutex& mutex_;
|
||||
trrep::provider* provider_;
|
||||
std::string name_;
|
||||
std::string id_;
|
||||
|
Reference in New Issue
Block a user