mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-30 07:23:07 +03:00
Split client_context::after_command() into two stages, before
sending result to client and after the result was sent. Added s_result state to client_context states.
This commit is contained in:
@ -120,6 +120,10 @@ namespace trrep
|
||||
* system.
|
||||
*/
|
||||
s_exec,
|
||||
/*!
|
||||
* Client handler is sending result to client.
|
||||
*/
|
||||
s_result,
|
||||
/*!
|
||||
* The client session is terminating.
|
||||
*/
|
||||
@ -136,32 +140,40 @@ namespace trrep
|
||||
}
|
||||
|
||||
/*!
|
||||
* Virtual method which should be called before the client
|
||||
* 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();
|
||||
int before_command();
|
||||
|
||||
/*!
|
||||
* Virtual method which should be called before returning
|
||||
* 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.
|
||||
* the connection has been aborted. Rollback is performed
|
||||
* if needed.
|
||||
*/
|
||||
virtual void after_command();
|
||||
void after_command_before_result();
|
||||
|
||||
/*!
|
||||
* Method which should be called after returning the
|
||||
* control back to application which uses the DBMS system.
|
||||
* The method will do the check if the transaction associated
|
||||
* to the connection has been aborted. If so, rollback is
|
||||
* performed and the transaction is left to aborted state
|
||||
* so that the client will get appropriate error on next
|
||||
* command.
|
||||
*
|
||||
* This method has a side effect of changing state to
|
||||
* idle.
|
||||
*/
|
||||
void after_command_after_result();
|
||||
|
||||
/*!
|
||||
* Before statement execution operations.
|
||||
@ -176,7 +188,7 @@ namespace trrep
|
||||
* is not allowed to be executed due to read or write
|
||||
* isolation requirements.
|
||||
*/
|
||||
virtual int before_statement();
|
||||
int before_statement();
|
||||
|
||||
/*!
|
||||
* After statement execution operations.
|
||||
@ -187,7 +199,7 @@ namespace trrep
|
||||
* If overridden by the implementation, base class method
|
||||
* should be called after any implementation specific operations.
|
||||
*/
|
||||
virtual void after_statement();
|
||||
void after_statement();
|
||||
|
||||
int start_transaction()
|
||||
{
|
||||
|
@ -40,9 +40,10 @@ int trrep::client_context::before_command()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void trrep::client_context::after_command()
|
||||
void trrep::client_context::after_command_before_result()
|
||||
{
|
||||
trrep::unique_lock<trrep::mutex> lock(mutex_);
|
||||
assert(state() == s_exec);
|
||||
if (transaction_.active() &&
|
||||
transaction_.state() == trrep::transaction_context::s_must_abort)
|
||||
{
|
||||
@ -54,6 +55,26 @@ void trrep::client_context::after_command()
|
||||
assert(transaction_.state() == trrep::transaction_context::s_aborted);
|
||||
assert(current_error() != trrep::e_success);
|
||||
}
|
||||
state(lock, s_result);
|
||||
}
|
||||
|
||||
void trrep::client_context::after_command_after_result()
|
||||
{
|
||||
trrep::unique_lock<trrep::mutex> lock(mutex_);
|
||||
assert(state() == s_result);
|
||||
if (transaction_.active() &&
|
||||
transaction_.state() == trrep::transaction_context::s_must_abort)
|
||||
{
|
||||
// Note: Error is not overridden here as the result has already
|
||||
// been sent to client. The error should be set in before_command()
|
||||
// when the client issues next command.
|
||||
lock.unlock();
|
||||
rollback();
|
||||
transaction_.after_statement();
|
||||
lock.lock();
|
||||
assert(transaction_.state() == trrep::transaction_context::s_aborted);
|
||||
assert(current_error() != trrep::e_success);
|
||||
}
|
||||
state(lock, s_idle);
|
||||
}
|
||||
|
||||
@ -103,10 +124,11 @@ void trrep::client_context::state(
|
||||
assert(lock.owns_lock());
|
||||
static const char allowed[state_max_][state_max_] =
|
||||
{
|
||||
/* idle exec quit */
|
||||
{ 0, 1, 1}, /* idle */
|
||||
{ 1, 0, 1}, /* exec */
|
||||
{ 0, 0, 0}
|
||||
/* idle exec result quit */
|
||||
{ 0, 1, 0, 1}, /* idle */
|
||||
{ 0, 0, 1, 0}, /* exec */
|
||||
{ 1, 0, 0, 1}, /* result */
|
||||
{ 0, 0, 0, 0} /* quit */
|
||||
};
|
||||
if (allowed[state_][state])
|
||||
{
|
||||
|
@ -25,5 +25,6 @@ BOOST_AUTO_TEST_CASE(client_context_test_error_codes)
|
||||
trrep_mock::bf_abort_unordered(cc);
|
||||
|
||||
cc.after_statement();
|
||||
cc.after_command();
|
||||
cc.after_command_before_result();
|
||||
cc.after_command_after_result();
|
||||
}
|
||||
|
@ -392,7 +392,8 @@ private:
|
||||
}
|
||||
after_statement();
|
||||
}
|
||||
after_command();
|
||||
after_command_before_result();
|
||||
after_command_after_result();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,8 @@ int trrep::server_context::on_apply(
|
||||
if (not_replaying)
|
||||
{
|
||||
client_context.after_statement();
|
||||
client_context.after_command();
|
||||
client_context.after_command_before_result();
|
||||
client_context.after_command_after_result();
|
||||
}
|
||||
assert(ret ||
|
||||
txc.state() == trrep::transaction_context::s_committed);
|
||||
|
Reference in New Issue
Block a user