summaryrefslogtreecommitdiff
path: root/sql/xa.cc
diff options
context:
space:
mode:
authorSergey Vojtovich <svoj@mariadb.org>2019-04-22 00:04:14 +0400
committerSergey Vojtovich <svoj@mariadb.org>2019-04-25 15:06:40 +0400
commit1599825ffc2c942f8b63274a9556b425229375c7 (patch)
tree17a95099e6317b796f5715a3462b7a271bf55fa1 /sql/xa.cc
parent210855ce5d6803f41d672d75be3334726f52a9df (diff)
downloadmariadb-git-1599825ffc2c942f8b63274a9556b425229375c7.tar.gz
trans_xa_detach() framework
Part of MDEV-7974 - backport fix for mysql bug#12161 (XA and binlog)
Diffstat (limited to 'sql/xa.cc')
-rw-r--r--sql/xa.cc72
1 files changed, 51 insertions, 21 deletions
diff --git a/sql/xa.cc b/sql/xa.cc
index 64efa06253a..c4b983aa4f5 100644
--- a/sql/xa.cc
+++ b/sql/xa.cc
@@ -106,11 +106,16 @@ public:
(void) LF_BACKOFF();
}
}
+ void acquired_to_recovered()
+ {
+ m_state.fetch_or(RECOVERED, std::memory_order_relaxed);
+ m_state.fetch_and(~ACQUIRED, std::memory_order_release);
+ }
bool acquire_recovered()
{
int32_t old= RECOVERED;
while (!m_state.compare_exchange_weak(old, ACQUIRED | RECOVERED,
- std::memory_order_relaxed,
+ std::memory_order_acquire,
std::memory_order_relaxed))
{
if (!(old & RECOVERED) || (old & ACQUIRED))
@@ -303,11 +308,9 @@ static void xid_cache_delete(THD *thd, XID_cache_element *&element)
void xid_cache_delete(THD *thd, XID_STATE *xid_state)
{
- if (xid_state->xid_cache_element)
- {
- xid_cache_delete(thd, xid_state->xid_cache_element);
- xid_state->xid_cache_element= 0;
- }
+ DBUG_ASSERT(xid_state->is_explicit_XA());
+ xid_cache_delete(thd, xid_state->xid_cache_element);
+ xid_state->xid_cache_element= 0;
}
@@ -379,12 +382,24 @@ static bool xa_trans_rolled_back(XID_cache_element *element)
static bool xa_trans_force_rollback(THD *thd)
{
+ bool rc= false;
+
if (ha_rollback_trans(thd, true))
{
my_error(ER_XAER_RMERR, MYF(0));
- return true;
+ rc= true;
}
- return false;
+
+ thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.reset();
+ thd->server_status&=
+ ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
+ DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
+ xid_cache_delete(thd, &thd->transaction.xid_state);
+
+ trans_track_end_trx(thd);
+
+ return rc;
}
@@ -532,7 +547,7 @@ bool trans_xa_commit(THD *thd)
if (xa_trans_rolled_back(thd->transaction.xid_state.xid_cache_element))
{
xa_trans_force_rollback(thd);
- res= thd->is_error();
+ DBUG_RETURN(thd->is_error());
}
else if (thd->transaction.xid_state.xid_cache_element->xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
@@ -601,7 +616,6 @@ bool trans_xa_commit(THD *thd)
bool trans_xa_rollback(THD *thd)
{
- bool res= TRUE;
DBUG_ENTER("trans_xa_rollback");
if (!thd->transaction.xid_state.is_explicit_XA() ||
@@ -629,19 +643,35 @@ bool trans_xa_rollback(THD *thd)
thd->transaction.xid_state.er_xaer_rmfail();
DBUG_RETURN(TRUE);
}
+ DBUG_RETURN(xa_trans_force_rollback(thd));
+}
- res= xa_trans_force_rollback(thd);
-
- thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.reset();
- thd->server_status&=
- ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY);
- DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS"));
- xid_cache_delete(thd, &thd->transaction.xid_state);
-
- trans_track_end_trx(thd);
- DBUG_RETURN(res);
+bool trans_xa_detach(THD *thd)
+{
+ DBUG_ASSERT(thd->transaction.xid_state.is_explicit_XA());
+#if 1
+ return xa_trans_force_rollback(thd);
+#else
+ if (thd->transaction.xid_state.xid_cache_element->xa_state != XA_PREPARED)
+ return xa_trans_force_rollback(thd);
+ thd->transaction.xid_state.xid_cache_element->acquired_to_recovered();
+ thd->transaction.xid_state.xid_cache_element= 0;
+ thd->transaction.cleanup();
+
+ Ha_trx_info *ha_info, *ha_info_next;
+ for (ha_info= thd->transaction.all.ha_list;
+ ha_info;
+ ha_info= ha_info_next)
+ {
+ ha_info_next= ha_info->next();
+ ha_info->reset(); /* keep it conveniently zero-filled */
+ }
+
+ thd->transaction.all.ha_list= 0;
+ thd->transaction.all.no_2pc= 0;
+ return false;
+#endif
}