mirror of
https://github.com/codership/wsrep-lib.git
synced 2025-07-28 20:02:00 +03:00
Allow must_abort - cert_failed transition.
If the BF abort happens during provider certify call which returns certification failure, the cert_failed state should take precedence.
This commit is contained in:
@ -412,7 +412,7 @@ public:
|
||||
wsrep::client_context::store_globals();
|
||||
}
|
||||
private:
|
||||
void debug_sync(wsrep::unique_lock<wsrep::mutex>&, const char*) override { }
|
||||
void debug_sync(const char*) override { }
|
||||
void debug_suicide(const char*) override { }
|
||||
void on_error(enum wsrep::client_error) override { }
|
||||
|
||||
|
@ -522,7 +522,7 @@ namespace wsrep
|
||||
/*!
|
||||
* Enter debug synchronization point.
|
||||
*/
|
||||
virtual void debug_sync(wsrep::unique_lock<wsrep::mutex>&, const char*) = 0;
|
||||
virtual void debug_sync(const char*) = 0;
|
||||
|
||||
/*!
|
||||
*
|
||||
|
@ -646,7 +646,7 @@ void wsrep::transaction_context::state(
|
||||
{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, /* oc */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* ct */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, /* cf */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0}, /* ma */
|
||||
{ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0}, /* ma */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, /* ab */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* ad */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* mr */
|
||||
@ -778,6 +778,7 @@ int wsrep::transaction_context::certify_commit(
|
||||
state(lock, s_certifying);
|
||||
|
||||
flags(flags() | wsrep::provider::flag::commit);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (client_context_.prepare_data_for_replication(*this))
|
||||
@ -797,16 +798,17 @@ int wsrep::transaction_context::certify_commit(
|
||||
return 1;
|
||||
}
|
||||
|
||||
client_context_.debug_sync("wsrep_before_certification");
|
||||
enum wsrep::provider::status
|
||||
cert_ret(provider_.certify(client_context_.id().get(),
|
||||
ws_handle_,
|
||||
flags(),
|
||||
ws_meta_));
|
||||
client_context_.debug_sync("wsrep_after_certification");
|
||||
|
||||
lock.lock();
|
||||
|
||||
assert(state() == s_certifying || state() == s_must_abort);
|
||||
client_context_.debug_sync(lock, "wsrep_after_certification");
|
||||
|
||||
int ret(1);
|
||||
switch (cert_ret)
|
||||
|
@ -110,20 +110,20 @@ namespace wsrep
|
||||
bool killed() const WSREP_OVERRIDE { return killed_before_certify_; }
|
||||
void abort() WSREP_OVERRIDE { ++aborts_; }
|
||||
void store_globals() WSREP_OVERRIDE { }
|
||||
void debug_sync(wsrep::unique_lock<wsrep::mutex>& lock,
|
||||
const char* sync_point) WSREP_OVERRIDE
|
||||
void debug_sync(const char* sync_point) WSREP_OVERRIDE
|
||||
{
|
||||
lock.unlock();
|
||||
if (sync_point_enabled_ == sync_point)
|
||||
{
|
||||
switch (sync_point_action_)
|
||||
{
|
||||
case spa_bf_abort:
|
||||
case spa_bf_abort_unordered:
|
||||
wsrep_test::bf_abort_unordered(*this);
|
||||
break;
|
||||
case spa_bf_abort_ordered:
|
||||
wsrep_test::bf_abort_ordered(*this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lock.lock();
|
||||
}
|
||||
void debug_suicide(const char*) WSREP_OVERRIDE
|
||||
{
|
||||
@ -146,7 +146,8 @@ namespace wsrep
|
||||
std::string sync_point_enabled_;
|
||||
enum sync_point_action
|
||||
{
|
||||
spa_bf_abort
|
||||
spa_bf_abort_unordered,
|
||||
spa_bf_abort_ordered
|
||||
} sync_point_action_;
|
||||
size_t bytes_generated_;
|
||||
private:
|
||||
|
@ -22,10 +22,10 @@ namespace wsrep
|
||||
|
||||
fake_provider(wsrep::server_context& server_context)
|
||||
: provider(server_context)
|
||||
, certify_status_()
|
||||
, commit_order_enter_status_()
|
||||
, commit_order_leave_status_()
|
||||
, release_status_()
|
||||
, certify_result_()
|
||||
, commit_order_enter_result_()
|
||||
, commit_order_leave_result_()
|
||||
, release_result_()
|
||||
, group_id_("1")
|
||||
, server_id_("1")
|
||||
, group_seqno_(0)
|
||||
@ -57,11 +57,11 @@ namespace wsrep
|
||||
<< "client: " << client_id.get()
|
||||
<< " flags: " << std::hex << flags
|
||||
<< std::dec
|
||||
<< " certify_status: " << certify_status_;
|
||||
<< " certify_status: " << certify_result_;
|
||||
|
||||
if (certify_status_)
|
||||
if (certify_result_)
|
||||
{
|
||||
return certify_status_;
|
||||
return certify_result_;
|
||||
}
|
||||
|
||||
++fragments_;
|
||||
@ -129,14 +129,14 @@ namespace wsrep
|
||||
enum wsrep::provider::status
|
||||
commit_order_enter(const wsrep::ws_handle&,
|
||||
const wsrep::ws_meta&)
|
||||
{ return commit_order_enter_status_; }
|
||||
{ return commit_order_enter_result_; }
|
||||
|
||||
int commit_order_leave(const wsrep::ws_handle&,
|
||||
const wsrep::ws_meta&)
|
||||
{ return commit_order_leave_status_;}
|
||||
{ return commit_order_leave_result_;}
|
||||
|
||||
int release(wsrep::ws_handle&)
|
||||
{ return release_status_; }
|
||||
{ return release_result_; }
|
||||
|
||||
int replay(wsrep::ws_handle&, void*) { ::abort(); /* not impl */}
|
||||
|
||||
@ -171,10 +171,10 @@ namespace wsrep
|
||||
}
|
||||
|
||||
// Parameters to control return value from the call
|
||||
enum wsrep::provider::status certify_status_;
|
||||
enum wsrep::provider::status commit_order_enter_status_;
|
||||
enum wsrep::provider::status commit_order_leave_status_;
|
||||
enum wsrep::provider::status release_status_;
|
||||
enum wsrep::provider::status certify_result_;
|
||||
enum wsrep::provider::status commit_order_enter_result_;
|
||||
enum wsrep::provider::status commit_order_leave_result_;
|
||||
enum wsrep::provider::status release_result_;
|
||||
|
||||
size_t start_fragments() const { return start_fragments_; }
|
||||
size_t fragments() const { return fragments_; }
|
||||
|
@ -350,6 +350,42 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(cc.replays() == 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Test a 1PC transaction which gets BF aborted simultaneously with
|
||||
// certification failure. BF abort should not succeed as the
|
||||
// transaction is going to roll back anyway. Certification failure
|
||||
// should not generate seqno for write set meta.
|
||||
//
|
||||
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
transaction_context_1pc_bf_before_unordered_cert_failure, T,
|
||||
replicating_fixtures, T)
|
||||
{
|
||||
wsrep::fake_server_context& sc(T::sc);
|
||||
wsrep::fake_client_context& cc(T::cc);
|
||||
const wsrep::transaction_context& tc(T::tc);
|
||||
|
||||
cc.start_transaction(1);
|
||||
BOOST_REQUIRE(tc.active());
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
cc.sync_point_enabled_ = "wsrep_before_certification";
|
||||
cc.sync_point_action_ = wsrep::fake_client_context::spa_bf_abort_unordered;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_certification_failed;
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_cert_failed);
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborting);
|
||||
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_aborted);
|
||||
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_error);
|
||||
BOOST_REQUIRE(tc.active() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(cc.current_error() == wsrep::e_deadlock_error);
|
||||
}
|
||||
|
||||
//
|
||||
// Test a 1PC transaction which gets "warning error" from certify call
|
||||
//
|
||||
@ -367,7 +403,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_warning;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_warning;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -375,7 +411,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -408,7 +444,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_transaction_missing;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_transaction_missing;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -416,7 +452,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -449,7 +485,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_size_exceeded;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_size_exceeded;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -457,7 +493,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -490,7 +526,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_connection_failed;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_connection_failed;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -498,7 +534,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -531,7 +567,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_not_allowed;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_not_allowed;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -539,7 +575,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -572,7 +608,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_fatal;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_fatal;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -580,7 +616,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -614,7 +650,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.id() == wsrep::transaction_id(1));
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::error_unknown;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_unknown;
|
||||
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
@ -622,7 +658,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.certified() == false);
|
||||
BOOST_REQUIRE(tc.ordered() == false);
|
||||
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
|
||||
// Rollback sequence
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
@ -643,7 +679,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
// after certify call
|
||||
//
|
||||
BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
transaction_context_1pc_bf_abort_after_certify_regain_lock, T,
|
||||
transaction_context_1pc_bf_abort_before_certify_regain_lock, T,
|
||||
replicating_fixtures, T)
|
||||
{
|
||||
// wsrep::fake_server_context& sc(T::sc);
|
||||
@ -657,6 +693,7 @@ BOOST_FIXTURE_TEST_CASE_TEMPLATE(
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
|
||||
cc.sync_point_enabled_ = "wsrep_after_certification";
|
||||
cc.sync_point_action_ = wsrep::fake_client_context::spa_bf_abort_ordered;
|
||||
// Run before commit
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||
@ -988,9 +1025,9 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_row_streaming_cert_fail_non_commit,
|
||||
BOOST_REQUIRE(cc.start_transaction(1) == 0);
|
||||
BOOST_REQUIRE(cc.after_row() == 0);
|
||||
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
|
||||
sc.provider().certify_status_ = wsrep::provider::error_certification_failed;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_certification_failed;
|
||||
BOOST_REQUIRE(cc.after_row() == 1);
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_success);
|
||||
@ -1008,10 +1045,10 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_row_streaming_cert_fail_commit,
|
||||
BOOST_REQUIRE(cc.start_transaction(1) == 0);
|
||||
BOOST_REQUIRE(cc.after_row() == 0);
|
||||
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 1);
|
||||
sc.provider().certify_status_ = wsrep::provider::error_certification_failed;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_certification_failed;
|
||||
BOOST_REQUIRE(cc.before_commit() == 1);
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_cert_failed);
|
||||
sc.provider().certify_status_ = wsrep::provider::success;
|
||||
sc.provider().certify_result_ = wsrep::provider::success;
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_error);
|
||||
@ -1141,7 +1178,7 @@ BOOST_FIXTURE_TEST_CASE(transaction_context_statement_streaming_cert_fail,
|
||||
BOOST_REQUIRE(cc.start_transaction(1) == 0);
|
||||
BOOST_REQUIRE(cc.after_row() == 0);
|
||||
BOOST_REQUIRE(tc.streaming_context_.fragments_certified() == 0);
|
||||
sc.provider().certify_status_ = wsrep::provider::error_certification_failed;
|
||||
sc.provider().certify_result_ = wsrep::provider::error_certification_failed;
|
||||
BOOST_REQUIRE(cc.after_statement() == wsrep::client_context::asr_error);
|
||||
BOOST_REQUIRE(cc.current_error() == wsrep::e_deadlock_error);
|
||||
BOOST_REQUIRE(sc.provider().fragments() == 0);
|
||||
|
@ -162,12 +162,12 @@ BOOST_FIXTURE_TEST_CASE(
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_executing);
|
||||
BOOST_REQUIRE(cc.before_prepare() == 0);
|
||||
BOOST_REQUIRE(cc.after_prepare() == 0);
|
||||
sc.provider().commit_order_enter_status_ = wsrep::provider::error_bf_abort;
|
||||
sc.provider().commit_order_enter_result_ = wsrep::provider::error_bf_abort;
|
||||
BOOST_REQUIRE(cc.before_commit());
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||
BOOST_REQUIRE(tc.certified() == true);
|
||||
BOOST_REQUIRE(tc.ordered() == true);
|
||||
sc.provider().commit_order_enter_status_ = wsrep::provider::success;
|
||||
sc.provider().commit_order_enter_result_ = wsrep::provider::success;
|
||||
BOOST_REQUIRE(cc.before_rollback() == 0);
|
||||
BOOST_REQUIRE(tc.state() == wsrep::transaction_context::s_must_replay);
|
||||
BOOST_REQUIRE(cc.after_rollback() == 0);
|
||||
|
Reference in New Issue
Block a user