19 #include "sql_array.h" 
   21 #include <mysqld_error.h> 
   22 #include <mysql/plugin.h> 
   26 #ifdef HAVE_PSI_INTERFACE 
   27 static PSI_mutex_key key_MDL_map_mutex;
 
   28 static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
 
   30 static PSI_mutex_info all_mdl_mutexes[]=
 
   32   { &key_MDL_map_mutex, 
"MDL_map::mutex", 0},
 
   33   { &key_MDL_wait_LOCK_wait_status, 
"MDL_wait::LOCK_wait_status", 0}
 
   36 static PSI_rwlock_key key_MDL_lock_rwlock;
 
   37 static PSI_rwlock_key key_MDL_context_LOCK_waiting_for;
 
   39 static PSI_rwlock_info all_mdl_rwlocks[]=
 
   41   { &key_MDL_lock_rwlock, 
"MDL_lock::rwlock", 0},
 
   42   { &key_MDL_context_LOCK_waiting_for, 
"MDL_context::LOCK_waiting_for", 0}
 
   45 static PSI_cond_key key_MDL_wait_COND_wait_status;
 
   47 static PSI_cond_info all_mdl_conds[]=
 
   49   { &key_MDL_wait_COND_wait_status, 
"MDL_context::COND_wait_status", 0}
 
   56 static void init_mdl_psi_keys(
void)
 
   60   count= array_elements(all_mdl_mutexes);
 
   63   count= array_elements(all_mdl_rwlocks);
 
   66   count= array_elements(all_mdl_conds);
 
   69   MDL_key::init_psi_keys();
 
   79 PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]=
 
   81   {0, 
"Waiting for global read lock", 0},
 
   82   {0, 
"Waiting for schema metadata lock", 0},
 
   83   {0, 
"Waiting for table metadata lock", 0},
 
   84   {0, 
"Waiting for stored function metadata lock", 0},
 
   85   {0, 
"Waiting for stored procedure metadata lock", 0},
 
   86   {0, 
"Waiting for trigger metadata lock", 0},
 
   87   {0, 
"Waiting for event metadata lock", 0},
 
   88   {0, 
"Waiting for commit lock", 0}
 
   91 #ifdef HAVE_PSI_INTERFACE 
   92 void MDL_key::init_psi_keys()
 
   98   count= array_elements(MDL_key::m_namespace_to_wait_state_name);
 
   99   for (i= 0; i<count; i++)
 
  102     info= & MDL_key::m_namespace_to_wait_state_name[
i];
 
  108 static bool mdl_initialized= 0;
 
  127                                   my_hash_value_type hash_value);
 
  129   my_hash_value_type get_key_hash(
const MDL_key *mdl_key)
 const 
  131     return my_calc_hash(&m_locks, mdl_key->ptr(), mdl_key->length());
 
  134   bool move_from_hash_to_lock_mutex(
MDL_lock *lock);
 
  164 ulong mdl_locks_hash_partitions;
 
  198     : m_start_node(start_node_arg),
 
  200       m_current_search_depth(0),
 
  201       m_found_deadlock(FALSE)
 
  208   MDL_context *get_victim()
 const { 
return m_victim; }
 
  214   void opt_change_victim_to(
MDL_context *new_victim);
 
  229   uint m_current_search_depth;
 
  231   bool m_found_deadlock;
 
  245   static const uint MAX_SEARCH_DEPTH= 32;
 
  263   m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
 
  264   if (m_found_deadlock)
 
  266     DBUG_ASSERT(! m_victim);
 
  267     opt_change_victim_to(node);
 
  269   return m_found_deadlock;
 
  283   --m_current_search_depth;
 
  284   if (m_found_deadlock)
 
  285     opt_change_victim_to(node);
 
  298   m_found_deadlock= node == m_start_node;
 
  299   return m_found_deadlock;
 
  312 Deadlock_detection_visitor::opt_change_victim_to(
MDL_context *new_victim)
 
  314   if (m_victim == NULL ||
 
  319     m_victim= new_victim;
 
  320     m_victim->lock_deadlock_victim();
 
  322       tmp->unlock_deadlock_victim();
 
  332 #define MDL_BIT(A) static_cast<MDL_lock::bitmap_t>(1U << A) 
  348   typedef unsigned short bitmap_t;
 
  356                                       &MDL_ticket::prev_in_lock>,
 
  360     operator const List &() 
const { 
return m_list; }
 
  365     bool is_empty()
 const { 
return m_list.is_empty(); }
 
  366     bitmap_t bitmap()
 const { 
return m_bitmap; }
 
  368     void clear_bit_if_not_in_list(enum_mdl_type 
type);
 
  416   bool is_empty()
 const 
  421   virtual const bitmap_t *incompatible_granted_types_bitmap() 
const = 0;
 
  422   virtual const bitmap_t *incompatible_waiting_types_bitmap() 
const = 0;
 
  427                       bool ignore_lock_priority) 
