diff options
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r-- | sql/sql_class.cc | 257 |
1 files changed, 0 insertions, 257 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c0c89ee59b3..c77c8a1a05a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5641,263 +5641,6 @@ void THD::mark_transaction_to_rollback(bool all) is_fatal_sub_stmt_error= true; transaction_rollback_request= all; } -/*************************************************************************** - Handling of XA id cacheing -***************************************************************************/ -class XID_cache_element -{ - /* - m_state is used to prevent elements from being deleted while XA RECOVER - iterates xid cache and to prevent recovered elments from being acquired by - multiple threads. - - bits 1..29 are reference counter - bit 30 is RECOVERED flag - bit 31 is ACQUIRED flag (thread owns this xid) - bit 32 is unused - - Newly allocated and deleted elements have m_state set to 0. - - On lock() m_state is atomically incremented. It also creates load-ACQUIRE - memory barrier to make sure m_state is actually updated before furhter - memory accesses. Attempting to lock an element that has neither ACQUIRED - nor RECOVERED flag set returns failure and further accesses to element - memory are forbidden. - - On unlock() m_state is decremented. It also creates store-RELEASE memory - barrier to make sure m_state is actually updated after preceding memory - accesses. - - ACQUIRED flag is set when thread registers it's xid or when thread acquires - recovered xid. - - RECOVERED flag is set for elements found during crash recovery. - - ACQUIRED and RECOVERED flags are cleared before element is deleted from - hash in a spin loop, after last reference is released. - */ - std::atomic<int32_t> m_state; -public: - static const int32 ACQUIRED= 1 << 30; - static const int32 RECOVERED= 1 << 29; - XID_STATE *m_xid_state; - bool is_set(int32_t flag) - { return m_state.load(std::memory_order_relaxed) & flag; } - void set(int32_t flag) - { - DBUG_ASSERT(!is_set(ACQUIRED | RECOVERED)); - m_state.fetch_add(flag, std::memory_order_relaxed); - } - bool lock() - { - int32_t old= m_state.fetch_add(1, std::memory_order_acquire); - if (old & (ACQUIRED | RECOVERED)) - return true; - unlock(); - return false; - } - void unlock() - { m_state.fetch_sub(1, std::memory_order_release); } - void mark_uninitialized() - { - int32_t old= ACQUIRED; - while (!m_state.compare_exchange_weak(old, 0, - std::memory_order_relaxed, - std::memory_order_relaxed)) - { - old&= ACQUIRED | RECOVERED; - (void) LF_BACKOFF(); - } - } - bool acquire_recovered() - { - int32_t old= RECOVERED; - while (!m_state.compare_exchange_weak(old, ACQUIRED | RECOVERED, - std::memory_order_relaxed, - std::memory_order_relaxed)) - { - if (!(old & RECOVERED) || (old & ACQUIRED)) - return false; - old= RECOVERED; - (void) LF_BACKOFF(); - } - return true; - } - static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)), - XID_cache_element *element, - XID_STATE *xid_state) - { - DBUG_ASSERT(!element->is_set(ACQUIRED | RECOVERED)); - element->m_xid_state= xid_state; - xid_state->xid_cache_element= element; - } - static void lf_alloc_constructor(uchar *ptr) - { - XID_cache_element *element= (XID_cache_element*) (ptr + LF_HASH_OVERHEAD); - element->m_state= 0; - } - static void lf_alloc_destructor(uchar *ptr) - { - XID_cache_element *element= (XID_cache_element*) (ptr + LF_HASH_OVERHEAD); - DBUG_ASSERT(!element->is_set(ACQUIRED)); - if (element->is_set(RECOVERED)) - my_free(element->m_xid_state); - } - static uchar *key(const XID_cache_element *element, size_t *length, - my_bool not_used __attribute__((unused))) - { - *length= element->m_xid_state->xid.key_length(); - return element->m_xid_state->xid.key(); - } -}; - - -static LF_HASH xid_cache; -static bool xid_cache_inited; - - -bool THD::fix_xid_hash_pins() -{ - if (!xid_hash_pins) - xid_hash_pins= lf_hash_get_pins(&xid_cache); - return !xid_hash_pins; -} - - -void xid_cache_init() -{ - xid_cache_inited= true; - lf_hash_init(&xid_cache, sizeof(XID_cache_element), LF_HASH_UNIQUE, 0, 0, - (my_hash_get_key) XID_cache_element::key, &my_charset_bin); - xid_cache.alloc.constructor= XID_cache_element::lf_alloc_constructor; - xid_cache.alloc.destructor= XID_cache_element::lf_alloc_destructor; - xid_cache.initializer= - (lf_hash_initializer) XID_cache_element::lf_hash_initializer; -} - - -void xid_cache_free() -{ - if (xid_cache_inited) - { - lf_hash_destroy(&xid_cache); - xid_cache_inited= false; - } -} - - -/** - Find recovered XA transaction by XID. -*/ - -XID_STATE *xid_cache_search(THD *thd, XID *xid) -{ - XID_STATE *xs= 0; - DBUG_ASSERT(thd->xid_hash_pins); - XID_cache_element *element= - (XID_cache_element*) lf_hash_search(&xid_cache, thd->xid_hash_pins, - xid->key(), xid->key_length()); - if (element) - { - if (element->acquire_recovered()) - xs= element->m_xid_state; - lf_hash_search_unpin(thd->xid_hash_pins); - DEBUG_SYNC(thd, "xa_after_search"); - } - return xs; -} - - -bool xid_cache_insert(XID *xid, enum xa_states xa_state) -{ - XID_STATE *xs; - LF_PINS *pins; - int res= 1; - - if (!(pins= lf_hash_get_pins(&xid_cache))) - return true; - - if ((xs= (XID_STATE*) my_malloc(sizeof(*xs), MYF(MY_WME)))) - { - xs->xa_state=xa_state; - xs->xid.set(xid); - xs->rm_error=0; - - if ((res= lf_hash_insert(&xid_cache, pins, xs))) - my_free(xs); - else - xs->xid_cache_element->set(XID_cache_element::RECOVERED); - if (res == 1) - res= 0; - } - lf_hash_put_pins(pins); - return res; -} - - -bool xid_cache_insert(THD *thd, XID_STATE *xid_state) -{ - if (thd->fix_xid_hash_pins()) - return true; - - int res= lf_hash_insert(&xid_cache, thd->xid_hash_pins, xid_state); - switch (res) - { - case 0: - xid_state->xid_cache_element->set(XID_cache_element::ACQUIRED); - break; - case 1: - my_error(ER_XAER_DUPID, MYF(0)); - /* fall through */ - default: - xid_state->xid_cache_element= 0; - } - return res; -} - - -void xid_cache_delete(THD *thd, XID_STATE *xid_state) -{ - if (xid_state->xid_cache_element) - { - bool recovered= xid_state->xid_cache_element->is_set(XID_cache_element::RECOVERED); - DBUG_ASSERT(thd->xid_hash_pins); - xid_state->xid_cache_element->mark_uninitialized(); - lf_hash_delete(&xid_cache, thd->xid_hash_pins, - xid_state->xid.key(), xid_state->xid.key_length()); - xid_state->xid_cache_element= 0; - if (recovered) - my_free(xid_state); - } -} - - -struct xid_cache_iterate_arg -{ - my_hash_walk_action action; - void *argument; -}; - -static my_bool xid_cache_iterate_callback(XID_cache_element *element, - xid_cache_iterate_arg *arg) -{ - my_bool res= FALSE; - if (element->lock()) - { - res= arg->action(element->m_xid_state, arg->argument); - element->unlock(); - } - return res; -} - -int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) -{ - xid_cache_iterate_arg argument= { action, arg }; - return thd->fix_xid_hash_pins() ? -1 : - lf_hash_iterate(&xid_cache, thd->xid_hash_pins, - (my_hash_walk_action) xid_cache_iterate_callback, - &argument); -} /** |