diff --git a/src/transaction.cpp b/src/transaction.cpp index e7f0127..9e4f86b 100644 --- a/src/transaction.cpp +++ b/src/transaction.cpp @@ -373,7 +373,8 @@ int wsrep::transaction::before_commit() || (state() == s_must_abort || state() == s_must_replay || - state() == s_cert_failed)); + state() == s_cert_failed || + state() == s_aborted)); } else if (state() != s_committing) { diff --git a/test/transaction_test.cpp b/test/transaction_test.cpp index 5ad1d96..166ff99 100644 --- a/test/transaction_test.cpp +++ b/test/transaction_test.cpp @@ -1056,6 +1056,27 @@ BOOST_FIXTURE_TEST_CASE( BOOST_REQUIRE(sc.provider().commit_fragments() == 1); } +// +// Fragments are removed in before_prepare in running transaction context. +// In 1pc the before_prepare() is called from before_commit(). +// However, the BF abort may arrive during this removal and the +// client_service::remove_fragments() may roll back the transaction +// internally. This will cause the transaction to leave before_prepare() +// in aborted state. +// +BOOST_FIXTURE_TEST_CASE(transaction_streaming_1pc_bf_abort_during_fragment_removal, + streaming_client_fixture_row) +{ + BOOST_REQUIRE(cc.start_transaction(wsrep::transaction_id(1)) == 0); + BOOST_REQUIRE(cc.after_row() == 0); + BOOST_REQUIRE(tc.streaming_context().fragments_certified() == 1); + cc.bf_abort_during_fragment_removal_ = true; + BOOST_REQUIRE(cc.before_commit()); + BOOST_REQUIRE(tc.state() == wsrep::transaction::s_aborted); + BOOST_REQUIRE(cc.after_statement()); + BOOST_REQUIRE(tc.active() == false); +} + // // Test streaming rollback //