const;
 
  439   virtual bool needs_notification(
const MDL_ticket *ticket) 
const = 0;
 
  440   virtual void notify_conflicting_locks(
MDL_context *ctx) = 0;
 
  442   virtual bitmap_t hog_lock_types_bitmap() 
const = 0;
 
  462     m_is_destroyed(FALSE),
 
  473   inline static void destroy(
MDL_lock *lock);
 
  535   virtual const bitmap_t *incompatible_granted_types_bitmap()
 const 
  537     return m_granted_incompatible;
 
  539   virtual const bitmap_t *incompatible_waiting_types_bitmap()
 const 
  541     return m_waiting_incompatible;
 
  543   virtual bool needs_notification(
const MDL_ticket *ticket)
 const 
  545     return (ticket->get_type() == MDL_SHARED);
 
  553   virtual bitmap_t hog_lock_types_bitmap()
 const 
  559   static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
 
  560   static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
 
  585     DBUG_ASSERT(is_empty());
 
  587     DBUG_ASSERT(! m_is_destroyed);
 
  596   virtual const bitmap_t *incompatible_granted_types_bitmap()
 const 
  598     return m_granted_incompatible;
 
  600   virtual const bitmap_t *incompatible_waiting_types_bitmap()
 const 
  602     return m_waiting_incompatible;
 
  604   virtual bool needs_notification(
const MDL_ticket *ticket)
 const 
  606     return (ticket->get_type() >= MDL_SHARED_NO_WRITE);
 
  615   virtual bitmap_t hog_lock_types_bitmap()
 const 
  617     return (MDL_BIT(MDL_SHARED_NO_WRITE) |
 
  618             MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
  619             MDL_BIT(MDL_EXCLUSIVE));
 
  623   static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
 
  624   static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
 
  637                               &MDL_object_lock::prev_in_cache>
 
  646 ulong mdl_locks_cache_size;
 
  652 mdl_locks_key(
const uchar *
record, 
size_t *length,
 
  653               my_bool not_used __attribute__((unused)))
 
  656   *length= lock->
key.length();
 
  657   return (uchar*) lock->
key.ptr();
 
  675   DBUG_ASSERT(! mdl_initialized);
 
  676   mdl_initialized= TRUE;
 
  678 #ifdef HAVE_PSI_INTERFACE 
  697     mdl_initialized= FALSE;
 
  707   MDL_key global_lock_key(MDL_key::GLOBAL, 
"", 
"");
 
  708   MDL_key commit_lock_key(MDL_key::COMMIT, 
"", 
"");
 
  713   for (uint i= 0; i < mdl_locks_hash_partitions; i++)
 
  716     m_partitions.
