1
0
mirror of https://github.com/codership/wsrep-lib.git synced 2025-07-28 20:02:00 +03:00

added new transaction state: s_waiting_for_replayers

to make it posisble to diagnose from outside, if potential
BF victim transaction is blocked in replayer wait loop (before entering commit phase).
Also, added new forced state change to s_must_abort, if before_rollback() is used
for a transaction in s_committing state. Such situation can happen, if BF abort happens
for a victim, which has passed certification and moved to commit phase before the BF aborting happens.
This commit is contained in:
sjaakola
2021-10-01 12:11:29 +03:00
parent 6fd1fdf690
commit 8c7a003761
2 changed files with 32 additions and 18 deletions

View File

@ -58,6 +58,7 @@ namespace wsrep
s_aborting,
s_aborted,
s_must_replay,
s_waiting_for_replayers,
s_replaying
};
static const int n_states = s_replaying + 1;
@ -299,6 +300,7 @@ namespace wsrep
case wsrep::transaction::s_aborting: return "aborting";
case wsrep::transaction::s_aborted: return "aborted";
case wsrep::transaction::s_must_replay: return "must_replay";
case wsrep::transaction::s_waiting_for_replayers: return "waiting_for_replayers";
case wsrep::transaction::s_replaying: return "replaying";
}
return "unknown";

View File

@ -660,6 +660,7 @@ int wsrep::transaction::before_rollback()
state() == s_preparing ||
state() == s_prepared ||
state() == s_must_abort ||
state() == s_committing ||
// Background rollbacker or rollback initiated from SE
state() == s_aborting ||
state() == s_cert_failed ||
@ -672,6 +673,15 @@ int wsrep::transaction::before_rollback()
{
client_service_.debug_sync("wsrep_before_SR_rollback");
}
/* this state change was added to support BF aborting
at later state (before prepare), where victim has certified
successfully, and state has already
propagated to committing phase
*/
if (state() == s_committing) {
state(lock, s_must_abort);
}
switch (state())
{
case s_preparing:
@ -984,6 +994,7 @@ bool wsrep::transaction::bf_abort(
case s_preparing:
case s_prepared:
case s_certifying:
case s_waiting_for_replayers:
case s_committing:
{
wsrep::seqno victim_seqno;
@ -1306,22 +1317,22 @@ void wsrep::transaction::state(
next_state == s_aborting);
static const char allowed[n_states][n_states] =
{ /* ex pg pd ce co oc ct cf ma ab ad mr re */
{ 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, /* ex */
{ 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0}, /* pg */
{ 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0}, /* pd */
{ 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0}, /* ce */
{ 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0}, /* co */
{ 0, 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, 0}, /* ct */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, /* cf */
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0}, /* ma */
{ 0, 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, 0}, /* ad */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* mr */
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0} /* re */
{ /* ex pg pd ce co oc ct cf ma ab ad mr wr re */
{ 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0}, /* ex */
{ 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0}, /* pg */
{ 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0}, /* pd */
{ 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0}, /* ce */
{ 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0}, /* co */
{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, /* oc */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* ct */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, /* cf */
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, /* ma */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, /* ab */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* ad */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* mr */
{ 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1}, /* wr */
{ 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0} /* re */
};
if (!allowed[state_][next_state])
{
wsrep::log_debug() << "unallowed state transition for transaction "
@ -1681,6 +1692,7 @@ int wsrep::transaction::certify_commit(
{
assert(lock.owns_lock());
assert(active());
state(lock, s_waiting_for_replayers);
client_service_.wait_for_replayers(lock);
assert(lock.owns_lock());