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:
@ -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());
|
||||||
|
Reference in New Issue
Block a user