append(part);
 
  726   my_hash_init(&m_locks, &my_charset_bin, 16 , 0, 0,
 
  727                mdl_locks_key, 0, 0);
 
  741   while (m_partitions.elements() > 0)
 
  756   DBUG_ASSERT(!m_locks.records);
 
  758   my_hash_free(&m_locks);
 
  761   while ((lock= m_unused_locks_cache.pop_front()))
 
  762     MDL_lock::destroy(lock);
 
  779   if (mdl_key->mdl_namespace() == MDL_key::GLOBAL ||
 
  780       mdl_key->mdl_namespace() == MDL_key::COMMIT)
 
  791     DBUG_ASSERT(mdl_key->length() == 3);
 
  793     lock= (mdl_key->mdl_namespace() == MDL_key::GLOBAL) ? m_global_lock :
 
  801   my_hash_value_type hash_value= m_partitions.
at(0)->get_key_hash(mdl_key);
 
  802   uint part_id= hash_value % mdl_locks_hash_partitions;
 
  819                                             my_hash_value_type hash_value)
 
  825   if (!(lock= (
MDL_lock*) my_hash_search_using_hash_value(&m_locks,
 
  836     if (mdl_key->mdl_namespace() != MDL_key::SCHEMA &&
 
  837         m_unused_locks_cache.elements())
 
  844       DBUG_ASSERT(mdl_key->mdl_namespace() != MDL_key::GLOBAL &&
 
  845                   mdl_key->mdl_namespace() != MDL_key::COMMIT);
 
  847       unused_lock= m_unused_locks_cache.pop_front();
 
  848       unused_lock->
reset(mdl_key);
 
  857     if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
 
  866         m_unused_locks_cache.push_front(unused_lock);
 
  870         MDL_lock::destroy(lock);
 
  877   if (move_from_hash_to_lock_mutex(lock))
 
  894 bool MDL_map_partition::move_from_hash_to_lock_mutex(
MDL_lock *lock)
 
  898   DBUG_ASSERT(! lock->m_is_destroyed);
 
  912   lock->m_ref_release++;
 
  914   if (unlikely(lock->
m_version != version))
 
  923     if (unlikely(lock->m_is_destroyed))
 
  935       uint ref_release= lock->m_ref_release;
 
  937       if (ref_usage == ref_release)
 
  938         MDL_lock::destroy(lock);
 
  965   if (lock->
key.mdl_namespace() == MDL_key::GLOBAL ||
 
  966       lock->
key.mdl_namespace() == MDL_key::COMMIT)
 
  989   my_hash_delete(&m_locks, (uchar*) lock);
 
  999   if ((lock->
key.mdl_namespace() != MDL_key::SCHEMA) &&
 
 1000       (m_unused_locks_cache.elements() <
 
 1001        mdl_locks_cache_size/mdl_locks_hash_partitions))
 
 1012     DBUG_ASSERT(lock->
key.mdl_namespace() != MDL_key::GLOBAL &&
 
 1013                 lock->
key.mdl_namespace() != MDL_key::COMMIT);
 
 1038     uint ref_usage, ref_release;
 
 1040     lock->m_is_destroyed= TRUE;
 
 1042     ref_release= lock->m_ref_release;
 
 1045     if (ref_usage == ref_release)
 
 1046       MDL_lock::destroy(lock);
 
 1060   m_needs_thr_lock_abort(FALSE),
 
 1081   DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty());
 
 1082   DBUG_ASSERT(m_tickets[MDL_TRANSACTION].is_empty());
 
 1083   DBUG_ASSERT(m_tickets[MDL_EXPLICIT].is_empty());
 
 1111                        const char *name_arg,
 
 1112                        enum_mdl_type mdl_type_arg,
 
 1113                        enum_mdl_duration mdl_duration_arg)
 
 1132                        enum_mdl_type mdl_type_arg,
 
 1133                        enum_mdl_duration mdl_duration_arg)
 
 1151   switch (mdl_key->mdl_namespace())
 
 1153     case MDL_key::GLOBAL:
 
 1154     case MDL_key::SCHEMA:
 
 1155     case MDL_key::COMMIT:
 
 1163 void MDL_lock::destroy(
MDL_lock *lock)
 
 1179                                , enum_mdl_duration duration_arg
 
 1183   return new (std::nothrow)
 
 1207   return (m_lock->
key.mdl_namespace() == MDL_key::GLOBAL ||
 
 1208           m_type >= MDL_SHARED_UPGRADABLE ?
 
 1209           DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML);
 
 1216   :m_wait_status(EMPTY)
 
 1218   mysql_mutex_init(key_MDL_wait_LOCK_wait_status, &m_LOCK_wait_status, NULL);
 
 1219   mysql_cond_init(key_MDL_wait_COND_wait_status, &m_COND_wait_status, NULL);
 
 1239   bool was_occupied= TRUE;
 
 1241   if (m_wait_status == EMPTY)
 
 1243     was_occupied= FALSE;
 
 1244     m_wait_status= status_arg;
 
 1248   return was_occupied;
 
 1256   enum_wait_status result;
 
 1258   result= m_wait_status;
 
 1269   m_wait_status= EMPTY;
 
 1288 MDL_wait::enum_wait_status
 
 1290                      bool set_status_on_timeout,
 
 1294   enum_wait_status result;
 
 1299   owner->ENTER_COND(&m_COND_wait_status, &m_LOCK_wait_status,
 
 1300                     wait_state_name, & old_stage);
 
 1302   while (!m_wait_status && !owner->
is_killed() &&
 
 1303          wait_result != ETIMEDOUT && wait_result != ETIME)
 
 1310   if (m_wait_status == EMPTY)
 
 1325       m_wait_status= KILLED;
 
 1326     else if (set_status_on_timeout)
 
 1327       m_wait_status= TIMEOUT;
 
 1329   result= m_wait_status;
 
 1331   owner->EXIT_COND(& old_stage);
 
 1346 void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type 
