1
0
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:
Teemu Ollakka
2018-06-02 15:55:54 +03:00
parent c73e7c8f5d
commit 188bda1339
5 changed files with 59 additions and 22 deletions

View File

@ -120,6 +120,10 @@ namespace trrep
* system. * system.
*/ */
s_exec, s_exec,
/*!
* Client handler is sending result to client.
*/
s_result,
/*! /*!
* The client session is terminating. * 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. * starts processing the command received from the application.
* This method will wait until the possible synchronous * This method will wait until the possible synchronous
* rollback for associated transaction has finished. * rollback for associated transaction has finished.
* The method has a side effect of changing the client * The method has a side effect of changing the client
* context state to executing. * 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 * \return Zero in case of success, non-zero in case of the
* associated transaction was BF aborted. * 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. * the control back to application which uses the DBMS system.
* This method will check if the transaction associated to * This method will check if the transaction associated to
* the connection has been aborted. This method has a side effect * the connection has been aborted. Rollback is performed
* of changing the client state to idle. * if needed.
*
* If overridden, the implementation should call base
* class metods after any implementation specifict operations.
*/ */
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. * Before statement execution operations.
@ -176,7 +188,7 @@ namespace trrep
* is not allowed to be executed due to read or write * is not allowed to be executed due to read or write
* isolation requirements. * isolation requirements.
*/ */
virtual int before_statement(); int before_statement();
/*! /*!
* After statement execution operations. * After statement execution operations.
@ -187,7 +199,7 @@ namespace trrep
* If overridden by the implementation, base class method * If overridden by the implementation, base class method
* should be called after any implementation specific operations. * should be called after any implementation specific operations.
*/ */
virtual void after_statement(); void after_statement();
int start_transaction() int start_transaction()
{ {

View File

@ -40,9 +40,10 @@ int trrep::client_context::before_command()
return 0; return 0;
} }
void trrep::client_context::after_command() void trrep::client_context::after_command_before_result()
{ {
trrep::unique_lock<trrep::mutex> lock(mutex_); trrep::unique_lock<trrep::mutex> lock(mutex_);
assert(state() == s_exec);
if (transaction_.active() && if (transaction_.active() &&
transaction_.state() == trrep::transaction_context::s_must_abort) 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(transaction_.state() == trrep::transaction_context::s_aborted);
assert(current_error() != trrep::e_success); 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); state(lock, s_idle);
} }
@ -103,10 +124,11 @@ void trrep::client_context::state(
assert(lock.owns_lock()); assert(lock.owns_lock());
static const char allowed[state_max_][state_max_] = static const char allowed[state_max_][state_max_] =
{ {
/* idle exec quit */ /* idle exec result quit */
{ 0, 1, 1}, /* idle */ { 0, 1, 0, 1}, /* idle */
{ 1, 0, 1}, /* exec */ { 0, 0, 1, 0}, /* exec */
{ 0, 0, 0} { 1, 0, 0, 1}, /* result */
{ 0, 0, 0, 0} /* quit */
}; };
if (allowed[state_][state]) if (allowed[state_][state])
{ {

View File

@ -25,5 +25,6 @@ BOOST_AUTO_TEST_CASE(client_context_test_error_codes)
trrep_mock::bf_abort_unordered(cc); trrep_mock::bf_abort_unordered(cc);
cc.after_statement(); cc.after_statement();
cc.after_command(); cc.after_command_before_result();
cc.after_command_after_result();
} }

View File

@ -392,7 +392,8 @@ private:
} }
after_statement(); after_statement();
} }
after_command(); after_command_before_result();
after_command_after_result();
return err; return err;
} }

View File

@ -323,7 +323,8 @@ int trrep::server_context::on_apply(
if (not_replaying) if (not_replaying)
{ {
client_context.after_statement(); client_context.after_statement();
client_context.after_command(); client_context.after_command_before_result();
client_context.after_command_after_result();
} }
assert(ret || assert(ret ||
txc.state() == trrep::transaction_context::s_committed); txc.state() == trrep::transaction_context::s_committed);