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

Fix BF abort one phase XA transactions

Assertion is_streaming() would trigger in transaction::before_commit()
if a one phase XA transaction was BF aborted at the right
time (because one phase XA transaction is not streaming yet at commit
time).
This commit is contained in:
Daniele Sciascia
2020-07-10 10:41:40 +02:00
parent 588166e183
commit 39e37d3a39

View File

@ -453,48 +453,22 @@ int wsrep::transaction::before_commit()
switch (client_state_.mode()) switch (client_state_.mode())
{ {
case wsrep::client_state::m_local: case wsrep::client_state::m_local:
if (is_xa()) if (state() == s_executing)
{
ret = 0;
if (state() == s_executing)
{
// XA COMMIT in one phase
// This optimization is not supported...
// fall back to prepare + commit
ret = before_prepare(lock) || after_prepare(lock);
}
else if (state() == s_must_abort)
{
assert(is_streaming());
client_service_.will_replay();
state(lock, s_must_replay);
ret = 1;
}
if (!ret)
{
assert(state() == s_prepared);
ret = certify_commit(lock);
assert((ret == 0 && state() == s_committing) ||
(state() == s_must_abort ||
state() == s_must_replay ||
state() == s_cert_failed ||
state() == s_prepared));
}
}
else if (state() == s_executing)
{ {
ret = before_prepare(lock) || after_prepare(lock); ret = before_prepare(lock) || after_prepare(lock);
assert((ret == 0 && state() == s_committing) assert((ret == 0 &&
(state() == s_committing || state() == s_prepared))
|| ||
(state() == s_must_abort || (state() == s_must_abort ||
state() == s_must_replay || state() == s_must_replay ||
state() == s_cert_failed || state() == s_cert_failed ||
state() == s_aborted)); state() == s_aborted));
} }
else if (state() != s_committing) else if (state() != s_committing && state() != s_prepared)
{ {
assert(state() == s_must_abort); assert(state() == s_must_abort);
if (certified()) if (certified() ||
(is_xa() && is_streaming()))
{ {
client_service_.will_replay(); client_service_.will_replay();
state(lock, s_must_replay); state(lock, s_must_replay);
@ -509,6 +483,18 @@ int wsrep::transaction::before_commit()
// 2PC commit, prepare was done before // 2PC commit, prepare was done before
ret = 0; ret = 0;
} }
if (ret == 0 && state() == s_prepared)
{
assert(state() == s_prepared);
ret = certify_commit(lock);
assert((ret == 0 && state() == s_committing) ||
(state() == s_must_abort ||
state() == s_must_replay ||
state() == s_cert_failed ||
state() == s_prepared));
}
if (ret == 0) if (ret == 0)
{ {
assert(certified()); assert(certified());