type)
 
 1351   while ((ticket= it++))
 
 1352     if (ticket->get_type() == 
type)
 
 1354   m_bitmap&= ~ MDL_BIT(type);
 
 1370   DBUG_ASSERT(ticket->get_lock());
 
 1375   m_list.push_back(ticket);
 
 1376   m_bitmap|= MDL_BIT(ticket->get_type());
 
 1387   m_list.remove(ticket);
 
 1398   clear_bit_if_not_in_list(ticket->get_type());
 
 1417   bool skip_high_priority= 
false;
 
 1418   bitmap_t hog_lock_types= hog_lock_types_bitmap();
 
 1428     if ((
m_waiting.bitmap() & ~hog_lock_types) != 0)
 
 1449       skip_high_priority= 
true;
 
 1471   while ((ticket= it++))
 
 1477     if (skip_high_priority &&
 
 1478         ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0))
 
 1482                        skip_high_priority))
 
 1501         if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)
 
 1515   if ((
m_waiting.bitmap() & ~hog_lock_types) == 0)
 
 1584 const MDL_lock::bitmap_t MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END] =
 
 1586   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
 
 1587   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE), 0, 0, 0, 0, 0, 0,
 
 1588   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
 
 1591 const MDL_lock::bitmap_t MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END] =
 
 1593   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
 
 1594   MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0
 
 1652 const MDL_lock::bitmap_t
 
 1653 MDL_object_lock::m_granted_incompatible[MDL_TYPE_END] =
 
 1656   MDL_BIT(MDL_EXCLUSIVE),
 
 1657   MDL_BIT(MDL_EXCLUSIVE),
 
 1658   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
 
 1659   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1660     MDL_BIT(MDL_SHARED_NO_WRITE),
 
 1661   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1662     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
 
 1663   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1664     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
 
 1665     MDL_BIT(MDL_SHARED_WRITE),
 
 1666   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1667     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
 
 1668     MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ),
 
 1669   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1670     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
 
 1671     MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ) |
 
 1672     MDL_BIT(MDL_SHARED_HIGH_PRIO) | MDL_BIT(MDL_SHARED)
 
 1676 const MDL_lock::bitmap_t
 
 1677 MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
 
 1680   MDL_BIT(MDL_EXCLUSIVE),
 
 1682   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
 
 1683   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
 
 1684     MDL_BIT(MDL_SHARED_NO_WRITE),
 
 1685   MDL_BIT(MDL_EXCLUSIVE),
 
 1686   MDL_BIT(MDL_EXCLUSIVE),
 
 1687   MDL_BIT(MDL_EXCLUSIVE),
 
 1711                          bool ignore_lock_priority)
 const 
 1713   bool can_grant= FALSE;
 
 1714   bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
 
 1715   bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
 
 1724   if (ignore_lock_priority || !(
m_waiting.bitmap() & waiting_incompat_map))
 
 1726     if (! (
m_granted.bitmap() & granted_incompat_map))
 
 1734       while ((ticket= it++))
 
 1736         if (ticket->get_ctx() != requestor_ctx &&
 
 1737             ticket->is_incompatible_when_granted(type_arg))
 
 1794   result= (
m_waiting.bitmap() & incompatible_granted_types_bitmap()[
type]);
 
 1800 MDL_wait_for_graph_visitor::~MDL_wait_for_graph_visitor()
 
 1805 MDL_wait_for_subgraph::~MDL_wait_for_subgraph()
 
 1820   const MDL_lock::bitmap_t *
 
 1821     granted_incompat_map= m_lock->incompatible_granted_types_bitmap();
 
 1823   return ! (granted_incompat_map[
type] & ~(granted_incompat_map[m_type]));
 
 1827 bool MDL_ticket::is_incompatible_when_granted(enum_mdl_type type)
 const 
 1829   return (MDL_BIT(m_type) &
 
 1830           m_lock->incompatible_granted_types_bitmap()[
type]);
 
 1834 bool MDL_ticket::is_incompatible_when_waiting(enum_mdl_type type)
 const 
 1836   return (MDL_BIT(m_type) &
 
 1837           m_lock->incompatible_waiting_types_bitmap()[
type]);
 
 1857 MDL_context::find_ticket(
MDL_request *mdl_request,
 
 1858                          enum_mdl_duration *result_duration)
 
 1863   for (i= 0; i < MDL_DURATION_END; i++)
 
 1865     enum_mdl_duration duration= (enum_mdl_duration)((mdl_request->
duration+i) %
 
 1867     Ticket_iterator it(m_tickets[duration]);
 
 1869     while ((ticket= it++))
 
 1871       if (mdl_request->
key.is_equal(&ticket->m_lock->
key) &&
 
 1874         *result_duration= duration;
 
 1914   if (try_acquire_lock_impl(mdl_request, &ticket))
 
 1917   if (! mdl_request->
ticket)
 
 1925     DBUG_ASSERT(! ticket->m_lock->is_empty());
 
 1927     MDL_ticket::destroy(ticket);
 
 1951 MDL_context::try_acquire_lock_impl(
MDL_request *mdl_request,
 
 1957   enum_mdl_duration found_duration;
 
 1959   DBUG_ASSERT(mdl_request->
type != MDL_EXCLUSIVE ||
 
 1960               is_lock_owner(MDL_key::GLOBAL, 
"", 
"", MDL_INTENTION_EXCLUSIVE));
 
 1961   DBUG_ASSERT(mdl_request->
ticket == NULL);
 
 1964   mdl_request->
ticket= NULL;
 
 1971   if ((ticket= find_ticket(mdl_request, &found_duration)))
 
 1973     DBUG_ASSERT(ticket->m_lock);
 
 1992     mdl_request->
ticket= ticket;
 
 1993     if ((found_duration != mdl_request->
duration ||
 
 1994          mdl_request->
duration == MDL_EXPLICIT) &&
 
 1995         clone_ticket(mdl_request))
 
 1998       mdl_request->
ticket= NULL;
 
 2004   if (!(ticket= MDL_ticket::create(
this, mdl_request->
type 
 2014     MDL_ticket::destroy(ticket);
 
 2018   ticket->m_lock= lock;
 
 2026     m_tickets[mdl_request->
duration].push_front(ticket);
 
 2028     mdl_request->
ticket= ticket;
 
 2031     *out_ticket= ticket;
 
 2061   if (!(ticket= MDL_ticket::create(
this, mdl_request->
type 
 2071   ticket->m_lock= mdl_request->
ticket->m_lock;
 
 2072   mdl_request->
ticket= ticket;
 
 2078   m_tickets[mdl_request->
duration].push_front(ticket);
 
 2096   while ((conflicting_ticket= it++))
 
 2099     if (conflicting_ticket->get_ctx() != ctx &&
 
 2100         conflicting_ticket->get_type() < MDL_SHARED_UPGRADABLE)
 
 2103       MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
 
 2111         notify_shared_lock(conflicting_ctx->get_owner(),
 
 2112                            conflicting_ctx->get_needs_thr_lock_abort());
 
 2129   while ((conflicting_ticket= it++))
 
 2131     if (conflicting_ticket->get_ctx() != ctx &&
 
 2132         conflicting_ticket->get_type() == MDL_INTENTION_EXCLUSIVE)
 
 2135       MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
 
 2143         notify_shared_lock(conflicting_ctx->get_owner(),
 
 2144                            conflicting_ctx->get_needs_thr_lock_abort());
 
 2168   MDL_wait::enum_wait_status wait_status;
 
 2170   set_timespec(abs_timeout, lock_wait_timeout);
 
 2172   if (try_acquire_lock_impl(mdl_request, &ticket))
 
 2191   lock= ticket->m_lock;
 
 2201   m_wait.reset_status();
 
 2203   if (lock->needs_notification(ticket))
 
 2204     lock->notify_conflicting_locks(
this);
 
 2208   will_wait_for(ticket);
 
 2211   DEBUG_SYNC(get_thd(), 
"mdl_acquire_lock_wait");
 
 2215   if (lock->needs_notification(ticket))
 
 2218     set_timespec(abs_shortwait, 1);
 
 2219     wait_status= MDL_wait::EMPTY;
 
 2221     while (cmp_timespec(abs_shortwait, abs_timeout) <= 0)
 
 2224       wait_status= m_wait.timed_wait(m_owner, &abs_shortwait, FALSE,
 
 2227       if (wait_status != MDL_wait::EMPTY)
 
 2231       lock->notify_conflicting_locks(
this);
 
 2233       set_timespec(abs_shortwait, 1);
 
 2235     if (wait_status == MDL_wait::EMPTY)
 
 2236       wait_status= m_wait.timed_wait(m_owner, &abs_timeout, TRUE,
 
 2240     wait_status= m_wait.timed_wait(m_owner, &abs_timeout, TRUE,
 
 2245   if (wait_status != MDL_wait::GRANTED)
 
 2248     MDL_ticket::destroy(ticket);
 
 2249     switch (wait_status)
 
 2251     case MDL_wait::VICTIM:
 
 2252       my_error(ER_LOCK_DEADLOCK, MYF(0));
 
 2254     case MDL_wait::TIMEOUT:
 
 2255       my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
 
 2257     case MDL_wait::KILLED:
 
 2272   DBUG_ASSERT(wait_status == MDL_wait::GRANTED);
 
 2274   m_tickets[mdl_request->
duration].push_front(ticket);
 
 2276   mdl_request->
ticket= ticket;
 
 2282 extern "C" int mdl_request_ptr_cmp(
const void* ptr1, 
const void* ptr2)
 
 2311                                 ulong lock_wait_timeout)
 
 2316   ssize_t req_count= 
static_cast<ssize_t
>(mdl_requests->elements());
 
 2322   if (! (sort_buf= (
MDL_request **)my_malloc(req_count *
 
 2327   for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++)
 
 2330   my_qsort(sort_buf, req_count, 
sizeof(
MDL_request*),
 
 2331            mdl_request_ptr_cmp);
 
 2333   for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++)
 
 2335     if (acquire_lock(*p_req, lock_wait_timeout))
 
 2347   rollback_to_savepoint(mdl_svp);
 
 2349   for (req_count= p_req - sort_buf, p_req= sort_buf;
 
 2350        p_req < sort_buf + req_count; p_req++)
 
 2352     (*p_req)->ticket= NULL;
 
 2386                                  enum_mdl_type new_type,
 
 2387                                  ulong lock_wait_timeout)
 
 2393   DBUG_ENTER(
"MDL_context::upgrade_shared_lock");
 
 2394   DEBUG_SYNC(get_thd(), 
"mdl_upgrade_lock");
 
 2403   mdl_xlock_request.
init(&mdl_ticket->m_lock->
key, new_type,
 
 2406   if (acquire_lock(&mdl_xlock_request, lock_wait_timeout))
 
 2409   is_new_ticket= ! has_lock(mdl_svp, mdl_xlock_request.
ticket);
 
 2421   mdl_ticket->m_type= new_type;
 
 2428     m_tickets[MDL_TRANSACTION].remove(mdl_xlock_request.
ticket);
 
 2429     MDL_ticket::destroy(mdl_xlock_request.
ticket);
 
 2515   if (gvisitor->enter_node(src_ctx))
 
 2524   while ((ticket= granted_it++))
 
 2527     if (ticket->get_ctx() != src_ctx &&
 
 2528         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
 
 2529         gvisitor->inspect_edge(ticket->get_ctx()))
 
 2531       goto end_leave_node;
 
 2535   while ((ticket= waiting_it++))
 
 2538     if (ticket->get_ctx() != src_ctx &&
 
 2539         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
 
 2540         gvisitor->inspect_edge(ticket->get_ctx()))
 
 2542       goto end_leave_node;
 
 2547   granted_it.rewind();
 
 2548   while ((ticket= granted_it++))
 
 2550     if (ticket->get_ctx() != src_ctx &&
 
 2551         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
 
 2554       goto end_leave_node;
 
 2558   waiting_it.rewind();
 
 2559   while ((ticket= waiting_it++))
 
 2561     if (ticket->get_ctx() != src_ctx &&
 
 2562         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
 
 2565       goto end_leave_node;
 
 2572   gvisitor->leave_node(src_ctx);
 
 2592   return m_lock->visit_subgraph(
this, gvisitor);
 
 2619     result= m_waiting_for->accept_visitor(gvisitor);
 
 2656     victim= dvisitor.get_victim();
 
 2671     victim->unlock_deadlock_victim();
 
 2697   DBUG_ENTER(
"MDL_context::release_lock");
 
 2698   DBUG_PRINT(
"enter", (
"db=%s name=%s", lock->
key.db_name(),
 
 2701   DBUG_ASSERT(
this == ticket->get_ctx());
 
 2706   m_tickets[duration].remove(ticket);
 
 2707   MDL_ticket::destroy(ticket);
 
 2722   DBUG_ASSERT(ticket->m_duration == MDL_EXPLICIT);
 
 2724   release_lock(MDL_EXPLICIT, ticket);
 
 2741 void MDL_context::release_locks_stored_before(enum_mdl_duration duration,
 
 2745   Ticket_iterator it(m_tickets[duration]);
 
 2746   DBUG_ENTER(
"MDL_context::release_locks_stored_before");
 
 2748   if (m_tickets[duration].is_empty())
 
 2751   while ((ticket= it++) && ticket != sentinel)
 
 2753     DBUG_PRINT(
"info", (
"found lock to release ticket=%p", ticket));
 
 2754     release_lock(duration, ticket);
 
 2778   while ((ticket= it_ticket++))
 
 2780     DBUG_ASSERT(ticket->m_lock);
 
 2781     if (ticket->m_lock == lock)
 
 2782       release_lock(MDL_EXPLICIT, ticket);
 
 2804   if (m_type == type || !has_stronger_or_equal_type(type))
 
 2808   DBUG_ASSERT(m_type == MDL_EXCLUSIVE ||
 
 2809               m_type == MDL_SHARED_NO_WRITE);
 
 2816   m_lock->m_granted.remove_ticket(
this);
 
 2818   m_lock->m_granted.add_ticket(
this);
 
 2819   m_lock->reschedule_waiters();
 
 2840                            const char *db, 
const char *
name,
 
 2841                            enum_mdl_type mdl_type)
 
 2844   enum_mdl_duration not_unused;
 
 2846   mdl_request.
init(mdl_namespace, db, name, mdl_type, MDL_TRANSACTION);
 
 2847   MDL_ticket *ticket= find_ticket(&mdl_request, ¬_unused);
 
 2849   DBUG_ASSERT(ticket == NULL || ticket->m_lock);
 
 2865   return m_lock->has_pending_conflicting_lock(m_type);
 
 2880   DBUG_ENTER(
"MDL_context::rollback_to_savepoint");
 
 2883   release_locks_stored_before(MDL_STATEMENT, mdl_savepoint.m_stmt_ticket);
 
 2884   release_locks_stored_before(MDL_TRANSACTION, mdl_savepoint.m_trans_ticket);
 
 2901   DBUG_ENTER(
"MDL_context::release_transactional_locks");
 
 2902   release_locks_stored_before(MDL_STATEMENT, NULL);
 
 2903   release_locks_stored_before(MDL_TRANSACTION, NULL);
 
 2908 void MDL_context::release_statement_locks()
 
 2910   DBUG_ENTER(
"MDL_context::release_transactional_locks");
 
 2911   release_locks_stored_before(MDL_STATEMENT, NULL);
 
 2934   while ((ticket= s_it++) && ticket != mdl_savepoint.m_stmt_ticket)
 
 2936     if (ticket == mdl_ticket)
 
 2940   while ((ticket= t_it++) && ticket != mdl_savepoint.m_trans_ticket)
 
 2942     if (ticket == mdl_ticket)
 
 2960                                     enum_mdl_duration duration)
 
 2962   DBUG_ASSERT(mdl_ticket->m_duration == MDL_TRANSACTION &&
 
 2963               duration != MDL_TRANSACTION);
 
 2965   m_tickets[MDL_TRANSACTION].remove(mdl_ticket);
 
 2966   m_tickets[duration].push_front(mdl_ticket);
 
 2968   mdl_ticket->m_duration= duration;
 
 2991   m_tickets[MDL_EXPLICIT].swap(m_tickets[MDL_TRANSACTION]);
 
 2993   for (i= 0; i < MDL_EXPLICIT; i++)
 
 2997     while ((ticket= it_ticket++))
 
 2999       m_tickets[
i].remove(ticket);
 
 3000       m_tickets[MDL_EXPLICIT].push_front(ticket);
 
 3007   while ((ticket= exp_it++))
 
 3008     ticket->m_duration= MDL_EXPLICIT;
 
 3030   DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty());
 
 3032   m_tickets[MDL_TRANSACTION].swap(m_tickets[MDL_EXPLICIT]);
 
 3036   while ((ticket= it_ticket++))
 
 3038     m_tickets[MDL_EXPLICIT].remove(ticket);
 
 3039     m_tickets[MDL_TRANSACTION].push_front(ticket);
 
 3045   while ((ticket= trans_it++))
 
 3046     ticket->m_duration= MDL_TRANSACTION;