1 /* Copyright (c) 2007, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 
24 #include "mdl.h"
25 #include "debug_sync.h"
26 #include "prealloced_array.h"
27 #include <lf.h>
28 #include "mysqld.h"
29 #include <mysqld_error.h>
30 #include <mysql/plugin.h>
31 #include <mysql/service_thd_wait.h>
32 #include <pfs_metadata_provider.h>
33 #include <mysql/psi/mysql_mdl.h>
34 #include <pfs_stage_provider.h>
35 #include <mysql/psi/mysql_stage.h>
36 #include <my_murmur3.h>
37 #include <algorithm>
38 #include <functional>
39 
40 static PSI_memory_key key_memory_MDL_context_acquire_locks;
41 
42 #ifdef HAVE_PSI_INTERFACE
43 static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
44 
45 static PSI_mutex_info all_mdl_mutexes[]=
46 {
47   { &key_MDL_wait_LOCK_wait_status, "MDL_wait::LOCK_wait_status", 0}
48 };
49 
50 static PSI_rwlock_key key_MDL_lock_rwlock;
51 static PSI_rwlock_key key_MDL_context_LOCK_waiting_for;
52 
53 static PSI_rwlock_info all_mdl_rwlocks[]=
54 {
55   { &key_MDL_lock_rwlock, "MDL_lock::rwlock", 0},
56   { &key_MDL_context_LOCK_waiting_for, "MDL_context::LOCK_waiting_for", 0}
57 };
58 
59 static PSI_cond_key key_MDL_wait_COND_wait_status;
60 
61 static PSI_cond_info all_mdl_conds[]=
62 {
63   { &key_MDL_wait_COND_wait_status, "MDL_context::COND_wait_status", 0}
64 };
65 
66 static PSI_memory_info all_mdl_memory[]=
67 {
68   { &key_memory_MDL_context_acquire_locks, "MDL_context::acquire_locks", 0}
69 };
70 
71 /**
72   Initialise all the performance schema instrumentation points
73   used by the MDL subsystem.
74 */
init_mdl_psi_keys(void)75 static void init_mdl_psi_keys(void)
76 {
77   int count;
78 
79   count= array_elements(all_mdl_mutexes);
80   mysql_mutex_register("sql", all_mdl_mutexes, count);
81 
82   count= array_elements(all_mdl_rwlocks);
83   mysql_rwlock_register("sql", all_mdl_rwlocks, count);
84 
85   count= array_elements(all_mdl_conds);
86   mysql_cond_register("sql", all_mdl_conds, count);
87 
88   count= array_elements(all_mdl_memory);
89   mysql_memory_register("sql", all_mdl_memory, count);
90 
91   MDL_key::init_psi_keys();
92 }
93 #endif /* HAVE_PSI_INTERFACE */
94 
95 
96 /**
97   Thread state names to be used in case when we have to wait on resource
98   belonging to certain namespace.
99 */
100 
101 PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]=
102 {
103   {0, "Waiting for global read lock", 0},
104   {0, "Waiting for tablespace metadata lock", 0},
105   {0, "Waiting for schema metadata lock", 0},
106   {0, "Waiting for table metadata lock", 0},
107   {0, "Waiting for stored function metadata lock", 0},
108   {0, "Waiting for stored procedure metadata lock", 0},
109   {0, "Waiting for trigger metadata lock", 0},
110   {0, "Waiting for event metadata lock", 0},
111   {0, "Waiting for commit lock", 0},
112   {0, "User lock", 0}, /* Be compatible with old status. */
113   {0, "Waiting for locking service lock", 0},
114   {0, "Waiting for backup lock", 0},
115   {0, "Waiting for binlog lock", 0}
116 };
117 
118 #ifdef HAVE_PSI_INTERFACE
init_psi_keys()119 void MDL_key::init_psi_keys()
120 {
121   int i;
122   int count;
123   PSI_stage_info *info MY_ATTRIBUTE((unused));
124 
125   count= array_elements(MDL_key::m_namespace_to_wait_state_name);
126   for (i= 0; i<count; i++)
127   {
128     /* mysql_stage_register wants an array of pointers, registering 1 by 1. */
129     info= & MDL_key::m_namespace_to_wait_state_name[i];
130     mysql_stage_register("sql", &info, 1);
131   }
132 }
133 #endif
134 
135 static bool mdl_initialized= 0;
136 
137 
138 /**
139   A collection of all MDL locks. A singleton,
140   there is only one instance of the map in the server.
141 */
142 
143 class MDL_map
144 {
145 public:
146   void init();
147   void destroy();
148 
149   inline MDL_lock *find(LF_PINS *pins, const MDL_key *key, bool *pinned);
150   inline MDL_lock *find_or_insert(LF_PINS *pins, const MDL_key *key, bool *pinned);
151 
152   /**
153     Decrement unused MDL_lock objects counter.
154   */
lock_object_used()155   void lock_object_used()
156   {
157     my_atomic_add32(&m_unused_lock_objects, -1);
158   }
159 
160   /**
161     Increment unused MDL_lock objects counter. If number of such objects
162     exceeds threshold and unused/total objects ratio is high enough try
163     to free some of them.
164   */
lock_object_unused(MDL_context * ctx,LF_PINS * pins)165   void lock_object_unused(MDL_context *ctx, LF_PINS *pins)
166   {
167     /*
168       Use thread local copy of unused locks counter for performance/
169       scalability reasons. It is updated on both successfull and failed
170       attempts to delete unused MDL_lock objects in order to avoid infinite
171       loops,
172     */
173     int32 unused_locks= my_atomic_add32(&m_unused_lock_objects, 1) + 1;
174 
175     while (unused_locks > mdl_locks_unused_locks_low_water &&
176            (unused_locks > m_locks.count * MDL_LOCKS_UNUSED_LOCKS_MIN_RATIO))
177     {
178       /*
179         If number of unused lock objects exceeds low water threshold and
180         unused/total objects ratio is high enough - try to do random dive
181         into m_locks hash, find an unused object by iterating upwards
182         through its split-ordered list and try to free it.
183         If we fail to do this - update local copy of unused objects
184         counter and retry if needed,
185 
186         Note that:
187         *) It is not big deal if "m_unused_lock_objects" due to races becomes
188            negative temporarily as we perform signed comparison.
189         *) There is a good chance that we will find an unused object quickly
190            because unused/total ratio is high enough.
191         *) There is no possibility for infinite loop since our PRNG works
192            in such way that we eventually cycle through all LF_HASH hash
193            buckets (@sa MDL_context::get_random()).
194         *) Thanks to the fact that we choose random object to expel -
195            objects which are used more often will naturally stay
196            in the cache and rarely used objects will be expelled from it.
197         *) Non-atomic read of LF_HASH::count which happens above should be
198            OK as LF_HASH code does them too + preceding atomic operation
199            provides memory barrier.
200       */
201       remove_random_unused(ctx, pins, &unused_locks);
202     }
203   }
204 
205   /**
206     Get number of unused MDL_lock objects in MDL_map cache.
207 
208     @note Does non-atomic read so can return stale results. This is OK since
209           this method is used only in unit-tests. The latter employ means
210           of thread synchronization which are external to MDL and prevent
211           memory reordering/ensure that thread calling this method have
212           up-to-date view on the memory. @sa m_unused_lock_objects.
213   */
get_unused_locks_count() const214   int32 get_unused_locks_count() const
215   {
216     return m_unused_lock_objects;
217   }
218 
219   /**
220     Allocate pins which are necessary for MDL_context/thread to be able
221     to work with MDL_map container.
222   */
get_pins()223   LF_PINS *get_pins() { return lf_hash_get_pins(&m_locks); }
224 
225   /**
226     Check if MDL_lock object corresponding to the key is going to be
227     singleton.
228   */
is_lock_object_singleton(const MDL_key * mdl_key) const229   bool is_lock_object_singleton(const MDL_key *mdl_key) const
230   {
231     return (mdl_key->mdl_namespace() == MDL_key::GLOBAL ||
232             mdl_key->mdl_namespace() == MDL_key::COMMIT ||
233             mdl_key->mdl_namespace() == MDL_key::BACKUP ||
234             mdl_key->mdl_namespace() == MDL_key::BINLOG);
235   }
236 
237 private:
238 
239   void remove_random_unused(MDL_context *ctx, LF_PINS *pins, int32 *unused_locks);
240 
241   /** LF_HASH with all locks in the server. */
242   LF_HASH m_locks;
243   /** Pre-allocated MDL_lock object for GLOBAL namespace. */
244   MDL_lock *m_global_lock;
245   /** Pre-allocated MDL_lock object for COMMIT namespace. */
246   MDL_lock *m_commit_lock;
247   /**
248     Number of unused MDL_lock objects in the server.
249 
250     Updated using atomic operations, read using both atomic and ordinary
251     reads. We assume that ordinary reads of 32-bit words can't result in
252     partial results, but may produce stale results thanks to memory
253     reordering, LF_HASH seems to be using similar assumption.
254 
255     Note that due to fact that updates to this counter are not atomic with
256     marking MDL_lock objects as used/unused it might easily get negative
257     for some short period of time. Code which uses its value needs to take
258     this into account.
259   */
260   volatile int32 m_unused_lock_objects;
261   /** Pre-allocated MDL_lock object for BACKUP namespace. */
262   MDL_lock *m_backup_lock;
263   /** Pre-allocated MDL_lock object for BINLOG namespace */
264   MDL_lock *m_binlog_lock;
265 };
266 
267 
268 /**
269   Threshold for number of unused MDL_lock objects.
270 
271   We will start considering freeing some unused objects only after exceeding
272   this value and if unused/total objects ratio is high enough.
273 
274   Normally this threshold is constant. It is exposed outside of MDL subsystem
275   as a variable only in order to simplify unit testing.
276 */
277 int32 mdl_locks_unused_locks_low_water=
278         MDL_LOCKS_UNUSED_LOCKS_LOW_WATER_DEFAULT;
279 
280 
281 /**
282   A context of the recursive traversal through all contexts
283   in all sessions in search for deadlock.
284 */
285 
286 class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor
287 {
288 public:
Deadlock_detection_visitor(MDL_context * start_node_arg)289   Deadlock_detection_visitor(MDL_context *start_node_arg)
290     : m_start_node(start_node_arg),
291       m_victim(NULL),
292       m_current_search_depth(0),
293       m_found_deadlock(FALSE)
294   {}
295   virtual bool enter_node(MDL_context *node);
296   virtual void leave_node(MDL_context *node);
297 
298   virtual bool inspect_edge(MDL_context *dest);
299 
get_victim() const300   MDL_context *get_victim() const { return m_victim; }
301 private:
302   /**
303     Change the deadlock victim to a new one if it has lower deadlock
304     weight.
305   */
306   void opt_change_victim_to(MDL_context *new_victim);
307 private:
308   /**
309     The context which has initiated the search. There
310     can be multiple searches happening in parallel at the same time.
311   */
312   MDL_context *m_start_node;
313   /** If a deadlock is found, the context that identifies the victim. */
314   MDL_context *m_victim;
315   /** Set to the 0 at start. Increased whenever
316     we descend into another MDL context (aka traverse to the next
317     wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
318     assume that a deadlock is found, even if we have not found a
319     loop.
320   */
321   uint m_current_search_depth;
322   /** TRUE if we found a deadlock. */
323   bool m_found_deadlock;
324   /**
325     Maximum depth for deadlock searches. After this depth is
326     achieved we will unconditionally declare that there is a
327     deadlock.
328 
329     @note This depth should be small enough to avoid stack
330           being exhausted by recursive search algorithm.
331 
332     TODO: Find out what is the optimal value for this parameter.
333           Current value is safe, but probably sub-optimal,
334           as there is an anecdotal evidence that real-life
335           deadlocks are even shorter typically.
336   */
337   static const uint MAX_SEARCH_DEPTH= 32;
338 };
339 
340 
341 /**
342   Enter a node of a wait-for graph. After
343   a node is entered, inspect_edge() will be called
344   for all wait-for destinations of this node. Then
345   leave_node() will be called.
346   We call "enter_node()" for all nodes we inspect,
347   including the starting node.
348 
349   @retval  TRUE  Maximum search depth exceeded.
350   @retval  FALSE OK.
351 */
352 
enter_node(MDL_context * node)353 bool Deadlock_detection_visitor::enter_node(MDL_context *node)
354 {
355   m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
356   if (m_found_deadlock)
357   {
358     assert(! m_victim);
359     opt_change_victim_to(node);
360   }
361   return m_found_deadlock;
362 }
363 
364 
365 /**
366   Done inspecting this node. Decrease the search
367   depth. If a deadlock is found, and we are
368   backtracking to the start node, optionally
369   change the deadlock victim to one with lower
370   deadlock weight.
371 */
372 
leave_node(MDL_context * node)373 void Deadlock_detection_visitor::leave_node(MDL_context *node)
374 {
375   --m_current_search_depth;
376   if (m_found_deadlock)
377     opt_change_victim_to(node);
378 }
379 
380 
381 /**
382   Inspect a wait-for graph edge from one MDL context to another.
383 
384   @retval TRUE   A loop is found.
385   @retval FALSE  No loop is found.
386 */
387 
inspect_edge(MDL_context * node)388 bool Deadlock_detection_visitor::inspect_edge(MDL_context *node)
389 {
390   m_found_deadlock= node == m_start_node;
391   return m_found_deadlock;
392 }
393 
394 
395 /**
396   Change the deadlock victim to a new one if it has lower deadlock
397   weight.
398 
399   @param new_victim New candidate for deadlock victim.
400 */
401 
402 void
opt_change_victim_to(MDL_context * new_victim)403 Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
404 {
405   if (m_victim == NULL ||
406       m_victim->get_deadlock_weight() >= new_victim->get_deadlock_weight())
407   {
408     /* Swap victims, unlock the old one. */
409     MDL_context *tmp= m_victim;
410     m_victim= new_victim;
411     m_victim->lock_deadlock_victim();
412     if (tmp)
413       tmp->unlock_deadlock_victim();
414   }
415 }
416 
417 
418 /**
419   Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps
420   and compatibility matrices.
421 */
422 
423 #define MDL_BIT(A) static_cast<MDL_lock::bitmap_t>(1U << A)
424 
425 /**
426   The lock context. Created internally for an acquired lock.
427   For a given name, there exists only one MDL_lock instance,
428   and it exists only when the lock has been granted.
429   Can be seen as an MDL subsystem's version of TABLE_SHARE.
430 
431   This is an abstract class which lacks information about
432   compatibility rules for lock types. They should be specified
433   in its descendants.
434 */
435 
436 class MDL_lock
437 {
438 public:
439   typedef unsigned short bitmap_t;
440 
441   class Ticket_list
442   {
443   public:
444     typedef I_P_List<MDL_ticket,
445                      I_P_List_adapter<MDL_ticket,
446                                       &MDL_ticket::next_in_lock,
447                                       &MDL_ticket::prev_in_lock>,
448                      I_P_List_null_counter,
449                      I_P_List_fast_push_back<MDL_ticket> >
450             List;
operator const List&() const451     operator const List &() const { return m_list; }
Ticket_list()452     Ticket_list() :m_bitmap(0) {}
453 
454     void add_ticket(MDL_ticket *ticket);
455     void remove_ticket(MDL_ticket *ticket);
is_empty() const456     bool is_empty() const { return m_list.is_empty(); }
bitmap() const457     bitmap_t bitmap() const { return m_bitmap; }
458   private:
459     void clear_bit_if_not_in_list(enum_mdl_type type);
460   private:
461     /** List of tickets. */
462     List m_list;
463     /** Bitmap of types of tickets in this list. */
464     bitmap_t m_bitmap;
465   };
466 
467   typedef Ticket_list::List::Iterator Ticket_iterator;
468 
469   typedef longlong fast_path_state_t;
470 
471   /**
472     Helper struct which defines how different types of locks are handled
473     for a specific MDL_lock. In practice we use only two strategies: "scoped"
474     lock strategy for locks in GLOBAL, COMMIT, TABLESPACE and SCHEMA namespaces
475     and "object" lock strategy for all other namespaces.
476   */
477   struct MDL_lock_strategy
478   {
479     /**
480       Compatibility (or rather "incompatibility") matrices for lock types.
481 
482       Array of bitmaps which elements specify which granted locks are
483       incompatible with the type of lock being requested.
484     */
485     bitmap_t m_granted_incompatible[MDL_TYPE_END];
486     /**
487       Arrays of bitmaps which elements specify which waiting locks are
488       incompatible with the type of lock being requested. Basically, each
489       array defines priorities between lock types.
490       We need 4 separate arrays since in order to prevent starvation for
491       some of lock request types, we use different priority matrices:
492       0) in "normal" situation.
493       1) in situation when the number of successively granted "piglet" requests
494          exceeds the max_write_lock_count limit.
495       2) in situation when the number of successively granted "hog" requests
496          exceeds the max_write_lock_count limit.
497       3) in situation when both "piglet" and "hog" counters exceed limit.
498     */
499     bitmap_t m_waiting_incompatible[4][MDL_TYPE_END];
500     /**
501       Array of increments for "unobtrusive" types of lock requests for locks.
502       @sa MDL_lock::get_unobtrusive_lock_increment().
503     */
504     fast_path_state_t m_unobtrusive_lock_increment[MDL_TYPE_END];
505     /**
506       Indicates that locks of this type are affected by
507       the max_write_lock_count limit.
508     */
509     bool m_is_affected_by_max_write_lock_count;
510 
511     /**
512       Pointer to a static method which determines if the type of lock
513       requested requires notification of conflicting locks. NULL if there
514       are no lock types requiring notification.
515     */
516     bool (*m_needs_notification)(const MDL_ticket *ticket);
517     /**
518       Pointer to a static method which allows notification of owners of
519       conflicting locks about the fact that a type of lock requiring
520       notification was requested.
521     */
522     void (*m_notify_conflicting_locks)(MDL_context *ctx, MDL_lock *lock);
523     /**
524       Pointer to a static method which converts information about
525       locks granted using "fast" path from fast_path_state_t
526       representation to bitmap of lock types.
527     */
528     bitmap_t (*m_fast_path_granted_bitmap)(const MDL_lock &lock);
529     /**
530       Pointer to a static method which determines if waiting for the lock
531       should be aborted when when connection is lost. NULL if locks of
532       this type don't require such aborts.
533     */
534     bool (*m_needs_connection_check)(const MDL_lock *lock);
535   };
536 
537 public:
538   /** The key of the object (data) being protected. */
539   MDL_key key;
540   /**
541     Read-write lock protecting this lock context.
542 
543     @note The fact that we use read-write lock prefers readers here is
544           important as deadlock detector won't work correctly otherwise.
545 
546           For example, imagine that we have following waiters graph:
547 
548                        ctxA -> obj1 -> ctxB -> obj1 -|
549                         ^                            |
550                         |----------------------------|
551 
552           and both ctxA and ctxB start deadlock detection process:
553 
554             ctxA read-locks obj1             ctxB read-locks obj2
555             ctxA goes deeper                 ctxB goes deeper
556 
557           Now ctxC comes in who wants to start waiting on obj1, also
558           ctxD comes in who wants to start waiting on obj2.
559 
560             ctxC tries to write-lock obj1   ctxD tries to write-lock obj2
561             ctxC is blocked                 ctxD is blocked
562 
563           Now ctxA and ctxB resume their search:
564 
565             ctxA tries to read-lock obj2    ctxB tries to read-lock obj1
566 
567           If m_rwlock prefers writes (or fair) both ctxA and ctxB would be
568           blocked because of pending write locks from ctxD and ctxC
569           correspondingly. Thus we will get a deadlock in deadlock detector.
570           If m_wrlock prefers readers (actually ignoring pending writers is
571           enough) ctxA and ctxB will continue and no deadlock will occur.
572   */
573   mysql_prlock_t m_rwlock;
574 
incompatible_granted_types_bitmap() const575   const bitmap_t *incompatible_granted_types_bitmap() const
576   {
577     return m_strategy->m_granted_incompatible;
578   }
579 
incompatible_waiting_types_bitmap() const580   const bitmap_t *incompatible_waiting_types_bitmap() const
581   {
582     return
583       m_strategy->m_waiting_incompatible[m_current_waiting_incompatible_idx];
584   }
585 
586   /**
587     Get index of priority matrice in MDL_lock_strategy::m_waiting_incompatible
588     array which corresponds to current values of the m_piglet_lock_count and
589     m_hog_lock_count counters and the max_write_lock_count threshold.
590   */
get_incompatible_waiting_types_bitmap_idx() const591   uint get_incompatible_waiting_types_bitmap_idx() const
592   {
593     mysql_prlock_assert_write_owner(&m_rwlock);
594     /*
595       To prevent starvation for lock types with lower priority use:
596 
597       *) MDL_lock_strategy::m_waiting_incompatible[0] matrice by default.
598       *) MDL_lock_strategy::m_waiting_incompatible[1] when the number of
599          successively granted "piglet" requests exceeds max_write_lock_count.
600       *) MDL_lock_strategy::m_waiting_incompatible[2] when the number of
601          successively granted "hog" requests exceeds max_write_lock_count.
602       *) MDL_lock_strategy::m_waiting_incompatible[3] when both "piglet" and
603          "hog" counters exceed this limit.
604     */
605     uint idx= 0;
606     if (m_piglet_lock_count >= max_write_lock_count)
607       idx+= 1;
608     if (m_hog_lock_count >= max_write_lock_count)
609       idx+= 2;
610     return idx;
611   }
612 
613   /**
614     Switch priority matrice for the MDL_lock object if m_piglet_lock_count or/
615     and m_hog_lock_count counters have crossed max_write_lock_count threshold.
616 
617     @returns true - if priority matrice has been changed, false - otherwise.
618   */
switch_incompatible_waiting_types_bitmap_if_needed()619   bool switch_incompatible_waiting_types_bitmap_if_needed()
620   {
621     mysql_prlock_assert_write_owner(&m_rwlock);
622 
623     uint new_idx= get_incompatible_waiting_types_bitmap_idx();
624     if (m_current_waiting_incompatible_idx == new_idx)
625       return false;
626     m_current_waiting_incompatible_idx= new_idx;
627     return true;
628   }
629 
630   bool has_pending_conflicting_lock(enum_mdl_type type);
631 
632   bool can_grant_lock(enum_mdl_type type,
633                       const MDL_context *requestor_ctx) const;
634 
635   void reschedule_waiters();
636 
637   void remove_ticket(MDL_context *ctx, LF_PINS *pins,
638                      Ticket_list MDL_lock::*queue,
639                      MDL_ticket *ticket);
640 
641   bool visit_subgraph(MDL_ticket *waiting_ticket,
642                       MDL_wait_for_graph_visitor *gvisitor);
643 
needs_notification(const MDL_ticket * ticket) const644   bool needs_notification(const MDL_ticket *ticket) const
645   {
646     return m_strategy->m_needs_notification ?
647            m_strategy->m_needs_notification(ticket) : false;
648   }
649 
notify_conflicting_locks(MDL_context * ctx)650   void notify_conflicting_locks(MDL_context *ctx)
651   {
652     if (m_strategy->m_notify_conflicting_locks)
653       m_strategy->m_notify_conflicting_locks(ctx, this);
654   }
655 
needs_connection_check() const656   bool needs_connection_check() const
657   {
658     return m_strategy->m_needs_connection_check ?
659            m_strategy->m_needs_connection_check(this) : false;
660   }
661 
662   inline static bool needs_hton_notification(MDL_key::enum_mdl_namespace
663                                              mdl_namespace);
664 
is_affected_by_max_write_lock_count() const665   bool is_affected_by_max_write_lock_count() const
666   {
667     return m_strategy->m_is_affected_by_max_write_lock_count;
668   }
669 
670   /**
671     If we just have granted a lock of "piglet" or "hog" type and there are
672     pending lower priority locks, increase the appropriate counter. If this
673     counter now exceeds the max_write_lock_count threshold, switch priority
674     matrice for the MDL_lock object.
675 
676     @returns true - if priority matrice has been changed, false - otherwise.
677   */
count_piglets_and_hogs(enum_mdl_type type)678   bool count_piglets_and_hogs(enum_mdl_type type)
679   {
680     mysql_prlock_assert_write_owner(&m_rwlock);
681 
682     if ((MDL_BIT(type) & MDL_OBJECT_HOG_LOCK_TYPES) != 0)
683     {
684       if (m_waiting.bitmap() & ~MDL_OBJECT_HOG_LOCK_TYPES)
685       {
686         m_hog_lock_count++;
687         if (switch_incompatible_waiting_types_bitmap_if_needed())
688           return true;
689       }
690     }
691     else if (type == MDL_SHARED_WRITE)
692     {
693       if (m_waiting.bitmap() & MDL_BIT(MDL_SHARED_READ_ONLY))
694       {
695         m_piglet_lock_count++;
696         if (switch_incompatible_waiting_types_bitmap_if_needed())
697           return true;
698       }
699     }
700     return false;
701   }
702 
703   /**
704     @returns "Fast path" increment for request for "unobtrusive" type
705               of lock, 0 - if it is request for "obtrusive" type of
706               lock.
707 
708     @note We split all lock types for each of MDL namespaces
709           in two sets:
710 
711           A) "unobtrusive" lock types
712             1) Each type from this set should be compatible with all other
713                types from the set (including itself).
714             2) These types should be common for DML operations
715 
716           Our goal is to optimize acquisition and release of locks of this
717           type by avoiding complex checks and manipulations on m_waiting/
718           m_granted bitmaps/lists. We replace them with a check of and
719           increment/decrement of integer counters.
720           We call the latter type of acquisition/release "fast path".
721           Use of "fast path" reduces the size of critical section associated
722           with MDL_lock::m_rwlock lock in the common case and thus increases
723           scalability.
724 
725           The amount by which acquisition/release of specific type
726           "unobtrusive" lock increases/decreases packed counter in
727           MDL_lock::m_fast_path_state is returned by this function.
728 
729           B) "obtrusive" lock types
730             1) Granted or pending lock of those type is incompatible with
731                some other types of locks or with itself.
732             2) Not common for DML operations
733 
734           These locks have to be always acquired involving manipulations on
735           m_waiting/m_granted bitmaps/lists, i.e. we have to use "slow path"
736           for them. Moreover in the presence of active/pending locks from
737           "obtrusive" set we have to acquire using "slow path" even locks of
738           "unobtrusive" type.
739 
740     @sa MDL_scoped_lock/MDL_object_lock::m_unobtrusive_lock_increment for
741         definitions of these sets for scoped and per-object locks.
742   */
743   inline static fast_path_state_t
744     get_unobtrusive_lock_increment(const MDL_request *request);
745 
746   /**
747     @returns "Fast path" increment if type of lock is "unobtrusive" type,
748               0 - if it is "obtrusive" type of lock.
749   */
get_unobtrusive_lock_increment(enum_mdl_type type) const750   fast_path_state_t get_unobtrusive_lock_increment(enum_mdl_type type) const
751   {
752     return m_strategy->m_unobtrusive_lock_increment[type];
753   }
754 
755   /**
756     Check if type of lock requested is "obtrusive" type of lock.
757 
758     @sa MDL_lock::get_unobtrusive_lock_increment() description.
759   */
is_obtrusive_lock(enum_mdl_type type) const760   bool is_obtrusive_lock(enum_mdl_type type) const
761   {
762     return get_unobtrusive_lock_increment(type) == 0;
763   }
764 
765   /**
766     Return set of types of lock requests which were granted using
767     "fast path" algorithm in the bitmap_t form.
768 
769     This method is only called from MDL_lock::can_grant_lock() and its
770     return value is only important when we are trying to figure out if
771     we can grant an obtrusive lock. But this means that the HAS_OBTRUSIVE
772     flag is set so all changes to m_fast_path_state happen under protection
773     of MDL_lock::m_rwlock (see invariant [INV1]).
774     Since can_grant_lock() is called only when MDL_lock::m_rwlock is held,
775     it is safe to do an ordinary read of m_fast_path_state here.
776   */
fast_path_granted_bitmap() const777   bitmap_t fast_path_granted_bitmap() const
778   {
779     return m_strategy->m_fast_path_granted_bitmap(*this);
780   }
781 
782   /** List of granted tickets for this lock. */
783   Ticket_list m_granted;
784   /** Tickets for contexts waiting to acquire a lock. */
785   Ticket_list m_waiting;
786 
787 private:
788   /**
789     Number of times high priority, "hog" lock requests (X, SNRW, SNW) have been
790     granted while lower priority lock requests (all other types) were waiting.
791     Currently used only for object locks. Protected by m_rwlock lock.
792   */
793   ulong m_hog_lock_count;
794   /**
795     Number of times high priority, "piglet" lock requests (SW) have been
796     granted while locks requests with lower priority (SRO) were waiting.
797     Currently used only for object locks. Protected by m_rwlock lock.
798   */
799   ulong m_piglet_lock_count;
800   /**
801     Index of one of the MDL_lock_strategy::m_waiting_incompatible
802     arrays which represents the current priority matrice.
803   */
804   uint m_current_waiting_incompatible_idx;
805 
806 public:
807 
808   /**
809     Do "expensive" part of MDL_lock object initialization,
810     Called by LF_ALLOCATOR for each newly malloc()'ed MDL_lock object, is not
811     called in cases when LF_ALLOCATOR decides to reuse object which was
812     returned to it earlier. "Full" initialization happens later by calling
813     MDL_lock::reinit(). So @sa MDL_lock::reiniti()
814   */
MDL_lock()815   MDL_lock()
816     : m_obtrusive_locks_granted_waiting_count(0)
817   {
818     mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock);
819   }
820 
821   inline void reinit(const MDL_key *mdl_key);
822 
~MDL_lock()823   ~MDL_lock()
824   {
825     mysql_prlock_destroy(&m_rwlock);
826   }
827 
828   inline static MDL_lock *create(const MDL_key *key);
829   inline static void destroy(MDL_lock *lock);
830 
831   inline MDL_context *get_lock_owner() const;
832 
833 public:
834   /**
835     Number of granted or waiting lock requests of "obtrusive" type.
836     Also includes "obtrusive" lock requests for which we about to check
837     if they can be granted.
838 
839 
840     @sa MDL_lock::get_unobtrusive_lock_increment() description.
841 
842     @note This number doesn't include "unobtrusive" locks which were acquired
843           using "slow path".
844   */
845   uint m_obtrusive_locks_granted_waiting_count;
846   /**
847     Flag in MDL_lock::m_fast_path_state that indicates that the MDL_lock
848     object was marked for destruction and will be destroyed once all threads
849     referencing to it through hazard pointers have unpinned it.
850     Set using atomic compare-and-swap AND under protection of
851     MDL_lock::m_rwlock lock.
852     Thanks to this can be read either by using atomic compare-and-swap OR
853     using ordinary read under protection of MDL_lock::m_rwlock lock.
854   */
855   static const fast_path_state_t IS_DESTROYED=  1ULL << 62;
856   /**
857     Flag in MDL_lock::m_fast_path_state that indicates that there are
858     "obtrusive" locks which are granted, waiting or for which we are
859     about to check if they can be granted.
860     Corresponds to "MDL_lock::m_obtrusive_locks_granted_waiting_count == 0"
861     predicate.
862     Set using atomic compare-and-swap AND under protection of
863     MDL_lock::m_rwlock lock.
864     Thanks to this can be read either by using atomic compare-and-swap OR
865     using ordinary read under protection of MDL_lock::m_rwlock lock.
866 
867     Invariant [INV1]: When this flag is set all changes to m_fast_path_state
868     member has to be done under protection of m_rwlock lock.
869   */
870   static const fast_path_state_t HAS_OBTRUSIVE= 1ULL << 61;
871   /**
872     Flag in MDL_lock::m_fast_path_state that indicates that there are
873     "slow" path locks which are granted, waiting or for which we are
874     about to check if they can be granted.
875     Corresponds to MDL_lock::m_granted/m_waiting lists being non-empty
876     (except special case in MDL_context::try_acquire_lock()).
877     Set using atomic compare-and-swap AND under protection of m_rwlock
878     lock. The latter is necessary because value of this flag needs to be
879     synchronized with contents of MDL_lock::m_granted/m_waiting lists.
880   */
881   static const fast_path_state_t HAS_SLOW_PATH= 1ULL << 60;
882   /**
883     Combination of IS_DESTROYED/HAS_OBTRUSIVE/HAS_SLOW_PATH flags and packed
884     counters of specific types of "unobtrusive" locks which were granted using
885     "fast path".
886 
887     @sa MDL_scoped_lock::m_unobtrusive_lock_increment and
888         MDL_object_lock::m_unobtrusive_lock_increment for details about how
889         counts of different types of locks are packed into this field.
890 
891     @note Doesn't include "unobtrusive" locks granted using "slow path".
892 
893     @note We use combination of atomic operations and protection by
894           MDL_lock::m_rwlock lock to work with this member:
895 
896           * Write and Read-Modify-Write operations are always carried out
897             atomically. This is necessary to avoid lost updates on 32-bit
898             platforms among other things.
899           * In some cases Reads can be done non-atomically because we don't
900             really care about value which they will return (for example,
901             if further down the line there will be an atomic compare-and-swap
902             operation, which will validate this value and provide the correct
903             value if the validation will fail).
904           * In other cases Reads can be done non-atomically since they happen
905             under protection of MDL_lock::m_rwlock and there is some invariant
906             which ensures that concurrent updates of the m_fast_path_state
907             member can't happen while  MDL_lock::m_rwlock is held
908             (@sa IS_DESTROYED, HAS_OBTRUSIVE, HAS_SLOW_PATH).
909 
910     @note IMPORTANT!!!
911           In order to enforce the above rules and other invariants,
912           MDL_lock::m_fast_path_state should not be updated directly.
913           Use fast_path_state_cas()/add()/reset() wrapper methods instead.
914 
915     @note Needs to be volatile in order to be compatible with our
916           my_atomic_*() API.
917   */
918   volatile fast_path_state_t m_fast_path_state;
919 
920   /**
921     Wrapper for my_atomic_cas64 operation on m_fast_path_state member
922     which enforces locking and other invariants.
923   */
fast_path_state_cas(fast_path_state_t * old_state,fast_path_state_t new_state)924   bool fast_path_state_cas(fast_path_state_t *old_state,
925                            fast_path_state_t new_state)
926   {
927     /*
928       IS_DESTROYED, HAS_OBTRUSIVE and HAS_SLOW_PATH flags can be set or
929       cleared only while holding MDL_lock::m_rwlock lock.
930       If HAS_SLOW_PATH flag is set all changes to m_fast_path_state
931       should happen under protection of MDL_lock::m_rwlock ([INV1]).
932     */
933 #if !defined(NDEBUG)
934     if (((*old_state & (IS_DESTROYED | HAS_OBTRUSIVE | HAS_SLOW_PATH)) !=
935          (new_state & (IS_DESTROYED | HAS_OBTRUSIVE | HAS_SLOW_PATH))) ||
936         *old_state & HAS_OBTRUSIVE)
937     {
938       mysql_prlock_assert_write_owner(&m_rwlock);
939     }
940 #endif
941     /*
942       We should not change state of destroyed object
943       (fast_path_state_reset() being exception).
944     */
945     assert(! (*old_state & IS_DESTROYED));
946 
947     return my_atomic_cas64(&m_fast_path_state, old_state, new_state);
948   }
949 
950   /**
951     Wrapper for my_atomic_add64 operation on m_fast_path_state member
952     which enforces locking and other invariants.
953   */
fast_path_state_add(fast_path_state_t value)954   fast_path_state_t fast_path_state_add(fast_path_state_t value)
955   {
956     /*
957       Invariant [INV1] requires all changes to m_fast_path_state happen
958       under protection of m_rwlock if HAS_OBTRUSIVE flag is set.
959       Since this operation doesn't check this flag it can be called only
960       under protection of m_rwlock.
961     */
962     mysql_prlock_assert_write_owner(&m_rwlock);
963 
964     fast_path_state_t old_state= my_atomic_add64(&m_fast_path_state, value);
965 
966     /*
967       We should not change state of destroyed object
968       (fast_path_state_reset() being exception).
969     */
970     assert(! (old_state & IS_DESTROYED));
971     return old_state;
972   }
973 
974   /**
975     Wrapper for resetting m_fast_path_state enforcing locking invariants.
976   */
fast_path_state_reset()977   void fast_path_state_reset()
978   {
979     /* HAS_DESTROYED flag can be cleared only under protection of m_rwlock. */
980     mysql_prlock_assert_write_owner(&m_rwlock);
981     my_atomic_store64(&m_fast_path_state, 0);
982   }
983 
984   /**
985     Pointer to strategy object which defines how different types of lock
986     requests should be handled for the namespace to which this lock belongs.
987     @sa MDL_lock::m_scoped_lock_strategy and MDL_lock:m_object_lock_strategy.
988   */
989   const MDL_lock_strategy *m_strategy;
990 
991   /**
992     Get bitmap of "unobtrusive" locks granted using "fast path" algorithm
993     for scoped locks.
994 
995     @sa MDL_lock::fast_path_granted_bitmap() for explanation about why it
996         is safe to use non-atomic read of MDL_lock::m_fast_path_state here.
997   */
scoped_lock_fast_path_granted_bitmap(const MDL_lock & lock)998   static bitmap_t scoped_lock_fast_path_granted_bitmap(const MDL_lock &lock)
999   {
1000     return (lock.m_fast_path_state & 0xFFFFFFFFFFFFFFFULL) ?
1001             MDL_BIT(MDL_INTENTION_EXCLUSIVE) : 0;
1002   }
1003 
1004   /**
1005     Check if we are requesting X lock on the object, so threads holding
1006     conflicting S/SH metadata locks on it need to be notified.
1007 
1008     @sa MDL_lock::object_lock_notify_conflicting_locks.
1009   */
object_lock_needs_notification(const MDL_ticket * ticket)1010   static bool object_lock_needs_notification(const MDL_ticket *ticket)
1011   {
1012     return (ticket->get_type() == MDL_EXCLUSIVE);
1013   }
1014   static void object_lock_notify_conflicting_locks(MDL_context *ctx,
1015                                                    MDL_lock *lock);
1016   /**
1017     Get bitmap of "unobtrusive" locks granted using "fast path" algorithm
1018     for per-object locks.
1019 
1020     @sa MDL_lock::fast_path_granted_bitmap() for explanation about why it
1021         is safe to use non-atomic read of MDL_lock::m_fast_path_state here.
1022   */
object_lock_fast_path_granted_bitmap(const MDL_lock & lock)1023   static bitmap_t object_lock_fast_path_granted_bitmap(const MDL_lock &lock)
1024   {
1025     bitmap_t result= 0;
1026     fast_path_state_t fps= lock.m_fast_path_state;
1027     if (fps & 0xFFFFFULL)
1028       result|= MDL_BIT(MDL_SHARED);
1029     if (fps & (0xFFFFFULL << 20))
1030       result|= MDL_BIT(MDL_SHARED_READ);
1031     if (fps & (0xFFFFFULL << 40))
1032       result|= MDL_BIT(MDL_SHARED_WRITE);
1033     return result;
1034   }
1035 
1036   /**
1037     Check if MDL_lock object represents user-level lock or locking service
1038     lock, so threads waiting for it need to check if connection is lost
1039     and abort waiting when it is.
1040   */
object_lock_needs_connection_check(const MDL_lock * lock)1041   static bool object_lock_needs_connection_check(const MDL_lock *lock)
1042   {
1043     return (lock->key.mdl_namespace() == MDL_key::USER_LEVEL_LOCK ||
1044             lock->key.mdl_namespace() == MDL_key::LOCKING_SERVICE);
1045   }
1046 
1047   /**
1048     Bitmap with "hog" lock types for object locks.
1049 
1050     Locks of these types can easily starve out lower priority locks.
1051     To prevent this we only grant them max_write_lock_count times in
1052     a row while other lock types are waiting.
1053   */
1054   static const bitmap_t MDL_OBJECT_HOG_LOCK_TYPES=
1055                           (MDL_BIT(MDL_SHARED_NO_WRITE) |
1056                            MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1057                            MDL_BIT(MDL_EXCLUSIVE));
1058 
1059 
1060   static const MDL_lock_strategy m_scoped_lock_strategy;
1061   static const MDL_lock_strategy m_object_lock_strategy;
1062 };
1063 
1064 
1065 static MDL_map mdl_locks;
1066 
1067 
1068 extern "C"
1069 {
1070 static uchar *
mdl_locks_key(const uchar * record,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))1071 mdl_locks_key(const uchar *record, size_t *length,
1072               my_bool not_used MY_ATTRIBUTE((unused)))
1073 {
1074   MDL_lock *lock=(MDL_lock*) record;
1075   *length= lock->key.length();
1076   return (uchar*) lock->key.ptr();
1077 }
1078 } /* extern "C" */
1079 
1080 
1081 /**
1082   Initialize the metadata locking subsystem.
1083 
1084   This function is called at server startup.
1085 
1086   In particular, initializes the new global mutex and
1087   the associated condition variable: LOCK_mdl and COND_mdl.
1088   These locking primitives are implementation details of the MDL
1089   subsystem and are private to it.
1090 */
1091 
mdl_init()1092 void mdl_init()
1093 {
1094   assert(! mdl_initialized);
1095   mdl_initialized= TRUE;
1096 
1097 #ifdef HAVE_PSI_INTERFACE
1098   init_mdl_psi_keys();
1099 #endif
1100 
1101   mdl_locks.init();
1102 }
1103 
1104 
1105 /**
1106   Release resources of metadata locking subsystem.
1107 
1108   Destroys the global mutex and the condition variable.
1109   Called at server shutdown.
1110 */
1111 
mdl_destroy()1112 void mdl_destroy()
1113 {
1114   if (mdl_initialized)
1115   {
1116     mdl_initialized= FALSE;
1117     mdl_locks.destroy();
1118   }
1119 }
1120 
1121 
1122 /**
1123   Get number of unused MDL_lock objects in MDL_map cache.
1124   Mostly needed for unit-testing.
1125 */
1126 
mdl_get_unused_locks_count()1127 int32 mdl_get_unused_locks_count()
1128 {
1129   return mdl_locks.get_unused_locks_count();
1130 }
1131 
1132 
1133 extern "C"
1134 {
mdl_lock_cons(uchar * arg)1135 static void mdl_lock_cons(uchar *arg)
1136 {
1137   new (arg+LF_HASH_OVERHEAD) MDL_lock();
1138 }
1139 
mdl_lock_dtor(uchar * arg)1140 static void mdl_lock_dtor(uchar *arg)
1141 {
1142   MDL_lock *lock= (MDL_lock *)(arg+LF_HASH_OVERHEAD);
1143   lock->~MDL_lock();
1144 }
1145 
mdl_lock_reinit(uchar * dst_arg,const uchar * src_arg)1146 static void mdl_lock_reinit(uchar *dst_arg, const uchar *src_arg)
1147 {
1148   MDL_lock *dst= (MDL_lock *)dst_arg;
1149   const MDL_key *src= (const MDL_key *)src_arg;
1150   dst->reinit(src);
1151 }
1152 
1153 /**
1154   Adapter function which allows to use murmur3 with LF_HASH implementation.
1155 */
1156 
murmur3_adapter(const LF_HASH *,const uchar * key,size_t length)1157 static uint murmur3_adapter(const LF_HASH*, const uchar *key, size_t length)
1158 {
1159   return murmur3_32(key, length, 0);
1160 }
1161 
1162 } /* extern "C" */
1163 
1164 
1165 /** Initialize the container for all MDL locks. */
1166 
init()1167 void MDL_map::init()
1168 {
1169   MDL_key global_lock_key(MDL_key::GLOBAL, "", "");
1170   MDL_key commit_lock_key(MDL_key::COMMIT, "", "");
1171   MDL_key backup_lock_key(MDL_key::BACKUP, "", "");
1172   MDL_key binlog_lock_key(MDL_key::BINLOG, "", "");
1173 
1174   m_global_lock= MDL_lock::create(&global_lock_key);
1175   m_commit_lock= MDL_lock::create(&commit_lock_key);
1176   m_backup_lock= MDL_lock::create(&backup_lock_key);
1177   m_binlog_lock= MDL_lock::create(&binlog_lock_key);
1178 
1179   m_unused_lock_objects= 0;
1180 
1181   lf_hash_init2(&m_locks, sizeof(MDL_lock), LF_HASH_UNIQUE,
1182                 0, 0, mdl_locks_key, &my_charset_bin, &murmur3_adapter,
1183                 &mdl_lock_cons, &mdl_lock_dtor, &mdl_lock_reinit);
1184 }
1185 
1186 
1187 /**
1188   Destroy the container for all MDL locks.
1189   @pre It must be empty.
1190 */
1191 
destroy()1192 void MDL_map::destroy()
1193 {
1194   MDL_lock::destroy(m_backup_lock);
1195   MDL_lock::destroy(m_binlog_lock);
1196   MDL_lock::destroy(m_global_lock);
1197   MDL_lock::destroy(m_commit_lock);
1198 
1199   lf_hash_destroy(&m_locks);
1200 }
1201 
1202 
1203 /**
1204   Find MDL_lock object corresponding to the key.
1205 
1206   @param[in/out]  pins     LF_PINS to be used for pinning pointers during
1207                            look-up and returned MDL_lock object.
1208   @param[in]      mdl_key  Key for which MDL_lock object needs to be found.
1209   @param[out]     pinned   TRUE  - if MDL_lock object is pinned,
1210                            FALSE - if MDL_lock object doesn't require pinning
1211                                    (i.e. it is an object for GLOBAL or COMMIT
1212                                    namespaces).
1213 
1214   @retval MY_ERRPTR      - Failure (OOM)
1215   @retval other-non-NULL - MDL_lock object found.
1216   @retval NULL           - Object not found.
1217 */
1218 
find(LF_PINS * pins,const MDL_key * mdl_key,bool * pinned)1219 MDL_lock* MDL_map::find(LF_PINS *pins, const MDL_key *mdl_key, bool *pinned)
1220 {
1221   MDL_lock *lock;
1222 
1223   if (is_lock_object_singleton(mdl_key))
1224   {
1225     /*
1226       Avoid look up in m_locks hash when lock for GLOBAL or COMMIT namespace
1227       is requested. Return pointer to pre-allocated MDL_lock instance instead.
1228       Such an optimization allows us to avoid a few atomic operations for any
1229       statement changing data.
1230 
1231       It works since these namespaces contain only one element so keys
1232       for them look like '<namespace-id>\0\0'.
1233     */
1234     assert(mdl_key->length() == 3);
1235 
1236     switch (mdl_key->mdl_namespace())
1237     {
1238     case MDL_key::GLOBAL:
1239       lock= m_global_lock;
1240       break;
1241     case MDL_key::COMMIT:
1242       lock= m_commit_lock;
1243       break;
1244     case MDL_key::BACKUP:
1245       lock= m_backup_lock;
1246       break;
1247     case MDL_key::BINLOG:
1248       lock= m_binlog_lock;
1249       break;
1250     default:
1251       MY_ASSERT_UNREACHABLE();
1252     }
1253 
1254     *pinned= false;
1255 
1256     return lock;
1257   }
1258 
1259   lock= static_cast<MDL_lock *>(lf_hash_search(&m_locks, pins, mdl_key->ptr(),
1260                                           mdl_key->length()));
1261 
1262   if (lock == NULL || lock == MY_ERRPTR)
1263   {
1264     lf_hash_search_unpin(pins);
1265     *pinned= false; // Avoid warnings on older compilers.
1266     return lock;
1267   }
1268 
1269   *pinned= true;
1270 
1271   return lock;
1272 }
1273 
1274 
1275 /**
1276   Find MDL_lock object corresponding to the key, create it
1277   if it does not exist.
1278 
1279   @param[in/out]  pins     LF_PINS to be used for pinning pointers during
1280                            look-up and returned MDL_lock object.
1281   @param[in]      mdl_key  Key for which MDL_lock object needs to be found.
1282   @param[out]     pinned   TRUE  - if MDL_lock object is pinned,
1283                            FALSE - if MDL_lock object doesn't require pinning
1284                                    (i.e. it is an object for GLOBAL or COMMIT
1285                                    namespaces).
1286 
1287   @retval non-NULL - Success. MDL_lock instance for the key with
1288                      locked MDL_lock::m_rwlock.
1289   @retval NULL     - Failure (OOM).
1290 */
1291 
find_or_insert(LF_PINS * pins,const MDL_key * mdl_key,bool * pinned)1292 MDL_lock* MDL_map::find_or_insert(LF_PINS *pins, const MDL_key *mdl_key,
1293                                   bool *pinned)
1294 {
1295   MDL_lock *lock;
1296 
1297   while ((lock= find(pins, mdl_key, pinned)) == NULL)
1298   {
1299     /*
1300       MDL_lock for key isn't present in hash, try to insert new object.
1301       This can fail due to concurrent inserts.
1302     */
1303     int rc= lf_hash_insert(&m_locks, pins, mdl_key);
1304     if (rc == -1) /* If OOM. */
1305       return NULL;
1306     else if (rc == 0)
1307     {
1308       /*
1309         New MDL_lock object is not used yet. So we need to
1310         increment number of unused lock objects.
1311       */
1312       my_atomic_add32(&m_unused_lock_objects, 1);
1313     }
1314   }
1315   if (lock == MY_ERRPTR)
1316   {
1317     /* If OOM in lf_hash_search. */
1318     return NULL;
1319   }
1320 
1321   return lock;
1322 }
1323 
1324 
1325 extern "C"
1326 {
1327 /**
1328   Helper function which allows to check if MDL_lock object stored in LF_HASH
1329   is unused - i.e. doesn't have any locks on both "fast" and "slow" paths
1330   and is not marked as deleted.
1331 */
mdl_lock_match_unused(const uchar * arg)1332 static int mdl_lock_match_unused(const uchar *arg)
1333 {
1334   const MDL_lock *lock= (const MDL_lock *)arg;
1335   /*
1336     It is OK to check MDL_lock::m_fast_path_state non-atomically here
1337     since the fact that MDL_lock object is unused will be properly
1338     validated later anyway.
1339   */
1340   return (lock->m_fast_path_state == 0);
1341 }
1342 } /* extern "C" */
1343 
1344 
1345 /**
1346   Try to find random MDL_lock object in MDL_map for which there are no "fast"
1347   path nor "slow" path locks. If found - mark it as destroyed, remove object
1348   from MDL_map and return it back to allocator.
1349 
1350   @param[in]     ctx           Context on which behalf we are trying to remove
1351                                unused object. Primarily needed to generate
1352                                random value to be used for random dive into
1353                                the hash in MDL_map.
1354   @param[in/out] pins          Pins for the calling thread to be used for
1355                                hash lookup and deletion.
1356   @param[out]    unused_locks  Number of unused lock objects after operation.
1357 
1358   @note
1359     In reality MDL_lock object will be returned to allocator once it is no
1360     longer pinned by any threads.
1361 */
1362 
remove_random_unused(MDL_context * ctx,LF_PINS * pins,int32 * unused_locks)1363 void MDL_map::remove_random_unused(MDL_context *ctx, LF_PINS *pins,
1364                                    int32 *unused_locks)
1365 {
1366   DEBUG_SYNC(ctx->get_thd(), "mdl_remove_random_unused_before_search");
1367 
1368   /*
1369     Try to find an unused MDL_lock object by doing random dive into the hash.
1370     Since this method is called only when unused/total lock objects ratio is
1371     high enough, there is a good chance for this technique to succeed.
1372   */
1373   MDL_lock *lock= static_cast<MDL_lock *>(lf_hash_random_match(&m_locks,
1374                                             pins, &mdl_lock_match_unused,
1375                                             ctx->get_random()));
1376 
1377   if (lock == NULL || lock == MY_ERRPTR)
1378   {
1379     /*
1380       We were unlucky and no unused objects were found. This can happen,
1381       for example, if our random dive into LF_HASH was close to the tail
1382       of split-ordered list used in its implementation or if some other
1383       thread managed to destroy or start re-using MDL_lock object
1384       concurrently.
1385      */
1386     lf_hash_search_unpin(pins);
1387     *unused_locks= m_unused_lock_objects;
1388     return;
1389   }
1390 
1391   DEBUG_SYNC(ctx->get_thd(), "mdl_remove_random_unused_after_search");
1392 
1393   /*
1394     Acquire MDL_lock::m_rwlock to ensure that IS_DESTROYED flag is set
1395     atomically AND under protection of MDL_lock::m_rwlock, so it can be
1396     safely read using both atomics and ordinary read under protection of
1397     m_rwlock. This also means that it is safe to unpin MDL_lock object
1398     after we have checked its IS_DESTROYED flag if we keep m_rwlock lock.
1399   */
1400   mysql_prlock_wrlock(&lock->m_rwlock);
1401 
1402   if (lock->m_fast_path_state & MDL_lock::IS_DESTROYED)
1403   {
1404     /*
1405       Somebody has managed to mark MDL_lock object as destroyed before
1406       we have acquired MDL_lock::m_rwlock.
1407     */
1408     mysql_prlock_unlock(&lock->m_rwlock);
1409     lf_hash_search_unpin(pins);
1410     *unused_locks= m_unused_lock_objects;
1411     return;
1412   }
1413   lf_hash_search_unpin(pins);
1414 
1415   /*
1416     Atomically check that number of "fast path" and "slow path" locks is 0 and
1417     set IS_DESTROYED flag.
1418 
1419     This is the only place where we rely on the fact that our compare-and-swap
1420     operation can't spuriously fail i.e. is of strong kind.
1421   */
1422   MDL_lock::fast_path_state_t old_state= 0;
1423 
1424   if (lock->fast_path_state_cas(&old_state, MDL_lock::IS_DESTROYED))
1425   {
1426     /*
1427       There were no "fast path" or "slow path" references and we
1428       have successfully set IS_DESTROYED flag.
1429     */
1430     mysql_prlock_unlock(&lock->m_rwlock);
1431 
1432     DEBUG_SYNC(ctx->get_thd(), "mdl_remove_random_unused_after_is_destroyed_set");
1433 
1434     /*
1435       Even though other threads can't rely on the MDL_lock object being around
1436       once IS_DESTROYED flag is set, we know that it was not removed from
1437       the hash yet (as it is responsibility of the current thread, i.e. one
1438       which executes this MDL_map::remove_random_unused() call) and thus was
1439       not deallocated.
1440       And since lf_hash_delete() finds and pins the object for the key as its
1441       first step and keeps pins until its end it is safe to use MDL_lock::key
1442       as parameter to lf_hash_delete().
1443     */
1444     int rc= lf_hash_delete(&m_locks, pins, lock->key.ptr(), lock->key.length());
1445 
1446     /* The MDL_lock object must be present in the hash. */
1447     assert(rc != 1);
1448 
1449     if (rc == -1)
1450     {
1451       /*
1452         In unlikely case of OOM MDL_lock object stays in the hash. The best
1453         thing we can do is to reset IS_DESTROYED flag. The object will be
1454         destroyed either by further calls to lf_hash_delete() or by final
1455         call to lf_hash_destroy().
1456         Resetting needs to happen atomically AND under protection of
1457         MDL_lock::m_rwlock so it safe to read this flag both using atomics
1458         and ordinary reads under protection of m_rwlock lock.
1459       */
1460       mysql_prlock_wrlock(&lock->m_rwlock);
1461       lock->fast_path_state_reset();
1462       mysql_prlock_unlock(&lock->m_rwlock);
1463     }
1464     else
1465     {
1466       /* Success. */
1467       *unused_locks= my_atomic_add32(&m_unused_lock_objects, -1) - 1;
1468     }
1469   }
1470   else
1471   {
1472     /*
1473       Some other thread has managed to find and use this MDL_lock object after
1474       it has been found by the above call to lf_hash_random_match().
1475       There are/were "fast" or "slow path" references so MDL_lock object can't
1476       be deleted.
1477 
1478       Assert that compare-and-swap operation is of strong kind and can't
1479       fail spuriously.
1480     */
1481     assert(old_state != 0);
1482     mysql_prlock_unlock(&lock->m_rwlock);
1483     *unused_locks= m_unused_lock_objects;
1484   }
1485 }
1486 
1487 
1488 /**
1489   Initialize a metadata locking context.
1490 
1491   This is to be called when a new server connection is created.
1492 */
1493 
MDL_context()1494 MDL_context::MDL_context()
1495   :
1496   m_owner(NULL),
1497   m_needs_thr_lock_abort(FALSE),
1498   m_force_dml_deadlock_weight(false),
1499   m_waiting_for(NULL),
1500   m_pins(NULL),
1501   m_rand_state(UINT_MAX32)
1502 {
1503   mysql_prlock_init(key_MDL_context_LOCK_waiting_for, &m_LOCK_waiting_for);
1504 }
1505 
1506 
1507 /**
1508   Destroy metadata locking context.
1509 
1510   Assumes and asserts that there are no active or pending locks
1511   associated with this context at the time of the destruction.
1512 
1513   Currently does nothing. Asserts that there are no pending
1514   or satisfied lock requests. The pending locks must be released
1515   prior to destruction. This is a new way to express the assertion
1516   that all tables are closed before a connection is destroyed.
1517 */
1518 
destroy()1519 void MDL_context::destroy()
1520 {
1521   assert(m_tickets[MDL_STATEMENT].is_empty());
1522   assert(m_tickets[MDL_TRANSACTION].is_empty());
1523   assert(m_tickets[MDL_EXPLICIT].is_empty());
1524 
1525   mysql_prlock_destroy(&m_LOCK_waiting_for);
1526   if (m_pins)
1527     lf_hash_put_pins(m_pins);
1528 }
1529 
1530 
1531 /**
1532   Allocate pins which are necessary to work with MDL_map container
1533   if they are not allocated already.
1534 */
1535 
fix_pins()1536 bool MDL_context::fix_pins()
1537 {
1538   if (! m_pins)
1539     m_pins= mdl_locks.get_pins();
1540   return (m_pins == NULL);
1541 }
1542 
1543 
1544 /**
1545   Initialize a lock request.
1546 
1547   This is to be used for every lock request.
1548 
1549   Note that initialization and allocation are split into two
1550   calls. This is to allow flexible memory management of lock
1551   requests. Normally a lock request is stored in statement memory
1552   (e.g. is a member of struct TABLE_LIST), but we would also like
1553   to allow allocation of lock requests in other memory roots,
1554   for example in the grant subsystem, to lock privilege tables.
1555 
1556   The MDL subsystem does not own or manage memory of lock requests.
1557 
1558   @param  mdl_namespace  Id of namespace of object to be locked
1559   @param  db             Name of database to which the object belongs
1560   @param  name           Name of of the object
1561   @param  mdl_type       The MDL lock type for the request.
1562 */
1563 
init_with_source(MDL_key::enum_mdl_namespace mdl_namespace,const char * db_arg,const char * name_arg,enum_mdl_type mdl_type_arg,enum_mdl_duration mdl_duration_arg,const char * src_file,uint src_line)1564 void MDL_request::init_with_source(MDL_key::enum_mdl_namespace mdl_namespace,
1565                        const char *db_arg,
1566                        const char *name_arg,
1567                        enum_mdl_type mdl_type_arg,
1568                        enum_mdl_duration mdl_duration_arg,
1569                        const char *src_file,
1570                        uint src_line)
1571 {
1572   key.mdl_key_init(mdl_namespace, db_arg, name_arg);
1573   type= mdl_type_arg;
1574   duration= mdl_duration_arg;
1575   ticket= NULL;
1576   m_src_file= src_file;
1577   m_src_line= src_line;
1578 }
1579 
1580 
1581 /**
1582   Initialize a lock request using pre-built MDL_key.
1583 
1584   @sa MDL_request::init(namespace, db, name, type).
1585 
1586   @param key_arg       The pre-built MDL key for the request.
1587   @param mdl_type_arg  The MDL lock type for the request.
1588 */
1589 
init_by_key_with_source(const MDL_key * key_arg,enum_mdl_type mdl_type_arg,enum_mdl_duration mdl_duration_arg,const char * src_file,uint src_line)1590 void MDL_request::init_by_key_with_source(const MDL_key *key_arg,
1591                        enum_mdl_type mdl_type_arg,
1592                        enum_mdl_duration mdl_duration_arg,
1593                        const char *src_file,
1594                        uint src_line)
1595 {
1596   key.mdl_key_init(key_arg);
1597   type= mdl_type_arg;
1598   duration= mdl_duration_arg;
1599   ticket= NULL;
1600   m_src_file= src_file;
1601   m_src_line= src_line;
1602 }
1603 
1604 
1605 /**
1606   Auxiliary functions needed for creation/destruction of MDL_lock objects.
1607 */
1608 
create(const MDL_key * mdl_key)1609 inline MDL_lock *MDL_lock::create(const MDL_key *mdl_key)
1610 {
1611   MDL_lock *result= new (std::nothrow) MDL_lock();
1612   if (result)
1613     result->reinit(mdl_key);
1614   return result;
1615 }
1616 
1617 
destroy(MDL_lock * lock)1618 void MDL_lock::destroy(MDL_lock *lock)
1619 {
1620   delete lock;
1621 }
1622 
1623 
1624 /**
1625   Finalize initialization or re-initialize MDL_lock returned from
1626   LF_ALLOCATOR's cache to represent object identified by provided key.
1627 
1628   @note All non-static MDL_lock members:
1629         1) either have to be reinitialized here
1630            (like IS_DESTROYED flag in MDL_lock::m_fast_path_state).
1631         2) or need to be initialized in constructor AND returned to their
1632            pristine state once they are removed from MDL_map container
1633            (like MDL_lock::m_granted or MDL_lock::m_rwlock).
1634            Otherwise it is possible that we will end up in situation
1635            when "new" (actually reused) MDL_lock object inserted in
1636            LF_HASH will inherit some values from old object.
1637 */
1638 
reinit(const MDL_key * mdl_key)1639 inline void MDL_lock::reinit(const MDL_key *mdl_key)
1640 {
1641   key.mdl_key_init(mdl_key);
1642   switch (mdl_key->mdl_namespace())
1643   {
1644     case MDL_key::GLOBAL:
1645     case MDL_key::TABLESPACE:
1646     case MDL_key::SCHEMA:
1647     case MDL_key::COMMIT:
1648     case MDL_key::BACKUP:
1649     case MDL_key::BINLOG:
1650       m_strategy= &m_scoped_lock_strategy;
1651       break;
1652     default:
1653       m_strategy= &m_object_lock_strategy;
1654       break;
1655   }
1656   m_hog_lock_count= 0;
1657   m_piglet_lock_count= 0;
1658   m_current_waiting_incompatible_idx= 0;
1659   m_fast_path_state= 0;
1660   /*
1661     Check that we have clean "m_granted" and "m_waiting" sets/lists in both
1662     cases when we have fresh and re-used object.
1663   */
1664   assert(m_granted.is_empty() && m_waiting.is_empty());
1665   /* The same should be true for "m_obtrusive_locks_granted_waiting_count". */
1666   assert(m_obtrusive_locks_granted_waiting_count == 0);
1667 }
1668 
1669 
1670 /**
1671   @returns "Fast path" increment for request for "unobtrusive" type
1672             of lock, 0 - if it is request for "obtrusive" type of
1673             lock.
1674 
1675   @sa Description at method declaration for more details.
1676 */
1677 
1678 MDL_lock::fast_path_state_t
get_unobtrusive_lock_increment(const MDL_request * request)1679 MDL_lock::get_unobtrusive_lock_increment(const MDL_request *request)
1680 {
1681   switch (request->key.mdl_namespace())
1682   {
1683     case MDL_key::GLOBAL:
1684     case MDL_key::TABLESPACE:
1685     case MDL_key::SCHEMA:
1686     case MDL_key::COMMIT:
1687     case MDL_key::BACKUP:
1688     case MDL_key::BINLOG:
1689       return m_scoped_lock_strategy.m_unobtrusive_lock_increment[request->type];
1690     default:
1691       return m_object_lock_strategy.m_unobtrusive_lock_increment[request->type];
1692   }
1693 }
1694 
1695 
1696 /**
1697   Indicates whether object belongs to namespace which requires storage engine
1698   to be notified before acquiring and after releasing exclusive lock.
1699 */
1700 
1701 bool
needs_hton_notification(MDL_key::enum_mdl_namespace mdl_namespace)1702 MDL_lock::needs_hton_notification(MDL_key::enum_mdl_namespace mdl_namespace)
1703 {
1704   switch (mdl_namespace)
1705   {
1706     case MDL_key::TABLESPACE:
1707     case MDL_key::SCHEMA:
1708     case MDL_key::TABLE:
1709     case MDL_key::FUNCTION:
1710     case MDL_key::PROCEDURE:
1711     case MDL_key::TRIGGER:
1712     case MDL_key::EVENT:
1713       return true;
1714     default:
1715       return false;
1716   }
1717 }
1718 
1719 /**
1720   Auxiliary functions needed for creation/destruction of MDL_ticket
1721   objects.
1722 
1723   @todo This naive implementation should be replaced with one that saves
1724         on memory allocation by reusing released objects.
1725 */
1726 
create(MDL_context * ctx_arg,enum_mdl_type type_arg,enum_mdl_duration duration_arg)1727 MDL_ticket *MDL_ticket::create(MDL_context *ctx_arg, enum_mdl_type type_arg
1728 #ifndef NDEBUG
1729                                , enum_mdl_duration duration_arg
1730 #endif
1731                                )
1732 {
1733   return new (std::nothrow)
1734              MDL_ticket(ctx_arg, type_arg
1735 #ifndef NDEBUG
1736                         , duration_arg
1737 #endif
1738                         );
1739 }
1740 
1741 
destroy(MDL_ticket * ticket)1742 void MDL_ticket::destroy(MDL_ticket *ticket)
1743 {
1744   mysql_mdl_destroy(ticket->m_psi);
1745   ticket->m_psi= NULL;
1746 
1747   delete ticket;
1748 }
1749 
1750 
1751 /**
1752   Return the 'weight' of this ticket for the victim selection algorithm.
1753   Requests with lower weight are preferred to requests with higher weight
1754   when choosing a victim.
1755 
1756   @note When MDL_context::m_force_dml_deadlock_weight is set, the return value
1757         of this method is ignored and DEADLOCK_WEIGHT_DML is used for the
1758         context.
1759 */
1760 
get_deadlock_weight() const1761 uint MDL_ticket::get_deadlock_weight() const
1762 {
1763   /*
1764     Waits for user-level locks have lower weight than waits for locks
1765     typically acquired by DDL, so we don't abort DDL in case of deadlock
1766     involving user-level locks and DDL. Deadlock errors are not normally
1767     expected from DDL by users.
1768     Waits for user-level locks have higher weight than waits for locks
1769     acquired by DML, so we prefer to abort DML in case of deadlock involving
1770     user-level locks and DML. User-level locks are explicitly requested by
1771     user, so they are probably important for them. Plus users expect
1772     deadlocks from DML transactions and for DML statements executed in
1773     @@autocommit=1 mode back-off and retry algorithm hides deadlock errors.
1774   */
1775   if (m_lock->key.mdl_namespace() == MDL_key::USER_LEVEL_LOCK)
1776     return DEADLOCK_WEIGHT_ULL;
1777 
1778   /*
1779     Locks higher or equal to MDL_SHARED_UPGRADABLE:
1780     *) Are typically acquired for DDL and LOCK TABLES statements.
1781     *) Are often acquired in a way which doesn't allow simple release of
1782        locks and restart of lock acquisition process in case of deadlock
1783        (e.g. through lock_table_names() call).
1784 
1785     To avoid such statements getting aborted with ER_LOCK_DEADLOCK error
1786     we use the higher DEADLOCK_WEIGHT_DDL weight for them.
1787 
1788     Note that two DDL statements should not typically deadlock with each
1789     other since they normally acquire locks in the same order, thanks to
1790     to the fact that lock_table_names() uses MDL_context::acquire_locks()
1791     method which sorts lock requests before trying to acquire them.
1792 
1793     In cases when "strong" locks can be acquired out-of-order (e.g. for
1794     LOCK TABLES) we try to use DEADLOCK_WEIGHT_DML instead.
1795 
1796     TODO/FIXME: The below condition needs to be updated. The fact that a
1797                 lock from GLOBAL namespace is requested no longer means
1798                 that this is a DDL statement. There is a bug report about
1799                 this.
1800   */
1801   if (m_lock->key.mdl_namespace() == MDL_key::GLOBAL ||
1802       m_type >= MDL_SHARED_UPGRADABLE)
1803     return DEADLOCK_WEIGHT_DDL;
1804 
1805   return DEADLOCK_WEIGHT_DML;
1806 }
1807 
1808 
1809 /** Construct an empty wait slot. */
1810 
MDL_wait()1811 MDL_wait::MDL_wait()
1812   :m_wait_status(EMPTY)
1813 {
1814   mysql_mutex_init(key_MDL_wait_LOCK_wait_status, &m_LOCK_wait_status, NULL);
1815   mysql_cond_init(key_MDL_wait_COND_wait_status, &m_COND_wait_status);
1816 }
1817 
1818 
1819 /** Destroy system resources. */
1820 
~MDL_wait()1821 MDL_wait::~MDL_wait()
1822 {
1823   mysql_mutex_destroy(&m_LOCK_wait_status);
1824   mysql_cond_destroy(&m_COND_wait_status);
1825 }
1826 
1827 
1828 /**
1829   Set the status unless it's already set. Return FALSE if set,
1830   TRUE otherwise.
1831 */
1832 
set_status(enum_wait_status status_arg)1833 bool MDL_wait::set_status(enum_wait_status status_arg)
1834 {
1835   bool was_occupied= TRUE;
1836   mysql_mutex_lock(&m_LOCK_wait_status);
1837   if (m_wait_status == EMPTY)
1838   {
1839     was_occupied= FALSE;
1840     m_wait_status= status_arg;
1841     mysql_cond_signal(&m_COND_wait_status);
1842   }
1843   mysql_mutex_unlock(&m_LOCK_wait_status);
1844   return was_occupied;
1845 }
1846 
1847 
1848 /** Query the current value of the wait slot. */
1849 
get_status()1850 MDL_wait::enum_wait_status MDL_wait::get_status()
1851 {
1852   enum_wait_status result;
1853   mysql_mutex_lock(&m_LOCK_wait_status);
1854   result= m_wait_status;
1855   mysql_mutex_unlock(&m_LOCK_wait_status);
1856   return result;
1857 }
1858 
1859 
1860 /** Clear the current value of the wait slot. */
1861 
reset_status()1862 void MDL_wait::reset_status()
1863 {
1864   mysql_mutex_lock(&m_LOCK_wait_status);
1865   m_wait_status= EMPTY;
1866   mysql_mutex_unlock(&m_LOCK_wait_status);
1867 }
1868 
1869 
1870 /**
1871   Wait for the status to be assigned to this wait slot.
1872 
1873   @param owner           MDL context owner.
1874   @param abs_timeout     Absolute time after which waiting should stop.
1875   @param set_status_on_timeout TRUE  - If in case of timeout waiting
1876                                        context should close the wait slot by
1877                                        sending TIMEOUT to itself.
1878                                FALSE - Otherwise.
1879   @param wait_state_name  Thread state name to be set for duration of wait.
1880 
1881   @returns Signal posted.
1882 */
1883 
1884 MDL_wait::enum_wait_status
timed_wait(MDL_context_owner * owner,struct timespec * abs_timeout,bool set_status_on_timeout,const PSI_stage_info * wait_state_name)1885 MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
1886                      bool set_status_on_timeout,
1887                      const PSI_stage_info *wait_state_name)
1888 {
1889   PSI_stage_info old_stage;
1890   enum_wait_status result;
1891   int wait_result= 0;
1892 
1893   mysql_mutex_lock(&m_LOCK_wait_status);
1894 
1895   owner->ENTER_COND(&m_COND_wait_status, &m_LOCK_wait_status,
1896                     wait_state_name, & old_stage);
1897   thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK);
1898   while (!m_wait_status && !owner->is_killed() &&
1899          wait_result != ETIMEDOUT && wait_result != ETIME)
1900   {
1901     wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status,
1902                                       abs_timeout);
1903   }
1904   thd_wait_end(NULL);
1905 
1906   if (m_wait_status == EMPTY)
1907   {
1908     /*
1909       Wait has ended not due to a status being set from another
1910       thread but due to this connection/statement being killed or a
1911       time out.
1912       To avoid races, which may occur if another thread sets
1913       GRANTED status before the code which calls this method
1914       processes the abort/timeout, we assign the status under
1915       protection of the m_LOCK_wait_status, within the critical
1916       section. An exception is when set_status_on_timeout is
1917       false, which means that the caller intends to restart the
1918       wait.
1919     */
1920     if (owner->is_killed())
1921       m_wait_status= KILLED;
1922     else if (set_status_on_timeout)
1923       m_wait_status= TIMEOUT;
1924   }
1925   result= m_wait_status;
1926 
1927   mysql_mutex_unlock(&m_LOCK_wait_status);
1928   owner->EXIT_COND(& old_stage);
1929 
1930   return result;
1931 }
1932 
1933 /**
1934   Clear bit corresponding to the type of metadata lock in bitmap representing
1935   set of such types if list of tickets does not contain ticket with such type.
1936 
1937   @param[in,out]  bitmap  Bitmap representing set of types of locks.
1938   @param[in]      list    List to inspect.
1939   @param[in]      type    Type of metadata lock to look up in the list.
1940 */
1941 
clear_bit_if_not_in_list(enum_mdl_type type)1942 void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type type)
1943 {
1944   MDL_lock::Ticket_iterator it(m_list);
1945   const MDL_ticket *ticket;
1946 
1947   while ((ticket= it++))
1948     if (ticket->get_type() == type)
1949       return;
1950   m_bitmap&= ~ MDL_BIT(type);
1951 }
1952 
1953 
1954 /**
1955   Add ticket to MDL_lock's list of waiting requests and
1956   update corresponding bitmap of lock types.
1957 */
1958 
add_ticket(MDL_ticket * ticket)1959 void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
1960 {
1961   /*
1962     Ticket being added to the list must have MDL_ticket::m_lock set,
1963     since for such tickets methods accessing this member might be
1964     called by other threads.
1965   */
1966   assert(ticket->get_lock());
1967   /*
1968     Add ticket to the *back* of the queue to ensure fairness
1969     among requests with the same priority.
1970   */
1971   m_list.push_back(ticket);
1972   m_bitmap|= MDL_BIT(ticket->get_type());
1973 }
1974 
1975 
1976 /**
1977   Remove ticket from MDL_lock's list of requests and
1978   update corresponding bitmap of lock types.
1979 */
1980 
remove_ticket(MDL_ticket * ticket)1981 void MDL_lock::Ticket_list::remove_ticket(MDL_ticket *ticket)
1982 {
1983   m_list.remove(ticket);
1984   /*
1985     Check if waiting queue has another ticket with the same type as
1986     one which was removed. If there is no such ticket, i.e. we have
1987     removed last ticket of particular type, then we need to update
1988     bitmap of waiting ticket's types.
1989     Note that in most common case, i.e. when shared lock is removed
1990     from waiting queue, we are likely to find ticket of the same
1991     type early without performing full iteration through the list.
1992     So this method should not be too expensive.
1993   */
1994   clear_bit_if_not_in_list(ticket->get_type());
1995 }
1996 
1997 
1998 /**
1999   Determine waiting contexts which requests for the lock can be
2000   satisfied, grant lock to them and wake them up.
2001 
2002   @note Together with MDL_lock::add_ticket() this method implements
2003         fair scheduling among requests with the same priority.
2004         It tries to grant lock from the head of waiters list, while
2005         add_ticket() adds new requests to the back of this list.
2006 
2007 */
2008 
reschedule_waiters()2009 void MDL_lock::reschedule_waiters()
2010 {
2011   MDL_lock::Ticket_iterator it(m_waiting);
2012   MDL_ticket *ticket;
2013 
2014   /*
2015     Find the first (and hence the oldest) waiting request which
2016     can be satisfied (taking into account priority). Grant lock to it.
2017     Repeat the process for the remainder of waiters.
2018     Note we don't need to re-start iteration from the head of the
2019     list after satisfying the first suitable request as in our case
2020     all compatible types of requests have the same priority.
2021 
2022     TODO/FIXME: We should:
2023                 - Either switch to scheduling without priorities
2024                   which will allow to stop iteration through the
2025                   list of waiters once we found the first ticket
2026                   which can't be  satisfied
2027                 - Or implement some check using bitmaps which will
2028                   allow to stop iteration in cases when, e.g., we
2029                   grant SNRW lock and there are no pending S or
2030                   SH locks.
2031   */
2032   while ((ticket= it++))
2033   {
2034     if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))
2035     {
2036       if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))
2037       {
2038         /*
2039           Satisfy the found request by updating lock structures.
2040           It is OK to do so even after waking up the waiter since any
2041           session which tries to get any information about the state of
2042           this lock has to acquire MDL_lock::m_rwlock first and thus,
2043           when manages to do so, already sees an updated state of the
2044           MDL_lock object.
2045 
2046           It doesn't matter if we are dealing with "obtrusive" lock here,
2047           we are moving lock request from waiting to granted lists,
2048           so m_obtrusive_locks_granted_waiting_count should stay the same.
2049         */
2050         m_waiting.remove_ticket(ticket);
2051         m_granted.add_ticket(ticket);
2052 
2053         if (is_affected_by_max_write_lock_count())
2054         {
2055           /*
2056             Increase the counter of successively granted high priority "hog" or
2057             "piglet" locks, if we have granted one and there are pending
2058             lower priority locks.
2059           */
2060           if (count_piglets_and_hogs(ticket->get_type()))
2061           {
2062             /*
2063               Switch of priority matrice might have unblocked some lower-prio
2064               locks which are still compatible with the lock type we just have
2065               granted (for example, when we grant SNW lock and there are pending
2066               requests of SR type). Restart iteration to wake them up, otherwise
2067               we might get deadlocks.
2068             */
2069             it.rewind();
2070             continue;
2071           }
2072         }
2073       }
2074       /*
2075         If we could not update the wait slot of the waiter,
2076         it can be due to fact that its connection/statement was
2077         killed or it has timed out (i.e. the slot is not empty).
2078         Since in all such cases the waiter assumes that the lock was
2079         not been granted, we should keep the request in the waiting
2080         queue and look for another request to reschedule.
2081       */
2082     }
2083   }
2084 
2085   if (is_affected_by_max_write_lock_count())
2086   {
2087     /*
2088       Reset number of successively granted higher-prio "hog"/"piglet" locks
2089       if there are no pending lower-prio conflicting locks.
2090       This ensures:
2091       - That m_hog_lock_count/m_piglet_lock_count is correctly reset after
2092         a strong lock is released and weak locks are granted (or there are
2093         no other lock requests).
2094       - That the situation when SNW lock is granted along with some SR/SRO
2095         locks, but SW locks are still blocked is handled correctly.
2096       - That m_hog_lock_count/m_piglet_lock_count is zero in all cases
2097         when there are no pending weak locks (e.g. when weak locks are
2098         removed due to deadlock, being killed or timeout).
2099 
2100       Also switch priority matrice accordingly. Note that switch in
2101       this particular place doesn't require reschedule since:
2102 
2103       1) We never switch to a matrice which prefers lower priority locks
2104          more than "hog"/"piglet" locks here (this might have happened if
2105          MDL_lock::switch_incompatible_waiting_types_bitmap_if_needed()
2106          was used instead and max_write_lock_count was decreased
2107          concurrently).
2108       2) When we switch from matrice #1 (which prefers SRO over SW) to
2109          default matrice #0 only the priority of SW vs SRO requests changes.
2110          Since the switch happens only when there are no pending SRO
2111          locks, no reschedule is required.
2112       3) When we switch from matrice #2 (which prefers all non-"nog" over
2113          "hog" requests) to default matrice #0 only the priority of "hog" vs
2114          non-"hog" requests changes. But since this happens when there are
2115          no non-"hog" requests, no reschedule is required.
2116       4) When we switch from matrice #3 (which prefers SRO over SW and
2117          non-"hog"-minus-SW over "hog" locks) to default matrice #0 only
2118          the priority of non-"hog"-minus-SW vs "hog" and SRO vs SW changes
2119          (see invariant [INV3]). Since the switch happens only when there
2120          are no pending non-"hog"-minus-SW/SRO requests, no reschedule is
2121          required.
2122 
2123       Note that we might be switching priority matrice in a situation when we
2124       had pending SRO/non-"hog"/non-"hog"-minus-SW requests at the start of
2125       the call but they were granted during the loop. If some "piglet"/"hog"
2126       requests are compatible with those lower priority locks, they were
2127       granted as well. Those which were not compatible were not granted and
2128       should stay waiting until lower priority locks are released (in other
2129       words, the fact that a lock moved from pending to granted doesn't unblock
2130       additional requests, see invariant [INV2]).
2131     */
2132     if (m_current_waiting_incompatible_idx == 3)
2133     {
2134       /*
2135         We can't simply switch from matrice #3 to matrice #2 when there are no
2136         pending SRO locks, as that would allow a stream of concurrent SW and SRO
2137         requests to starve out "hog" locks when max_write_lock_count is set
2138         (there will be always pending SW or/and SRO locks in this case, so no
2139         switch back to matrice #0 will ever happen).
2140 
2141         So we switch from matrice #3 to #0 directly and ignore pending SW/SWLP
2142         locks. This is OK as situation when matrice #3 is active can only
2143         occur when there were max_write_lock_count SW locks granted recently
2144         (before switch from #0 -> #1 which preceded switch #3 or before switch
2145         #2 -> #3).
2146       */
2147       if ((m_waiting.bitmap() & ~(MDL_OBJECT_HOG_LOCK_TYPES |
2148                                   MDL_BIT(MDL_SHARED_WRITE) |
2149                                   MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO))) == 0)
2150       {
2151         m_piglet_lock_count= 0;
2152         m_hog_lock_count= 0;
2153         m_current_waiting_incompatible_idx= 0;
2154       }
2155     }
2156     else
2157     {
2158       if ((m_waiting.bitmap() & ~MDL_OBJECT_HOG_LOCK_TYPES) == 0)
2159       {
2160         m_hog_lock_count= 0;
2161         m_current_waiting_incompatible_idx&= ~2;
2162       }
2163       if ((m_waiting.bitmap() & MDL_BIT(MDL_SHARED_READ_ONLY)) == 0)
2164       {
2165         m_piglet_lock_count= 0;
2166         m_current_waiting_incompatible_idx&= ~1;
2167       }
2168     }
2169   }
2170 }
2171 
2172 
2173 /**
2174   Strategy instances to be used with scoped metadata locks (i.e. locks
2175   from GLOBAL, COMMIT, TABLESPACE and SCHEMA namespaces).
2176   The only locking modes which are supported at the moment are SHARED and
2177   INTENTION EXCLUSIVE and EXCLUSIVE.
2178 */
2179 
2180 const MDL_lock::MDL_lock_strategy MDL_lock::m_scoped_lock_strategy =
2181 {
2182   /**
2183     Compatibility (or rather "incompatibility") matrices for scoped metadata
2184     lock. Arrays of bitmaps which elements specify which granted/waiting locks
2185     are incompatible with type of lock being requested.
2186 
2187     The first array specifies if particular type of request can be satisfied
2188     if there is granted scoped lock of certain type.
2189 
2190                | Type of active   |
2191        Request |   scoped lock    |
2192         type   | IS(*)  IX   S  X |
2193       ---------+------------------+
2194       IS       |  +      +   +  + |
2195       IX       |  +      +   -  - |
2196       S        |  +      -   +  - |
2197       X        |  +      -   -  - |
2198 
2199     Here: "+" -- means that request can be satisfied
2200           "-" -- means that request can't be satisfied and should wait
2201 
2202     (*)  Since intention shared scoped locks are compatible with all other
2203          type of locks we don't even have any accounting for them.
2204 
2205     Note that relation between scoped locks and objects locks requested
2206     by statement is not straightforward and is therefore fully defined
2207     by SQL-layer.
2208     For example, in order to support global read lock implementation
2209     SQL-layer acquires IX lock in GLOBAL namespace for each statement
2210     that can modify metadata or data (i.e. for each statement that
2211     needs SW, SU, SNW, SNRW or X object locks). OTOH, to ensure that
2212     DROP DATABASE works correctly with concurrent DDL, IX metadata locks
2213     in SCHEMA namespace are acquired for DDL statements which can update
2214     metadata in the schema (i.e. which acquire SU, SNW, SNRW and X locks
2215     on schema objects) and aren't acquired for DML.
2216   */
2217   {
2218     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
2219     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE),
2220     0, 0, 0, 0, 0, 0, 0, 0,
2221     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) |
2222       MDL_BIT(MDL_INTENTION_EXCLUSIVE)
2223   },
2224   /**
2225     Each array in the next group specifies if a particular type of request can
2226     be satisfied if there is already a waiting request for the scoped lock of
2227     a certain type. I.e. each array specifies a matrice with priorities for
2228     different lock types.
2229 
2230     Scoped locks only use the first array which represents the "default"
2231     priority matrix. The remaing 3 matrices are not relevant for them.
2232 
2233                |    Pending      |
2234        Request |  scoped lock    |
2235         type   | IS(*)  IX  S  X |
2236       ---------+-----------------+
2237       IS       |  +      +  +  + |
2238       IX       |  +      +  -  - |
2239       S        |  +      +  +  - |
2240       X        |  +      +  +  + |
2241 
2242     Here the meaning of "+", "-" and (*) is the same as above.
2243   */
2244   {
2245     {
2246       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
2247       MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0, 0, 0
2248     },
2249     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2250     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2251     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
2252   },
2253   /**
2254     Array of increments for "unobtrusive" types of lock requests for scoped
2255     locks.
2256 
2257     @sa MDL_lock::get_unobtrusive_lock_increment().
2258 
2259     For scoped locks:
2260     - "unobtrusive" types: IX
2261     - "obtrusive" types: X and S
2262 
2263     We encode number of IX locks acquired using "fast path" in bits 0 .. 59
2264     of MDL_lock::m_fast_path_state.
2265   */
2266   { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
2267   /*
2268     In scoped locks, only IX lock request would starve because of X/S.
2269     But that is practically a very rare case. So we don't apply the
2270     max_write_lock_count limit to them.
2271   */
2272   false,
2273   /*
2274     Scoped locks doesn't require notification of owners of conflicting
2275     locks for any type of requests. Hence 'm_needs_notification' is NULL.
2276   */
2277   NULL,
2278   /*
2279     For the same reason, 'm_notify_conflicting_locks' is NULL for scoped locks.
2280   */
2281   NULL,
2282   &MDL_lock::scoped_lock_fast_path_granted_bitmap,
2283   /* Scoped locks never require connection check. */
2284   NULL
2285 };
2286 
2287 
2288 /**
2289   Strategy instance for per-object locks.
2290   Supports all locked modes except INTENTION EXCLUSIVE locks.
2291 */
2292 
2293 const MDL_lock::MDL_lock_strategy MDL_lock::m_object_lock_strategy =
2294 {
2295   /**
2296     Compatibility (or rather "incompatibility") matrices for per-object
2297     metadata lock. Arrays of bitmaps which elements specify which granted/
2298     waiting locks are incompatible with type of lock being requested.
2299 
2300     The first array specifies if particular type of request can be satisfied
2301     if there is granted lock of certain type.
2302 
2303        Request  |  Granted requests for lock            |
2304         type    | S  SH  SR  SW  SWLP  SU  SRO  SNW  SNRW  X  |
2305       ----------+---------------------------------------------+
2306       S         | +   +   +   +    +    +   +    +    +    -  |
2307       SH        | +   +   +   +    +    +   +    +    +    -  |
2308       SR        | +   +   +   +    +    +   +    +    -    -  |
2309       SW        | +   +   +   +    +    +   -    -    -    -  |
2310       SWLP      | +   +   +   +    +    +   -    -    -    -  |
2311       SU        | +   +   +   +    +    -   +    -    -    -  |
2312       SRO       | +   +   +   -    -    +   +    +    -    -  |
2313       SNW       | +   +   +   -    -    -   +    -    -    -  |
2314       SNRW      | +   +   -   -    -    -   -    -    -    -  |
2315       X         | -   -   -   -    -    -   -    -    -    -  |
2316 
2317     Here: "+" -- means that request can be satisfied
2318           "-" -- means that request can't be satisfied and should wait
2319 
2320     @note In cases then current context already has "stronger" type
2321           of lock on the object it will be automatically granted
2322           thanks to usage of the MDL_context::find_ticket() method.
2323 
2324     @note IX locks are excluded since they are not used for per-object
2325           metadata locks.
2326   */
2327   {
2328     0,
2329     MDL_BIT(MDL_EXCLUSIVE),
2330     MDL_BIT(MDL_EXCLUSIVE),
2331     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
2332     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2333       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2334     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2335       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2336     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2337       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
2338     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2339       MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) | MDL_BIT(MDL_SHARED_WRITE),
2340     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2341       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
2342       MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) | MDL_BIT(MDL_SHARED_WRITE),
2343     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2344       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
2345       MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) |
2346       MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ),
2347     MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2348       MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
2349       MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) |
2350       MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ) |
2351       MDL_BIT(MDL_SHARED_HIGH_PRIO) | MDL_BIT(MDL_SHARED)
2352   },
2353   /**
2354     Each array in the next group specifies if a particular type of request can
2355     be satisfied if there is a waiting request for the same lock of a certain
2356     type. In other words each array specifies a priority matrix for different
2357     lock types.
2358 
2359     We use each of the arrays depending on whether the number of successively
2360     granted "piglet" and "hog" lock requests exceed the max_write_lock_count
2361     threshold. This is necessary to avoid high priority lock requests starving
2362     out requests with lower priority.
2363 
2364     The first array in the group is used in default situation when both
2365     MDL_lock::m_piglet_lock_count and MDL_lock::m_hog_lock_count don't exceed
2366     the threshold.
2367 
2368     A priority matrice specified by it looks like:
2369 
2370        Request  |         Pending requests for lock          |
2371         type    | S  SH  SR  SW  SWLP  SU  SRO  SNW  SNRW  X |
2372       ----------+--------------------------------------------+
2373       S         | +   +   +   +    +    +   +    +     +   - |
2374       SH        | +   +   +   +    +    +   +    +     +   + |
2375       SR        | +   +   +   +    +    +   +    +     -   - |
2376       SW        | +   +   +   +    +    +   +    -     -   - |
2377       SWLP      | +   +   +   +    +    +   -    -     -   - |
2378       SU        | +   +   +   +    +    +   +    +     +   - |
2379       SRO       | +   +   +   -    +    +   +    +     -   - |
2380       SNW       | +   +   +   +    +    +   +    +     +   - |
2381       SNRW      | +   +   +   +    +    +   +    +     +   - |
2382       X         | +   +   +   +    +    +   +    +     +   + |
2383 
2384     Invariant [INV2]: for all priority matrices, if A is the set of
2385     incompatible waiting requests for a given request and B is the set
2386     of incompatible granted requests for the same request, then A will
2387     always be a subset of B. This means that moving a lock from waiting
2388     to granted state doesn't unblock additional requests.
2389     MDL_lock::reschedule_waiters() code relies on this.
2390   */
2391   {
2392     {
2393       0,
2394       MDL_BIT(MDL_EXCLUSIVE),
2395       0,
2396       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
2397       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2398         MDL_BIT(MDL_SHARED_NO_WRITE),
2399       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2400         MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2401       MDL_BIT(MDL_EXCLUSIVE),
2402       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2403         MDL_BIT(MDL_SHARED_WRITE),
2404       MDL_BIT(MDL_EXCLUSIVE),
2405       MDL_BIT(MDL_EXCLUSIVE),
2406       0
2407     },
2408     /**
2409       The second array in the group is used when the number of successively
2410       granted "piglet" (SW) locks exceeds max_write_lock_count.
2411 
2412       It is the same matrix as in the first case but with the SW lock type
2413       having lower priority than the SRO lock type.
2414     */
2415     {
2416       0,
2417       MDL_BIT(MDL_EXCLUSIVE),
2418       0,
2419       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
2420       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2421         MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2422       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2423         MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2424       MDL_BIT(MDL_EXCLUSIVE),
2425       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
2426       MDL_BIT(MDL_EXCLUSIVE),
2427       MDL_BIT(MDL_EXCLUSIVE),
2428       0
2429     },
2430     /**
2431       The third array in the group is used when the number of successively
2432       granted "hog" (SNW, SNRW, X) locks exceeds max_write_lock_count.
2433 
2434       In this case S, SH, SR, SW, SNRW, SRO and SU locks types have
2435       priority over all "hog" types.
2436     */
2437     {
2438       0,
2439       0,
2440       0,
2441       0,
2442       0,
2443       MDL_BIT(MDL_SHARED_READ_ONLY),
2444       0,
2445       MDL_BIT(MDL_SHARED_WRITE),
2446       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
2447       MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) | MDL_BIT(MDL_SHARED_WRITE),
2448       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
2449       MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO) |
2450       MDL_BIT(MDL_SHARED_WRITE) | MDL_BIT(MDL_SHARED_READ),
2451       static_cast<bitmap_t>(~MDL_OBJECT_HOG_LOCK_TYPES)
2452     },
2453     /**
2454       The fourth array in the group is used when both the number of successively
2455       granted "piglet" (SW) and the number of successively granted "hog"
2456       (SNW, SNRW, X) locks exceed max_write_lock_count.
2457 
2458       This matrice prefers SRO locks over SW/SWLP locks. And non-"hog" locks
2459       other than SW/SWLP over "hog" locks.
2460 
2461       Note that the fact that "hog" locks have the same priority vs SW/SWLP
2462       locks as in the default matrice (#0) is important and is relied upon in
2463       MDL_lock::reschedule_waiters(). This is invariant [INV3].
2464     */
2465     {
2466       0,
2467       0,
2468       0,
2469       0,
2470       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2471         MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2472       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
2473         MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
2474       0,
2475       0,
2476       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
2477       MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
2478       MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_READ),
2479       static_cast<bitmap_t>(~(MDL_OBJECT_HOG_LOCK_TYPES |
2480                             MDL_BIT(MDL_SHARED_WRITE) |
2481                             MDL_BIT(MDL_SHARED_WRITE_LOW_PRIO)))
2482     }
2483   },
2484   /**
2485     Array of increments for "unobtrusive" types of lock requests for per-object
2486     locks.
2487 
2488     @sa MDL_lock::get_unobtrusive_lock_increment().
2489 
2490     For per-object locks:
2491     - "unobtrusive" types: S, SH, SR and SW
2492     - "obtrusive" types: SU, SRO, SNW, SNRW, X
2493 
2494     Number of locks acquired using "fast path" are encoded in the following
2495     bits of MDL_lock::m_fast_path_state:
2496 
2497     - bits 0 .. 19  - S and SH (we don't differentiate them once acquired)
2498     - bits 20 .. 39 - SR
2499     - bits 40 .. 59 - SW and SWLP (we don't differentiate them once acquired)
2500 
2501     Overflow is not an issue as we are unlikely to support more than 2^20 - 1
2502     concurrent connections in foreseeable future.
2503 
2504     This encoding defines the below contents of increment array.
2505   */
2506   { 0, 1, 1, 1ULL << 20, 1ULL << 40, 1ULL << 40, 0, 0, 0, 0, 0 },
2507   /*
2508     To prevent starvation, "hog" and "piglet" lock types are only granted
2509     max_write_lock_count times in a row while conflicting lock types are
2510     waiting.
2511   */
2512   true,
2513   &MDL_lock::object_lock_needs_notification,
2514   &MDL_lock::object_lock_notify_conflicting_locks,
2515   &MDL_lock::object_lock_fast_path_granted_bitmap,
2516   &MDL_lock::object_lock_needs_connection_check
2517 };
2518 
2519 
2520 /**
2521   Check if request for the metadata lock can be satisfied given its
2522   current state.
2523 
2524   @param  type_arg             The requested lock type.
2525   @param  requestor_ctx        The MDL context of the requestor.
2526 
2527   @retval TRUE   Lock request can be satisfied
2528   @retval FALSE  There is some conflicting lock.
2529 
2530   @note In cases then current context already has "stronger" type
2531         of lock on the object it will be automatically granted
2532         thanks to usage of the MDL_context::find_ticket() method.
2533 */
2534 
2535 bool
can_grant_lock(enum_mdl_type type_arg,const MDL_context * requestor_ctx) const2536 MDL_lock::can_grant_lock(enum_mdl_type type_arg,
2537                          const MDL_context *requestor_ctx) const
2538 {
2539   bool can_grant= FALSE;
2540   bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
2541   bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
2542 
2543   /*
2544     New lock request can be satisfied iff:
2545     - There are no incompatible types of satisfied requests
2546     in other contexts
2547     - There are no waiting requests which have higher priority
2548     than this request.
2549   */
2550   if (!(m_waiting.bitmap() & waiting_incompat_map))
2551   {
2552     if (! (fast_path_granted_bitmap() & granted_incompat_map))
2553     {
2554       if (! (m_granted.bitmap() & granted_incompat_map))
2555         can_grant= TRUE;
2556       else
2557       {
2558         Ticket_iterator it(m_granted);
2559         MDL_ticket *ticket;
2560 
2561         /*
2562           There is an incompatible lock. Check that it belongs to some
2563           other context.
2564 
2565           If we are trying to acquire "unobtrusive" type of lock then the
2566           confliciting lock must be from "obtrusive" set, therefore it should
2567           have been acquired using "slow path" and should be present in
2568           m_granted list.
2569 
2570           If we are trying to acquire "obtrusive" type of lock then it can be
2571           either another "obtrusive" lock or "unobtrusive" type of lock
2572           acquired on "slow path" (can't be "unobtrusive" lock on fast path
2573           because of surrounding if-statement). In either case it should be
2574           present in m_granted list.
2575         */
2576         while ((ticket= it++))
2577         {
2578           if (ticket->get_ctx() != requestor_ctx &&
2579               ticket->is_incompatible_when_granted(type_arg))
2580             break;
2581         }
2582         if (ticket == NULL)             /* Incompatible locks are our own. */
2583           can_grant= TRUE;
2584       }
2585     }
2586     else
2587     {
2588       /*
2589         Our lock request conflicts with one of granted "fast path" locks:
2590 
2591         This means that we are trying to acquire "obtrusive" lock and:
2592         a) Either we are called from MDL_context::try_acquire_lock_impl()
2593            and then all "fast path" locks belonging to this context were
2594            materialized (as we do for "obtrusive" locks).
2595         b) Or we are called from MDL_lock::reschedule_waiters() then
2596            this context is waiting for this request and all its "fast
2597            path" locks were materialized before the wait.
2598 
2599         The above means that conflicting granted "fast path" lock cannot
2600         belong to us and our request cannot be satisfied.
2601       */
2602     }
2603   }
2604   return can_grant;
2605 }
2606 
2607 
2608 /**
2609   Return the first MDL_context which owns the lock.
2610 
2611   @return Pointer to the first MDL_context which has acquired the lock
2612           NULL if there are no such contexts.
2613 
2614   @note This method works properly only for locks acquired using
2615         "slow" path. It won't return context if it has used "fast"
2616         path to acquire the lock.
2617 */
2618 
2619 inline MDL_context *
get_lock_owner() const2620 MDL_lock::get_lock_owner() const
2621 {
2622   Ticket_iterator it(m_granted);
2623   MDL_ticket *ticket;
2624 
2625   if ((ticket= it++))
2626     return ticket->get_ctx();
2627   return NULL;
2628 }
2629 
2630 
2631 /** Remove a ticket from waiting or pending queue and wakeup up waiters. */
2632 
remove_ticket(MDL_context * ctx,LF_PINS * pins,Ticket_list MDL_lock::* list,MDL_ticket * ticket)2633 void MDL_lock::remove_ticket(MDL_context *ctx, LF_PINS *pins,
2634                              Ticket_list MDL_lock::*list,
2635                              MDL_ticket *ticket)
2636 {
2637   bool is_obtrusive= is_obtrusive_lock(ticket->get_type());
2638   bool is_singleton= mdl_locks.is_lock_object_singleton(&key);
2639 
2640   mysql_prlock_wrlock(&m_rwlock);
2641 
2642   DEBUG_SYNC(current_thd, "mdl_lock_remove_ticket_m_rwlock_locked");
2643 
2644   (this->*list).remove_ticket(ticket);
2645 
2646   /*
2647     If we are removing "obtrusive" type of request either from granted or
2648     waiting lists we need to decrement "obtrusive" requests counter.
2649     Once last ticket for "obtrusive" lock is removed we should clear
2650     HAS_OBTRUSIVE flag in m_fast_path_state as well.
2651   */
2652   bool last_obtrusive= is_obtrusive &&
2653                        ((--m_obtrusive_locks_granted_waiting_count) == 0);
2654   /*
2655     If both m_granted and m_waiting lists become empty as result we also
2656     need to clear HAS_SLOW_PATH flag in m_fast_path_state.
2657   */
2658   bool last_slow_path= m_granted.is_empty() && m_waiting.is_empty();
2659   bool last_use= false;
2660 
2661   if (last_slow_path || last_obtrusive)
2662   {
2663     fast_path_state_t old_state= m_fast_path_state;
2664     fast_path_state_t new_state;
2665     do
2666     {
2667       new_state= old_state;
2668       if (last_slow_path)
2669         new_state&= ~MDL_lock::HAS_SLOW_PATH;
2670       if (last_obtrusive)
2671         new_state&= ~MDL_lock::HAS_OBTRUSIVE;
2672     }
2673     while (! fast_path_state_cas(&old_state, new_state));
2674 
2675     /*
2676       We don't have any "fast" or "slow" path locks. MDL_lock object becomes
2677       unused so unused objects counter needs to be incremented.
2678     */
2679     if (new_state == 0)
2680       last_use= true;
2681   }
2682 
2683 
2684   if (last_slow_path)
2685   {
2686     /*
2687       We might end-up with the last waiting ticket being removed and non-0
2688       m_hog_lock_count/m_piglet_lock_count in the following situation:
2689 
2690       1) There is a granted "hog"/"piglet" lock blocking a lower priority lock
2691          request.
2692       2) The lower priority lock request is timed out or killed. It is not yet
2693          removed from waiters list and bitmap.
2694       3) The "Hog"/"piglet" lock is released. Its reschedule_waiters() call
2695          will still see the pending lower priority lock so it won't reset
2696          the m_hog_lock_count/m_piglet_lock_count counters.
2697       4) MDL_lock::remove_ticket() is called for the timed out/killed
2698          lower priority ticket. Which turns out to be the last ticket
2699          for this lock.
2700 
2701       Hence we need to reset these counters here.
2702     */
2703     m_hog_lock_count= 0;
2704     m_piglet_lock_count= 0;
2705     m_current_waiting_incompatible_idx= 0;
2706   }
2707   else
2708   {
2709     /*
2710       There can be some contexts waiting to acquire a lock
2711       which now might be able to do it. Grant the lock to
2712       them and wake them up!
2713 
2714       We always try to reschedule locks, since there is no easy way
2715       (i.e. by looking at the bitmaps) to find out whether it is
2716       required or not.
2717       In a general case, even when the queue's bitmap is not changed
2718       after removal of the ticket, there is a chance that some request
2719       can be satisfied (due to the fact that a granted request
2720       reflected in the bitmap might belong to the same context as a
2721       pending request).
2722     */
2723     reschedule_waiters();
2724   }
2725   mysql_prlock_unlock(&m_rwlock);
2726 
2727   /* Don't count singleton MDL_lock objects as unused. */
2728   if (last_use && ! is_singleton)
2729     mdl_locks.lock_object_unused(ctx, pins);
2730 }
2731 
2732 
2733 /**
2734   Check if we have any pending locks which conflict with existing
2735   shared lock.
2736 
2737   @pre The ticket must match an acquired lock.
2738 
2739   @return TRUE if there is a conflicting lock request, FALSE otherwise.
2740 */
2741 
has_pending_conflicting_lock(enum_mdl_type type)2742 bool MDL_lock::has_pending_conflicting_lock(enum_mdl_type type)
2743 {
2744   bool result;
2745 
2746   mysql_mutex_assert_not_owner(&LOCK_open);
2747 
2748   mysql_prlock_rdlock(&m_rwlock);
2749   result= (m_waiting.bitmap() & incompatible_granted_types_bitmap()[type]);
2750   mysql_prlock_unlock(&m_rwlock);
2751   return result;
2752 }
2753 
2754 
~MDL_wait_for_graph_visitor()2755 MDL_wait_for_graph_visitor::~MDL_wait_for_graph_visitor()
2756 {
2757 }
2758 
2759 
~MDL_wait_for_subgraph()2760 MDL_wait_for_subgraph::~MDL_wait_for_subgraph()
2761 {
2762 }
2763 
2764 /**
2765   Check if ticket represents metadata lock of "stronger" or equal type
2766   than specified one. I.e. if metadata lock represented by ticket won't
2767   allow any of locks which are not allowed by specified type of lock.
2768 
2769   @return TRUE  if ticket has stronger or equal type
2770           FALSE otherwise.
2771 */
2772 
has_stronger_or_equal_type(enum_mdl_type type) const2773 bool MDL_ticket::has_stronger_or_equal_type(enum_mdl_type type) const
2774 {
2775   const MDL_lock::bitmap_t *
2776     granted_incompat_map= m_lock->incompatible_granted_types_bitmap();
2777 
2778   return ! (granted_incompat_map[type] & ~(granted_incompat_map[m_type]));
2779 }
2780 
2781 
is_incompatible_when_granted(enum_mdl_type type) const2782 bool MDL_ticket::is_incompatible_when_granted(enum_mdl_type type) const
2783 {
2784   return (MDL_BIT(m_type) &
2785           m_lock->incompatible_granted_types_bitmap()[type]);
2786 }
2787 
2788 
2789 bool
is_incompatible_when_waiting(enum_mdl_type type) const2790 MDL_ticket::is_incompatible_when_waiting(enum_mdl_type type) const
2791 {
2792   return (MDL_BIT(m_type) &
2793           m_lock->incompatible_waiting_types_bitmap()[type]);
2794 }
2795 
2796 
2797 /**
2798   Check whether the context already holds a compatible lock ticket
2799   on an object.
2800   Start searching from list of locks for the same duration as lock
2801   being requested. If not look at lists for other durations.
2802 
2803   @param mdl_request  Lock request object for lock to be acquired
2804   @param[out] result_duration  Duration of lock which was found.
2805 
2806   @note Tickets which correspond to lock types "stronger" than one
2807         being requested are also considered compatible.
2808 
2809   @return A pointer to the lock ticket for the object or NULL otherwise.
2810 */
2811 
2812 MDL_ticket *
find_ticket(MDL_request * mdl_request,enum_mdl_duration * result_duration)2813 MDL_context::find_ticket(MDL_request *mdl_request,
2814                          enum_mdl_duration *result_duration)
2815 {
2816   MDL_ticket *ticket;
2817   int i;
2818 
2819   for (i= 0; i < MDL_DURATION_END; i++)
2820   {
2821     enum_mdl_duration duration= (enum_mdl_duration)((mdl_request->duration+i) %
2822                                                     MDL_DURATION_END);
2823     Ticket_iterator it(m_tickets[duration]);
2824 
2825     while ((ticket= it++))
2826     {
2827       if (mdl_request->key.is_equal(&ticket->m_lock->key) &&
2828           ticket->has_stronger_or_equal_type(mdl_request->type))
2829       {
2830         *result_duration= duration;
2831         return ticket;
2832       }
2833     }
2834   }
2835   return NULL;
2836 }
2837 
2838 
2839 /**
2840   Try to acquire one lock.
2841 
2842   Unlike exclusive locks, shared locks are acquired one by
2843   one. This is interface is chosen to simplify introduction of
2844   the new locking API to the system. MDL_context::try_acquire_lock()
2845   is currently used from open_table(), and there we have only one
2846   table to work with.
2847 
2848   This function may also be used to try to acquire an exclusive
2849   lock on a destination table, by ALTER TABLE ... RENAME.
2850 
2851   Returns immediately without any side effect if encounters a lock
2852   conflict. Otherwise takes the lock.
2853 
2854   @param mdl_request [in/out] Lock request object for lock to be acquired
2855 
2856   @retval  FALSE   Success. The lock may have not been acquired.
2857                    Check the ticket, if it's NULL, a conflicting lock
2858                    exists.
2859   @retval  TRUE    Out of resources, an error has been reported.
2860 */
2861 
2862 bool
try_acquire_lock(MDL_request * mdl_request)2863 MDL_context::try_acquire_lock(MDL_request *mdl_request)
2864 {
2865   MDL_ticket *ticket;
2866 
2867   if (try_acquire_lock_impl(mdl_request, &ticket))
2868     return TRUE;
2869 
2870   if (! mdl_request->ticket)
2871   {
2872     /*
2873       Our attempt to acquire lock without waiting has failed.
2874       Let us release resources which were acquired in the process.
2875 
2876       We don't need to count MDL_lock object as unused and possibly
2877       delete it here because:
2878       - Either there was a conflicting ticket in MDL_lock::m_granted/
2879         m_waiting lists during our call to MDL_lock::can_grant_lock().
2880         This ticket can't go away while MDL_lock::m_rwlock is held.
2881       - Or we have tried to acquire an "obtrusive" lock and there was
2882         a conflicting "fast path" lock in MDL_lock::m_fast_path_state
2883         counter during our call to MDL_lock::can_grant_lock().
2884         In this case HAS_OBTRUSIVE lock flag should have been set before
2885         call to MDL_lock::can_grant_lock() so release of this "fast path"
2886         lock will have to take slow path (see release_lock() and invariant
2887         [INV1]). This means that conflicting "fast path" lock can't go
2888         away until MDL_lock::m_rwlock is released or HAS_OBSTRUSIVE flag
2889         is cleared. In the latter case counting MDL_lock object as unused
2890         is responsibility of thread which is decrementing "fast path" lock
2891         counter. MDL_lock object can't be deleted under out feet since
2892         thread doing deletion needs to acquire MDL_lock::m_rwlock first.
2893     */
2894     MDL_lock *lock= ticket->m_lock;
2895 
2896     bool last_obtrusive= lock->is_obtrusive_lock(mdl_request->type) &&
2897            ((--lock->m_obtrusive_locks_granted_waiting_count) == 0);
2898     bool last_slow_path= lock->m_granted.is_empty() &&
2899                          lock->m_waiting.is_empty();
2900 
2901     if (last_slow_path || last_obtrusive)
2902     {
2903       MDL_lock::fast_path_state_t old_state= lock->m_fast_path_state;
2904       MDL_lock::fast_path_state_t new_state;
2905       do
2906       {
2907         new_state= old_state;
2908         if (last_slow_path)
2909           new_state&= ~MDL_lock::HAS_SLOW_PATH;
2910         if (last_obtrusive)
2911           new_state&= ~MDL_lock::HAS_OBTRUSIVE;
2912       }
2913       while (! lock->fast_path_state_cas(&old_state, new_state));
2914     }
2915 
2916     mysql_prlock_unlock(&lock->m_rwlock);
2917 
2918     /*
2919       If SEs were notified about impending lock acquisition, the failure
2920       to acquire it requires the same notification as lock release.
2921     */
2922     if (ticket->m_hton_notified)
2923     {
2924       mysql_mdl_set_status(ticket->m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
2925       m_owner->notify_hton_post_release_exclusive(&mdl_request->key);
2926     }
2927 
2928     MDL_ticket::destroy(ticket);
2929   }
2930 
2931   return FALSE;
2932 }
2933 
2934 
2935 /**
2936   "Materialize" requests for locks which were satisfied using
2937   "fast path" by properly including them into corresponding
2938   MDL_lock::m_granted bitmaps/lists and removing it from
2939   packed counter in MDL_lock::m_fast_path_state.
2940 
2941   @note In future we might optimize this method if necessary,
2942         for example, by keeping pointer to first "fast path"
2943         ticket.
2944 */
2945 
materialize_fast_path_locks()2946 void MDL_context::materialize_fast_path_locks()
2947 {
2948   int i;
2949 
2950   for (i= 0; i < MDL_DURATION_END; i++)
2951   {
2952     Ticket_iterator it(m_tickets[(enum_mdl_duration)i]);
2953     MDL_ticket *ticket;
2954 
2955     while ((ticket= it++))
2956     {
2957       if (ticket->m_is_fast_path)
2958       {
2959         MDL_lock *lock= ticket->m_lock;
2960         MDL_lock::fast_path_state_t unobtrusive_lock_increment=
2961           lock->get_unobtrusive_lock_increment(ticket->get_type());
2962         ticket->m_is_fast_path= false;
2963         mysql_prlock_wrlock(&lock->m_rwlock);
2964         lock->m_granted.add_ticket(ticket);
2965         /*
2966           Atomically decrement counter in MDL_lock::m_fast_path_state.
2967           This needs to happen under protection of MDL_lock::m_rwlock to make
2968           it atomic with addition of ticket to MDL_lock::m_granted list and
2969           to enforce invariant [INV1].
2970         */
2971         MDL_lock::fast_path_state_t old_state= lock->m_fast_path_state;
2972         while (! lock->fast_path_state_cas(&old_state,
2973                          ((old_state - unobtrusive_lock_increment) |
2974                           MDL_lock::HAS_SLOW_PATH)))
2975         { }
2976         mysql_prlock_unlock(&lock->m_rwlock);
2977       }
2978     }
2979   }
2980 }
2981 
2982 
2983 /**
2984   Auxiliary method for acquiring lock without waiting.
2985 
2986   @param mdl_request [in/out] Lock request object for lock to be acquired
2987   @param out_ticket  [out]    Ticket for the request in case when lock
2988                               has not been acquired.
2989 
2990   @retval  FALSE   Success. The lock may have not been acquired.
2991                    Check MDL_request::ticket, if it's NULL, a conflicting
2992                    lock exists. In this case "out_ticket" out parameter
2993                    points to ticket which was constructed for the request.
2994                    MDL_ticket::m_lock points to the corresponding MDL_lock
2995                    object and MDL_lock::m_rwlock write-locked.
2996   @retval  TRUE    Out of resources, an error has been reported.
2997 */
2998 
2999 bool
try_acquire_lock_impl(MDL_request * mdl_request,MDL_ticket ** out_ticket)3000 MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
3001                                    MDL_ticket **out_ticket)
3002 {
3003   MDL_lock *lock;
3004   MDL_key *key= &mdl_request->key;
3005   MDL_ticket *ticket;
3006   enum_mdl_duration found_duration;
3007   MDL_lock::fast_path_state_t unobtrusive_lock_increment;
3008   bool force_slow;
3009   bool pinned;
3010 
3011   assert(mdl_request->ticket == NULL);
3012 
3013   /* Don't take chances in production. */
3014   mdl_request->ticket= NULL;
3015   mysql_mutex_assert_not_owner(&LOCK_open);
3016 
3017   /*
3018     Check whether the context already holds a shared lock on the object,
3019     and if so, grant the request.
3020   */
3021   if ((ticket= find_ticket(mdl_request, &found_duration)))
3022   {
3023     assert(ticket->m_lock);
3024     assert(ticket->has_stronger_or_equal_type(mdl_request->type));
3025     /*
3026       If the request is for a transactional lock, and we found
3027       a transactional lock, just reuse the found ticket.
3028 
3029       It's possible that we found a transactional lock,
3030       but the request is for a HANDLER lock. In that case HANDLER
3031       code will clone the ticket (see below why it's needed).
3032 
3033       If the request is for a transactional lock, and we found
3034       a HANDLER lock, create a copy, to make sure that when user
3035       does HANDLER CLOSE, the transactional lock is not released.
3036 
3037       If the request is for a handler lock, and we found a
3038       HANDLER lock, also do the clone. HANDLER CLOSE for one alias
3039       should not release the lock on the table HANDLER opened through
3040       a different alias.
3041     */
3042     mdl_request->ticket= ticket;
3043     if ((found_duration != mdl_request->duration ||
3044          mdl_request->duration == MDL_EXPLICIT) &&
3045         clone_ticket(mdl_request))
3046     {
3047       /* Clone failed. */
3048       mdl_request->ticket= NULL;
3049       return TRUE;
3050     }
3051     return FALSE;
3052   }
3053 
3054   /*
3055     Prepare context for lookup in MDL_map container by allocating pins
3056     if necessary. This also ensures that this MDL_context has pins allocated
3057     and ready for future attempts elements from MDL_map container (which
3058     might happen during lock release).
3059   */
3060   if (fix_pins())
3061     return TRUE;
3062 
3063   if (!(ticket= MDL_ticket::create(this, mdl_request->type
3064 #ifndef NDEBUG
3065                                    , mdl_request->duration
3066 #endif
3067                                    )))
3068     return TRUE;
3069 
3070   /*
3071     Get increment for "fast path" or indication that this is
3072     request for "obtrusive" type of lock outside of critical section.
3073   */
3074   unobtrusive_lock_increment=
3075     MDL_lock::get_unobtrusive_lock_increment(mdl_request);
3076 
3077   /*
3078     If this "obtrusive" type we have to take "slow path".
3079     If this context has open HANDLERs we have to take "slow path"
3080     as well for MDL_object_lock::notify_conflicting_locks() to work
3081     properly.
3082   */
3083   force_slow= ! unobtrusive_lock_increment || m_needs_thr_lock_abort;
3084 
3085   /*
3086     If "obtrusive" lock is requested we need to "materialize" all fast
3087     path tickets, so MDL_lock::can_grant_lock() can safely assume
3088     that all granted "fast path" locks belong to different context.
3089   */
3090   if (! unobtrusive_lock_increment)
3091     materialize_fast_path_locks();
3092 
3093   assert(ticket->m_psi == NULL);
3094   ticket->m_psi= mysql_mdl_create(ticket, key,
3095                                   mdl_request->type,
3096                                   mdl_request->duration,
3097                                   MDL_ticket::PENDING,
3098                                   mdl_request->m_src_file,
3099                                   mdl_request->m_src_line);
3100 
3101   /*
3102     We need to notify/get permission from storage engines before acquiring
3103     X lock if it is requested in one of namespaces interesting for SEs.
3104   */
3105   if (mdl_request->type == MDL_EXCLUSIVE &&
3106       MDL_lock::needs_hton_notification(key->mdl_namespace()))
3107   {
3108     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::PRE_ACQUIRE_NOTIFY);
3109 
3110     bool victimized;
3111     if (m_owner->notify_hton_pre_acquire_exclusive(key, &victimized))
3112     {
3113       MDL_ticket::destroy(ticket);
3114       my_error(victimized ? ER_LOCK_DEADLOCK : ER_LOCK_REFUSED_BY_ENGINE, MYF(0));
3115       return TRUE;
3116     }
3117     ticket->m_hton_notified= true;
3118 
3119     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::PENDING);
3120   }
3121 
3122 retry:
3123   /*
3124     The below call pins pointer to returned MDL_lock object (unless
3125     it is the singleton object for GLOBAL or COMMIT namespaces).
3126   */
3127   if (!(lock= mdl_locks.find_or_insert(m_pins, key, &pinned)))
3128   {
3129     /*
3130       If SEs were notified about impending lock acquisition, the failure
3131       to acquire it requires the same notification as lock release.
3132     */
3133     if (ticket->m_hton_notified)
3134     {
3135       mysql_mdl_set_status(ticket->m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
3136       m_owner->notify_hton_post_release_exclusive(key);
3137     }
3138     MDL_ticket::destroy(ticket);
3139     return TRUE;
3140   }
3141 
3142   /*
3143     Code counting unused MDL_lock objects below assumes that object is not
3144     pinned iff it is a singleton.
3145   */
3146   assert(mdl_locks.is_lock_object_singleton(key) == !pinned);
3147 
3148   if (! force_slow)
3149   {
3150     /*
3151       "Fast path".
3152 
3153       Hurray! We are acquring "unobtrusive" type of lock and not forced
3154       to take "slow path" because of open HANDLERs.
3155 
3156       Let us do a few checks first to figure out if we really can acquire
3157       lock using "fast path".
3158 
3159       Since the MDL_lock object is pinned at this point (or it is the
3160       singleton) we can access its members without risk of it getting deleted
3161       under out feet.
3162 
3163       Ordinary read of MDL_lock::m_fast_path_state which we do here is OK as
3164       correctness of value returned by it will be anyway validated by atomic
3165       compare-and-swap which happens later.
3166       In theory, this algorithm will work correctly (but not very efficiently)
3167       if the read will return random values.
3168       In practice, it won't return values which are too out-of-date as the
3169       above call to MDL_map::find_or_insert() contains memory barrier.
3170     */
3171     MDL_lock::fast_path_state_t old_state= lock->m_fast_path_state;
3172     bool first_use;
3173 
3174     do
3175     {
3176       /*
3177         Check if hash look-up returned object marked as destroyed or
3178         it was marked as such while it was pinned by us. If yes we
3179         need to unpin it and retry look-up.
3180       */
3181       if (old_state & MDL_lock::IS_DESTROYED)
3182       {
3183         if (pinned)
3184           lf_hash_search_unpin(m_pins);
3185         DEBUG_SYNC(get_thd(), "mdl_acquire_lock_is_destroyed_fast_path");
3186         goto retry;
3187       }
3188 
3189       /*
3190         Check that there are no granted/pending "obtrusive" locks and nobody
3191         even is about to try to check if such lock can be acquired.
3192 
3193         In these cases we need to take "slow path".
3194       */
3195       if (old_state & MDL_lock::HAS_OBTRUSIVE)
3196         goto slow_path;
3197 
3198       /*
3199         If m_fast_path_state doesn't have HAS_SLOW_PATH set and all "fast"
3200         path counters are 0 then we are about to use an unused MDL_lock
3201         object. We need to decrement unused objects counter eventually.
3202       */
3203       first_use= (old_state == 0);
3204 
3205       /*
3206         Now we simply need to increment m_fast_path_state with a value which
3207         corresponds to type of our request (i.e. increment part this member
3208         which contains counter which corresponds to this type).
3209 
3210         This needs to be done as atomical operation with the above checks,
3211         which is achieved by using atomic compare-and-swap.
3212 
3213         @sa MDL_object_lock::m_unobtrusive_lock_increment for explanation
3214         why overflow is not an issue here.
3215       */
3216     }
3217     while (! lock->fast_path_state_cas(&old_state,
3218                                        old_state + unobtrusive_lock_increment));
3219 
3220     /*
3221       Lock has been acquired. Since this can only be an "unobtrusive" lock and
3222       there were no active/pending requests for "obtrusive" locks, we don't need
3223       to care about "hog" and "piglet" locks and the max_write_lock_count
3224       threshold.
3225     */
3226 
3227     if (pinned)
3228       lf_hash_search_unpin(m_pins);
3229 
3230     /*
3231       Don't count singleton MDL_lock objects as used, use "pinned == false"
3232       as an indication of such objects.
3233     */
3234     if (first_use && pinned)
3235       mdl_locks.lock_object_used();
3236 
3237     /*
3238       Since this MDL_ticket is not visible to any threads other than
3239       the current one, we can set MDL_ticket::m_lock member without
3240       protect of MDL_lock::m_rwlock. MDL_lock won't be deleted
3241       underneath our feet as MDL_lock::m_fast_path_state serves as
3242       reference counter in this case.
3243     */
3244     ticket->m_lock= lock;
3245     ticket->m_is_fast_path= true;
3246 
3247     m_tickets[mdl_request->duration].push_front(ticket);
3248 
3249     mdl_request->ticket= ticket;
3250 
3251     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
3252     return FALSE;
3253   }
3254 
3255 slow_path:
3256 
3257   /*
3258    "Slow path".
3259 
3260     Do full-blown check and list manipulation if necessary.
3261   */
3262   mysql_prlock_wrlock(&lock->m_rwlock);
3263 
3264   /*
3265     First of all, let us check if hash look-up returned MDL_lock object which
3266     is marked as destroyed or was marked as such while it was pinned by us.
3267     If we have got such object we need to retry look-up.
3268 
3269     We can use ordinary non-atomic read in this case as this flag is set under
3270     protection of MDL_lock::m_rwlock (we can get inconsistent data for other
3271     parts of m_fast_path_state due to concurrent atomic updates, but we don't
3272     care about them yet).
3273   */
3274   MDL_lock::fast_path_state_t state= lock->m_fast_path_state;
3275 
3276   if (state & MDL_lock::IS_DESTROYED)
3277   {
3278     mysql_prlock_unlock(&lock->m_rwlock);
3279     /*
3280       We can't unpin object earlier as lf_hash_delete() might have been
3281       called for it already and so LF_ALLOCATOR is free to deallocate it
3282       once unpinned.
3283     */
3284     if (pinned)
3285       lf_hash_search_unpin(m_pins);
3286     DEBUG_SYNC(get_thd(), "mdl_acquire_lock_is_destroyed_slow_path");
3287     goto retry;
3288   }
3289 
3290   /*
3291     Object was not marked as destroyed. Since it can't be deleted from hash
3292     and deallocated until this happens we can unpin it and work with it safely
3293     while MDL_lock::m_rwlock is held.
3294   */
3295   if (pinned)
3296     lf_hash_search_unpin(m_pins);
3297 
3298   /*
3299     When we try to acquire the first obtrusive lock for MDL_lock object we
3300     need to atomically set the HAS_OBTRUSIVE flag in m_fast_path_state before
3301     we call the MDL_lock::can_grant_lock() method.
3302     This is necessary to prevent concurrent fast path acquisitions from
3303     invalidating the results of this method.
3304   */
3305   bool first_obtrusive_lock= (unobtrusive_lock_increment == 0) &&
3306          ((lock->m_obtrusive_locks_granted_waiting_count++) == 0);
3307   bool first_use= false;
3308 
3309   /*
3310     When we try to acquire the first "slow" path lock for MDL_lock object
3311     we also need to atomically set HAS_SLOW_PATH flag. It is OK to read
3312     HAS_SLOW_PATH non-atomically here since it can be only set under
3313     protection of MDL_lock::m_rwlock lock.
3314   */
3315   if (!(state & MDL_lock::HAS_SLOW_PATH) || first_obtrusive_lock)
3316   {
3317     do
3318     {
3319       /*
3320         If HAS_SLOW_PATH flag is not set and all "fast" path counters
3321         are zero we are about to use previously unused MDL_lock object.
3322         MDL_map::m_unused_lock_objects counter needs to be decremented
3323         eventually.
3324       */
3325       first_use= (state == 0);
3326     }
3327     while (! lock->fast_path_state_cas(&state,
3328                      state | MDL_lock::HAS_SLOW_PATH |
3329                      (first_obtrusive_lock ? MDL_lock::HAS_OBTRUSIVE: 0)));
3330   }
3331 
3332   /*
3333     Don't count singleton MDL_lock objects as used, use "pinned == false"
3334     as an indication of such objects.
3335 
3336     If the fact that we do this atomic decrement under MDL_lock::m_rwlock
3337     ever becomes bottleneck (which is unlikely) it can be safely moved
3338     outside of critical section.
3339   */
3340   if (first_use && pinned)
3341     mdl_locks.lock_object_used();
3342 
3343   ticket->m_lock= lock;
3344 
3345   if (lock->can_grant_lock(mdl_request->type, this))
3346   {
3347     lock->m_granted.add_ticket(ticket);
3348 
3349     if (lock->is_affected_by_max_write_lock_count())
3350     {
3351       /*
3352         If we have acquired an higher-prio "piglet" or "hog" lock while there
3353         are pending lower priority locks, we need to increment the appropriate
3354         counter.
3355 
3356         If one or both of these counters exceed the max_write_lock_count
3357         threshold, change priority matrice for this MDL_lock object.
3358         Reschedule waiters to avoid problems when the change of matrice
3359         happens concurrently to other thread acquiring a lower priority
3360         lock between its call to MDL_lock::can_grant_lock() and
3361         MDL_context::find_deadlock().
3362       */
3363       if (lock->count_piglets_and_hogs(mdl_request->type))
3364         lock->reschedule_waiters();
3365     }
3366 
3367     mysql_prlock_unlock(&lock->m_rwlock);
3368 
3369     m_tickets[mdl_request->duration].push_front(ticket);
3370 
3371     mdl_request->ticket= ticket;
3372 
3373     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
3374   }
3375   else
3376     *out_ticket= ticket;
3377 
3378   return FALSE;
3379 }
3380 
3381 
3382 /**
3383   Create a copy of a granted ticket.
3384   This is used to make sure that HANDLER ticket
3385   is never shared with a ticket that belongs to
3386   a transaction, so that when we HANDLER CLOSE,
3387   we don't release a transactional ticket, and
3388   vice versa -- when we COMMIT, we don't mistakenly
3389   release a ticket for an open HANDLER.
3390 
3391   @retval TRUE   Out of memory.
3392   @retval FALSE  Success.
3393 */
3394 
3395 bool
clone_ticket(MDL_request * mdl_request)3396 MDL_context::clone_ticket(MDL_request *mdl_request)
3397 {
3398   MDL_ticket *ticket;
3399 
3400   mysql_mutex_assert_not_owner(&LOCK_open);
3401 
3402   /*
3403     Since in theory we can clone ticket belonging to a different context
3404     we need to prepare target context for possible attempts to release
3405     lock and thus possible removal of MDL_lock from MDL_map container.
3406     So we allocate pins to be able to work with this container if they
3407     are not allocated already.
3408   */
3409   if (fix_pins())
3410     return TRUE;
3411 
3412   /*
3413     By submitting mdl_request->type to MDL_ticket::create()
3414     we effectively downgrade the cloned lock to the level of
3415     the request.
3416   */
3417   if (!(ticket= MDL_ticket::create(this, mdl_request->type
3418 #ifndef NDEBUG
3419                                    , mdl_request->duration
3420 #endif
3421                                    )))
3422     return TRUE;
3423 
3424   assert(ticket->m_psi == NULL);
3425   ticket->m_psi= mysql_mdl_create(ticket,
3426                                   &mdl_request->key,
3427                                   mdl_request->type,
3428                                   mdl_request->duration,
3429                                   MDL_ticket::PENDING,
3430                                   mdl_request->m_src_file,
3431                                   mdl_request->m_src_line);
3432 
3433   /* clone() is not supposed to be used to get a stronger lock. */
3434   assert(mdl_request->ticket->has_stronger_or_equal_type(ticket->m_type));
3435 
3436 
3437   /*
3438     If we are to clone exclusive lock in namespace requiring notification
3439     of storage engines we need to notify/get permission from SEs similarly
3440     to situation when lock acquired.
3441   */
3442   if (mdl_request->type == MDL_EXCLUSIVE &&
3443       MDL_lock::needs_hton_notification(mdl_request->key.mdl_namespace()))
3444   {
3445     assert(mdl_request->ticket->m_hton_notified);
3446 
3447     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::PRE_ACQUIRE_NOTIFY);
3448 
3449     bool victimized;
3450     if (m_owner->notify_hton_pre_acquire_exclusive(&mdl_request->key, &victimized))
3451     {
3452       MDL_ticket::destroy(ticket);
3453       my_error(victimized ? ER_LOCK_DEADLOCK : ER_LOCK_REFUSED_BY_ENGINE, MYF(0));
3454       return TRUE;
3455     }
3456     ticket->m_hton_notified= true;
3457 
3458     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::PENDING);
3459   }
3460 
3461   ticket->m_lock= mdl_request->ticket->m_lock;
3462 
3463   if (mdl_request->ticket->m_is_fast_path)
3464   {
3465     /*
3466       We are cloning ticket which was acquired on "fast path".
3467       Let us use "fast path" to create clone as well.
3468     */
3469     MDL_lock::fast_path_state_t unobtrusive_lock_increment=
3470       ticket->m_lock->get_unobtrusive_lock_increment(ticket->get_type());
3471 
3472     /*
3473       "Obtrusive" type of lock can't be cloned from weaker, "unobtrusive"
3474       type of lock.
3475     */
3476     assert(unobtrusive_lock_increment != 0);
3477 
3478     /*
3479       Increment of counter in MDL_lock::m_fast_path_state needs to happen here
3480       atomically and under protection of MDL_lock::m_rwlock in order to enforce
3481       invariant [INV1].
3482     */
3483     mysql_prlock_wrlock(&ticket->m_lock->m_rwlock);
3484     ticket->m_lock->fast_path_state_add(unobtrusive_lock_increment);
3485     mysql_prlock_unlock(&ticket->m_lock->m_rwlock);
3486     ticket->m_is_fast_path= true;
3487   }
3488   else
3489   {
3490     /*
3491       We are cloning ticket which was acquired on "slow path".
3492       We will use "slow path" for new ticket as well. We also
3493       need to take into account if new ticket corresponds to
3494       "obtrusive" lock.
3495     */
3496     bool is_obtrusive= ticket->m_lock->is_obtrusive_lock(ticket->m_type);
3497     mysql_prlock_wrlock(&ticket->m_lock->m_rwlock);
3498     ticket->m_lock->m_granted.add_ticket(ticket);
3499     if (is_obtrusive)
3500     {
3501       /*
3502         We don't need to set HAS_OBTRUSIVE flag in MDL_lock::m_fast_path_state
3503         here as it is already set since the ticket being cloned already
3504         represents "obtrusive" lock for this MDL_lock object.
3505       */
3506       assert(ticket->m_lock->m_obtrusive_locks_granted_waiting_count != 0);
3507       ++ticket->m_lock->m_obtrusive_locks_granted_waiting_count;
3508     }
3509     mysql_prlock_unlock(&ticket->m_lock->m_rwlock);
3510   }
3511 
3512   mdl_request->ticket= ticket;
3513 
3514   m_tickets[mdl_request->duration].push_front(ticket);
3515 
3516   mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
3517 
3518   return FALSE;
3519 }
3520 
3521 
3522 /**
3523   Notify threads holding S/SH metadata locks on an object, which conflict
3524   with a pending X lock.
3525 
3526   @note Currently this method is guaranteed to notify shared lock
3527         owners which have MDL_context::m_needs_thr_lock_abort flag
3528         set (as for others conficting locks might have been acquired
3529         on "fast path" and thus might be absent from list of granted
3530         locks).
3531         This is OK as notification for other contexts is anyway
3532         no-op now.
3533 
3534   @note We don't notify threads holding other than S/SH types of
3535         conflicting locks on the object since notification should
3536         not be needed and anyway will be no-op for them (unless
3537         they also hold S/SH locks on the object).
3538 
3539   @param  ctx  MDL_context for current thread.
3540   @param  lock MDL_lock object representing lock which is to be
3541                acquired.
3542 */
3543 
object_lock_notify_conflicting_locks(MDL_context * ctx,MDL_lock * lock)3544 void MDL_lock::object_lock_notify_conflicting_locks(MDL_context *ctx, MDL_lock *lock)
3545 {
3546   Ticket_iterator it(lock->m_granted);
3547   MDL_ticket *conflicting_ticket;
3548 
3549   while ((conflicting_ticket= it++))
3550   {
3551     if (conflicting_ticket->get_ctx() != ctx &&
3552         (conflicting_ticket->get_type() == MDL_SHARED ||
3553          conflicting_ticket->get_type() == MDL_SHARED_HIGH_PRIO))
3554     {
3555       MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
3556 
3557       /*
3558         If thread which holds conflicting lock is waiting on table-level
3559         lock or some other non-MDL resource we might need to wake it up
3560         by calling code outside of MDL.
3561 
3562         The only scenario in which it is important now looks like:
3563         Thread 1: HANDLER t1 OPEN, acquires S metadata lock on t1.
3564         Thread 2: LOCK TABLES t1 WRITE, t2 READ LOCAL, acquire
3565                   SNRW lock on t1, SR lock on t2 and TL_READ THR_LOCK
3566                   lock on t2.
3567         Thread 1: Executes UPDATE t2 SET i = 1 or some other DML which
3568                   will directly or indirectly block on THR_LOCK for t2.
3569         Thread 2: Does ALTER TABLE t1 ... which tries to upgrade SNRW
3570                   metadata lock to X lock and blocks because of S lock
3571                   from open HANDLER.
3572 
3573         A similar scenario is possible when MERGE tables are used instead
3574         of the READ LOCAL clause.
3575         Once we will get rid of the support for READ LOCAL and MERGE clauses
3576         this code can be removed.
3577       */
3578       ctx->get_owner()->
3579         notify_shared_lock(conflicting_ctx->get_owner(),
3580                            conflicting_ctx->get_needs_thr_lock_abort());
3581     }
3582   }
3583 }
3584 
3585 
3586 /**
3587   Acquire one lock with waiting for conflicting locks to go away if needed.
3588 
3589   @param mdl_request [in/out] Lock request object for lock to be acquired
3590 
3591   @param lock_wait_timeout [in] Seconds to wait before timeout.
3592 
3593   @retval  FALSE   Success. MDL_request::ticket points to the ticket
3594                    for the lock.
3595   @retval  TRUE    Failure (Out of resources or waiting is aborted),
3596 */
3597 
3598 bool
acquire_lock(MDL_request * mdl_request,ulong lock_wait_timeout)3599 MDL_context::acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout)
3600 {
3601   if (lock_wait_timeout == 0)
3602   {
3603     /*
3604       Resort to try_acquire_lock() in case of zero timeout.
3605 
3606       This allows to avoid unnecessary deadlock detection attempt and "fake"
3607       deadlocks which might result from it.
3608       In case of failure to acquire lock, try_acquire_lock() preserves
3609       invariants by updating MDL_lock::fast_path_state and obtrusive locks
3610       count. It also performs SE notification if needed.
3611     */
3612     if (try_acquire_lock(mdl_request))
3613       return true;
3614 
3615     if (!mdl_request->ticket)
3616     {
3617       /* We have failed to acquire lock instantly. */
3618       DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait");
3619       my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
3620       return true;
3621     }
3622     return false;
3623   }
3624 
3625   /* Normal, non-zero timeout case. */
3626 
3627   MDL_lock *lock;
3628   MDL_ticket *ticket;
3629   struct timespec abs_timeout;
3630   MDL_wait::enum_wait_status wait_status;
3631   /* Do some work outside the critical section. */
3632   set_timespec(&abs_timeout, lock_wait_timeout);
3633 
3634   if (try_acquire_lock_impl(mdl_request, &ticket))
3635     return TRUE;
3636 
3637   if (mdl_request->ticket)
3638   {
3639     /*
3640       We have managed to acquire lock without waiting.
3641       MDL_lock, MDL_context and MDL_request were updated
3642       accordingly, so we can simply return success.
3643     */
3644     return FALSE;
3645   }
3646 
3647   /*
3648     Our attempt to acquire lock without waiting has failed.
3649     As a result of this attempt we got MDL_ticket with m_lock
3650     member pointing to the corresponding MDL_lock object which
3651     has MDL_lock::m_rwlock write-locked.
3652   */
3653   lock= ticket->m_lock;
3654 
3655   lock->m_waiting.add_ticket(ticket);
3656 
3657   /*
3658     Once we added a pending ticket to the waiting queue,
3659     we must ensure that our wait slot is empty, so
3660     that our lock request can be scheduled. Do that in the
3661     critical section formed by the acquired write lock on MDL_lock.
3662   */
3663   m_wait.reset_status();
3664 
3665   if (lock->needs_notification(ticket))
3666     lock->notify_conflicting_locks(this);
3667 
3668   mysql_prlock_unlock(&lock->m_rwlock);
3669 
3670 #ifdef HAVE_PSI_METADATA_INTERFACE
3671   PSI_metadata_locker_state state;
3672   PSI_metadata_locker *locker= NULL;
3673 
3674   if (ticket->m_psi != NULL)
3675   {
3676     locker= PSI_METADATA_CALL(start_metadata_wait)(&state,
3677                                                    ticket->m_psi,
3678                                                    __FILE__, __LINE__);
3679   }
3680 #endif
3681 
3682   will_wait_for(ticket);
3683 
3684   /* There is a shared or exclusive lock on the object. */
3685   DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait");
3686 
3687   find_deadlock();
3688 
3689   if (lock->needs_notification(ticket) || lock->needs_connection_check())
3690   {
3691     struct timespec abs_shortwait;
3692     set_timespec(&abs_shortwait, 1);
3693     wait_status= MDL_wait::EMPTY;
3694 
3695     while (cmp_timespec(&abs_shortwait, &abs_timeout) <= 0)
3696     {
3697       /* abs_timeout is far away. Wait a short while and notify locks. */
3698       wait_status= m_wait.timed_wait(m_owner, &abs_shortwait, FALSE,
3699                                      mdl_request->key.get_wait_state_name());
3700 
3701       if (wait_status != MDL_wait::EMPTY)
3702         break;
3703 
3704       if (lock->needs_connection_check() && ! m_owner->is_connected())
3705       {
3706         /*
3707           If this is user-level lock and the client is disconnected don't wait
3708           forever: assume it's the same as statement being killed (this differs
3709           from pre-5.7 where we treat it as timeout, but is more logical).
3710           Using MDL_wait::set_status() to set status atomically wastes one
3711           condition variable wake up but should happen rarely.
3712           We don't want to do this check for all types of metadata locks since
3713           in general case we may want to complete wait/operation even when
3714           connection is lost (e.g. in case of logging into slow/general log).
3715         */
3716         if (! m_wait.set_status(MDL_wait::KILLED))
3717           wait_status= MDL_wait::KILLED;
3718         break;
3719       }
3720 
3721       if (lock->needs_notification(ticket))
3722       {
3723         mysql_prlock_wrlock(&lock->m_rwlock);
3724         lock->notify_conflicting_locks(this);
3725         mysql_prlock_unlock(&lock->m_rwlock);
3726       }
3727 
3728       set_timespec(&abs_shortwait, 1);
3729     }
3730     if (wait_status == MDL_wait::EMPTY)
3731       wait_status= m_wait.timed_wait(m_owner, &abs_timeout, TRUE,
3732                                      mdl_request->key.get_wait_state_name());
3733   }
3734   else
3735   {
3736     wait_status= m_wait.timed_wait(m_owner, &abs_timeout, TRUE,
3737                                    mdl_request->key.get_wait_state_name());
3738   }
3739 
3740   done_waiting_for();
3741 
3742 #ifdef HAVE_PSI_METADATA_INTERFACE
3743   if (locker != NULL)
3744   {
3745     PSI_METADATA_CALL(end_metadata_wait)(locker, 0);
3746   }
3747 #endif
3748 
3749   if (wait_status != MDL_wait::GRANTED)
3750   {
3751     lock->remove_ticket(this, m_pins, &MDL_lock::m_waiting, ticket);
3752 
3753     /*
3754       If SEs were notified about impending lock acquisition, the failure
3755       to acquire it requires the same notification as lock release.
3756     */
3757     if (ticket->m_hton_notified)
3758     {
3759       mysql_mdl_set_status(ticket->m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
3760       m_owner->notify_hton_post_release_exclusive(&mdl_request->key);
3761     }
3762 
3763     MDL_ticket::destroy(ticket);
3764     switch (wait_status)
3765     {
3766     case MDL_wait::VICTIM:
3767       my_error(ER_LOCK_DEADLOCK, MYF(0));
3768       break;
3769     case MDL_wait::TIMEOUT:
3770       my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
3771       break;
3772     case MDL_wait::KILLED:
3773       if (get_owner()->is_killed() == ER_QUERY_TIMEOUT)
3774         my_error(ER_QUERY_TIMEOUT, MYF(0));
3775       else
3776         my_error(ER_QUERY_INTERRUPTED, MYF(0));
3777       break;
3778     default:
3779       assert(0);
3780       break;
3781     }
3782     return TRUE;
3783   }
3784 
3785   /*
3786     We have been granted our request.
3787     State of MDL_lock object is already being appropriately updated by a
3788     concurrent thread (@sa MDL_lock:reschedule_waiters()).
3789     So all we need to do is to update MDL_context and MDL_request objects.
3790   */
3791   assert(wait_status == MDL_wait::GRANTED);
3792 
3793   m_tickets[mdl_request->duration].push_front(ticket);
3794 
3795   mdl_request->ticket= ticket;
3796 
3797   mysql_mdl_set_status(ticket->m_psi, MDL_ticket::GRANTED);
3798 
3799   return FALSE;
3800 }
3801 
3802 
3803 class MDL_request_cmp :
3804   public std::binary_function<const MDL_request*, const MDL_request*, bool>
3805 {
3806 public:
operator ()(const MDL_request * req1,const MDL_request * req2)3807   bool operator()(const MDL_request *req1, const MDL_request *req2)
3808   {
3809     int rc= req1->key.cmp(&req2->key);
3810     /*
3811       In cases when both requests correspond to the same key, we need to put
3812       the request for the stronger lock type first, to avoid extra deadlocks.
3813       We do this by simply comparing types of lock requests.
3814       This works OK since it is mostly needed to avoid the scenario when
3815       LOCK TABLES t1 WRITE, t1 READ acquires SRO lock before SNRW lock.
3816       It won't work in the general case (e.g. SRO is not stronger than SW).
3817     */
3818     if (rc == 0)
3819       rc= static_cast<int>(req2->type) - static_cast<int>(req1->type);
3820     return rc < 0;
3821   }
3822 };
3823 
3824 
3825 
3826 /**
3827   Acquire exclusive locks. There must be no granted locks in the
3828   context.
3829 
3830   This is a replacement of lock_table_names(). It is used in
3831   RENAME, DROP and other DDL SQL statements.
3832 
3833   @param  mdl_requests  List of requests for locks to be acquired.
3834 
3835   @param lock_wait_timeout  Seconds to wait before timeout.
3836 
3837   @note The list of requests should not contain non-exclusive lock requests.
3838         There should not be any acquired locks in the context.
3839 
3840   @note Assumes that one already owns scoped intention exclusive lock.
3841 
3842   @note If acquisition fails any locks with MDL_EXPLICIT duration that had
3843         already been taken, are released. Not just locks with MDL_STATEMENT
3844         and MDL_TRANSACTION duration. This makes acquition of MDL_EXPLICIT
3845         locks atomic (all or nothing). This is needed for the locking
3846         service plugin API.
3847 
3848   @retval FALSE  Success
3849   @retval TRUE   Failure
3850 */
3851 
acquire_locks(MDL_request_list * mdl_requests,ulong lock_wait_timeout)3852 bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
3853                                 ulong lock_wait_timeout)
3854 {
3855   MDL_request_list::Iterator it(*mdl_requests);
3856   MDL_request **p_req;
3857   MDL_savepoint mdl_svp= mdl_savepoint();
3858   /*
3859     Remember the first MDL_EXPLICIT ticket so that we can release
3860     any new such locks taken if acquisition fails.
3861   */
3862   MDL_ticket *explicit_front= m_tickets[MDL_EXPLICIT].front();
3863   const size_t req_count= mdl_requests->elements();
3864 
3865   if (req_count == 0)
3866     return FALSE;
3867 
3868   /* Sort requests according to MDL_key. */
3869   Prealloced_array<MDL_request*, 16>
3870     sort_buf(key_memory_MDL_context_acquire_locks);
3871   if (sort_buf.reserve(req_count))
3872     return TRUE;
3873 
3874   for (size_t ii=0; ii < req_count; ++ii)
3875   {
3876     sort_buf.push_back(it++);
3877   }
3878 
3879   std::sort(sort_buf.begin(), sort_buf.end(), MDL_request_cmp());
3880 
3881   size_t num_acquired= 0;
3882   for (p_req= sort_buf.begin(); p_req != sort_buf.end(); p_req++)
3883   {
3884     if (acquire_lock(*p_req, lock_wait_timeout))
3885       goto err;
3886     ++num_acquired;
3887   }
3888   return FALSE;
3889 
3890 err:
3891   /*
3892     Release locks we have managed to acquire so far.
3893     Use rollback_to_savepoint() since there may be duplicate
3894     requests that got assigned the same ticket.
3895   */
3896   rollback_to_savepoint(mdl_svp);
3897   /*
3898     Also release the MDL_EXPLICIT locks taken in this call.
3899     The locking service plugin API needs acquisition of such
3900     locks to be atomic as well.
3901   */
3902   release_locks_stored_before(MDL_EXPLICIT, explicit_front);
3903 
3904   /* Reset lock requests back to its initial state. */
3905   for (p_req= sort_buf.begin();
3906        p_req != sort_buf.begin() + num_acquired; p_req++)
3907   {
3908     (*p_req)->ticket= NULL;
3909   }
3910   return TRUE;
3911 }
3912 
3913 
3914 /**
3915   Upgrade a shared metadata lock.
3916 
3917   Used in ALTER TABLE and CREATE TABLE.
3918 
3919   @param mdl_ticket         Lock to upgrade.
3920   @param new_type           Lock type to upgrade to.
3921   @param lock_wait_timeout  Seconds to wait before timeout.
3922 
3923   @note In case of failure to upgrade lock (e.g. because upgrader
3924         was killed) leaves lock in its original state (locked in
3925         shared mode).
3926 
3927   @note There can be only one upgrader for a lock or we will have deadlock.
3928         This invariant is ensured by the fact that upgradeable locks SU, SNW
3929         and SNRW are not compatible with each other and themselves in case
3930         of ALTER TABLE operation.
3931         In case of CREATE TABLE operation there is chance of deadlock as 'S'
3932         is compatible with 'S'. But the deadlock is recovered by backoff and
3933         retry mechanism.
3934 
3935   @retval FALSE  Success
3936   @retval TRUE   Failure (thread was killed)
3937 */
3938 
3939 bool
upgrade_shared_lock(MDL_ticket * mdl_ticket,enum_mdl_type new_type,ulong lock_wait_timeout)3940 MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
3941                                  enum_mdl_type new_type,
3942                                  ulong lock_wait_timeout)
3943 {
3944   MDL_request mdl_new_lock_request;
3945   MDL_savepoint mdl_svp= mdl_savepoint();
3946   bool is_new_ticket;
3947   MDL_lock *lock;
3948 
3949   DBUG_ENTER("MDL_context::upgrade_shared_lock");
3950   DEBUG_SYNC(get_thd(), "mdl_upgrade_lock");
3951 
3952   /*
3953     Do nothing if already upgraded. Used when we FLUSH TABLE under
3954     LOCK TABLES and a table is listed twice in LOCK TABLES list.
3955   */
3956   if (mdl_ticket->has_stronger_or_equal_type(new_type))
3957     DBUG_RETURN(FALSE);
3958 
3959   MDL_REQUEST_INIT_BY_KEY(&mdl_new_lock_request,
3960                           &mdl_ticket->m_lock->key, new_type,
3961                           MDL_TRANSACTION);
3962 
3963   if (acquire_lock(&mdl_new_lock_request, lock_wait_timeout))
3964     DBUG_RETURN(TRUE);
3965 
3966   is_new_ticket= ! has_lock(mdl_svp, mdl_new_lock_request.ticket);
3967 
3968   lock= mdl_ticket->m_lock;
3969 
3970   /* Code below assumes that we were upgrading to "obtrusive" type of lock. */
3971   assert(lock->is_obtrusive_lock(new_type));
3972 
3973   /* Merge the acquired and the original lock. @todo: move to a method. */
3974   mysql_prlock_wrlock(&lock->m_rwlock);
3975   if (is_new_ticket)
3976   {
3977     lock->m_granted.remove_ticket(mdl_new_lock_request.ticket);
3978     /*
3979       We should not clear HAS_OBTRUSIVE flag in this case as we will
3980       get "obtrusive' lock as result in any case.
3981     */
3982     --lock->m_obtrusive_locks_granted_waiting_count;
3983   }
3984   /*
3985     Set the new type of lock in the ticket. To update state of
3986     MDL_lock object correctly we need to temporarily exclude
3987     ticket from the granted queue or "fast path" counter and
3988     then include lock back into granted queue.
3989     Note that with current code at this point we can't have
3990     "fast path" tickets as upgrade to "obtrusive" locks
3991     materializes tickets normally. Still we cover this case
3992     for completeness.
3993   */
3994   if (mdl_ticket->m_is_fast_path)
3995   {
3996     /*
3997       Decrement of counter in MDL_lock::m_fast_path_state needs to be done
3998       under protection of MDL_lock::m_rwlock to ensure that it is atomic with
3999       changes to MDL_lock::m_granted list and to enforce invariant [INV1].
4000       Note that since we have HAS_OBTRUSIVE flag set at this point all
4001       concurrent lock acquisitions and releases will have to acquire
4002       MDL_lock::m_rwlock, so nobody will see results of this decrement until
4003       m_rwlock is released.
4004     */
4005     lock->fast_path_state_add(
4006             -lock->get_unobtrusive_lock_increment(mdl_ticket->m_type));
4007     mdl_ticket->m_is_fast_path= false;
4008   }
4009   else
4010   {
4011     lock->m_granted.remove_ticket(mdl_ticket);
4012     /*
4013       Also if we are upgrading from "obtrusive" lock we need to temporarily
4014       decrement m_obtrusive_locks_granted_waiting_count counter.
4015       We should not clear HAS_OBTRUSIVE flag in this case as we will get
4016       "obtrusive' lock as result in any case.
4017     */
4018     if (lock->is_obtrusive_lock(mdl_ticket->m_type))
4019       --lock->m_obtrusive_locks_granted_waiting_count;
4020   }
4021 
4022   mdl_ticket->m_type= new_type;
4023 
4024   lock->m_granted.add_ticket(mdl_ticket);
4025   /*
4026     Since we always upgrade to "obtrusive" type of lock we need to
4027     increment m_obtrusive_locks_granted_waiting_count counter.
4028 
4029     HAS_OBTRUSIVE flag has been already set by acquire_lock()
4030     and should not have been cleared since then.
4031   */
4032   assert(lock->m_fast_path_state & MDL_lock::HAS_OBTRUSIVE);
4033   ++lock->m_obtrusive_locks_granted_waiting_count;
4034 
4035   mysql_prlock_unlock(&lock->m_rwlock);
4036 
4037   /*
4038     The below code can't handle situation when we upgrade to lock requiring
4039     SE notification and it turns out that we already have lock of this type
4040     associated with different ticket.
4041   */
4042   assert(is_new_ticket || ! mdl_new_lock_request.ticket->m_hton_notified);
4043 
4044   mdl_ticket->m_hton_notified= mdl_new_lock_request.ticket->m_hton_notified;
4045 
4046   if (is_new_ticket)
4047   {
4048     m_tickets[MDL_TRANSACTION].remove(mdl_new_lock_request.ticket);
4049     MDL_ticket::destroy(mdl_new_lock_request.ticket);
4050   }
4051 
4052   DBUG_RETURN(FALSE);
4053 }
4054 
4055 
4056 /**
4057   A fragment of recursive traversal of the wait-for graph
4058   in search for deadlocks. Direct the deadlock visitor to all
4059   contexts that own the lock the current node in the wait-for
4060   graph is waiting for.
4061   As long as the initial node is remembered in the visitor,
4062   a deadlock is found when the same node is seen twice.
4063 */
4064 
visit_subgraph(MDL_ticket * waiting_ticket,MDL_wait_for_graph_visitor * gvisitor)4065 bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket,
4066                               MDL_wait_for_graph_visitor *gvisitor)
4067 {
4068   MDL_ticket *ticket;
4069   MDL_context *src_ctx= waiting_ticket->get_ctx();
4070   bool result= TRUE;
4071 
4072   mysql_prlock_rdlock(&m_rwlock);
4073 
4074   /*
4075     Iterators must be initialized after taking a read lock.
4076 
4077     Note that MDL_ticket's which correspond to lock requests satisfied
4078     on "fast path" are not present in m_granted list and thus
4079     corresponding edges are missing from wait-for graph.
4080     It is OK since contexts with "fast path" tickets are not allowed to
4081     wait for any resource (they have to convert "fast path" tickets to
4082     normal tickets first) and thus cannot participate in deadlock.
4083     @sa MDL_contex::will_wait_for().
4084   */
4085   Ticket_iterator granted_it(m_granted);
4086   Ticket_iterator waiting_it(m_waiting);
4087 
4088   /*
4089     MDL_lock's waiting and granted queues and MDL_context::m_waiting_for
4090     member are updated by different threads when the lock is granted
4091     (see MDL_context::acquire_lock() and MDL_lock::reschedule_waiters()).
4092     As a result, here we may encounter a situation when MDL_lock data
4093     already reflects the fact that the lock was granted but
4094     m_waiting_for member has not been updated yet.
4095 
4096     For example, imagine that:
4097 
4098     thread1: Owns SNW lock on table t1.
4099     thread2: Attempts to acquire SW lock on t1,
4100              but sees an active SNW lock.
4101              Thus adds the ticket to the waiting queue and
4102              sets m_waiting_for to point to the ticket.
4103     thread1: Releases SNW lock, updates MDL_lock object to
4104              grant SW lock to thread2 (moves the ticket for
4105              SW from waiting to the active queue).
4106              Attempts to acquire a new SNW lock on t1,
4107              sees an active SW lock (since it is present in the
4108              active queue), adds ticket for SNW lock to the waiting
4109              queue, sets m_waiting_for to point to this ticket.
4110 
4111     At this point deadlock detection algorithm run by thread1 will see that:
4112     - Thread1 waits for SNW lock on t1 (since m_waiting_for is set).
4113     - SNW lock is not granted, because it conflicts with active SW lock
4114       owned by thread 2 (since ticket for SW is present in granted queue).
4115     - Thread2 waits for SW lock (since its m_waiting_for has not been
4116       updated yet!).
4117     - SW lock is not granted because there is pending SNW lock from thread1.
4118       Therefore deadlock should exist [sic!].
4119 
4120     To avoid detection of such false deadlocks we need to check the "actual"
4121     status of the ticket being waited for, before analyzing its blockers.
4122     We do this by checking the wait status of the context which is waiting
4123     for it. To avoid races this has to be done under protection of
4124     MDL_lock::m_rwlock lock.
4125   */
4126   if (src_ctx->m_wait.get_status() != MDL_wait::EMPTY)
4127   {
4128     result= FALSE;
4129     goto end;
4130   }
4131 
4132   /*
4133     To avoid visiting nodes which were already marked as victims of
4134     deadlock detection (or whose requests were already satisfied) we
4135     enter the node only after peeking at its wait status.
4136     This is necessary to avoid active waiting in a situation
4137     when previous searches for a deadlock already selected the
4138     node we're about to enter as a victim (see the comment
4139     in MDL_context::find_deadlock() for explanation why several searches
4140     can be performed for the same wait).
4141     There is no guarantee that the node isn't chosen a victim while we
4142     are visiting it but this is OK: in the worst case we might do some
4143     extra work and one more context might be chosen as a victim.
4144   */
4145   if (gvisitor->enter_node(src_ctx))
4146     goto end;
4147 
4148   /*
4149     We do a breadth-first search first -- that is, inspect all
4150     edges of the current node, and only then follow up to the next
4151     node. In workloads that involve wait-for graph loops this
4152     has proven to be a more efficient strategy [citation missing].
4153   */
4154   while ((ticket= granted_it++))
4155   {
4156     /* Filter out edges that point to the same node. */
4157     if (ticket->get_ctx() != src_ctx &&
4158         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
4159         gvisitor->inspect_edge(ticket->get_ctx()))
4160     {
4161       goto end_leave_node;
4162     }
4163   }
4164 
4165   while ((ticket= waiting_it++))
4166   {
4167     /* Filter out edges that point to the same node. */
4168     if (ticket->get_ctx() != src_ctx &&
4169         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
4170         gvisitor->inspect_edge(ticket->get_ctx()))
4171     {
4172       goto end_leave_node;
4173     }
4174   }
4175 
4176   /* Recurse and inspect all adjacent nodes. */
4177   granted_it.rewind();
4178   while ((ticket= granted_it++))
4179   {
4180     if (ticket->get_ctx() != src_ctx &&
4181         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
4182         ticket->get_ctx()->visit_subgraph(gvisitor))
4183     {
4184       goto end_leave_node;
4185     }
4186   }
4187 
4188   waiting_it.rewind();
4189   while ((ticket= waiting_it++))
4190   {
4191     if (ticket->get_ctx() != src_ctx &&
4192         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
4193         ticket->get_ctx()->visit_subgraph(gvisitor))
4194     {
4195       goto end_leave_node;
4196     }
4197   }
4198 
4199   result= FALSE;
4200 
4201 end_leave_node:
4202   gvisitor->leave_node(src_ctx);
4203 
4204 end:
4205   mysql_prlock_unlock(&m_rwlock);
4206   return result;
4207 }
4208 
4209 
4210 /**
4211   Traverse a portion of wait-for graph which is reachable
4212   through the edge represented by this ticket and search
4213   for deadlocks.
4214 
4215   @retval TRUE  A deadlock is found. A pointer to deadlock
4216                  victim is saved in the visitor.
4217   @retval FALSE
4218 */
4219 
accept_visitor(MDL_wait_for_graph_visitor * gvisitor)4220 bool MDL_ticket::accept_visitor(MDL_wait_for_graph_visitor *gvisitor)
4221 {
4222   return m_lock->visit_subgraph(this, gvisitor);
4223 }
4224 
4225 
4226 /**
4227   A fragment of recursive traversal of the wait-for graph of
4228   MDL contexts in the server in search for deadlocks.
4229   Assume this MDL context is a node in the wait-for graph,
4230   and direct the visitor to all adjacent nodes. As long
4231   as the starting node is remembered in the visitor, a
4232   deadlock is found when the same node is visited twice.
4233   One MDL context is connected to another in the wait-for
4234   graph if it waits on a resource that is held by the other
4235   context.
4236 
4237   @retval TRUE  A deadlock is found. A pointer to deadlock
4238                 victim is saved in the visitor.
4239   @retval FALSE
4240 */
4241 
visit_subgraph(MDL_wait_for_graph_visitor * gvisitor)4242 bool MDL_context::visit_subgraph(MDL_wait_for_graph_visitor *gvisitor)
4243 {
4244   bool result= FALSE;
4245 
4246   mysql_prlock_rdlock(&m_LOCK_waiting_for);
4247 
4248   if (m_waiting_for)
4249     result= m_waiting_for->accept_visitor(gvisitor);
4250 
4251   mysql_prlock_unlock(&m_LOCK_waiting_for);
4252 
4253   return result;
4254 }
4255 
4256 
4257 /**
4258   Try to find a deadlock. This function produces no errors.
4259 
4260   @note If during deadlock resolution context which performs deadlock
4261         detection is chosen as a victim it will be informed about the
4262         fact by setting VICTIM status to its wait slot.
4263 */
4264 
find_deadlock()4265 void MDL_context::find_deadlock()
4266 {
4267   while (1)
4268   {
4269     /*
4270       The fact that we use fresh instance of gvisitor for each
4271       search performed by find_deadlock() below is important,
4272       the code responsible for victim selection relies on this.
4273     */
4274     Deadlock_detection_visitor dvisitor(this);
4275     MDL_context *victim;
4276 
4277     if (! visit_subgraph(&dvisitor))
4278     {
4279       /* No deadlocks are found! */
4280       break;
4281     }
4282 
4283     victim= dvisitor.get_victim();
4284 
4285     /*
4286       Failure to change status of the victim is OK as it means
4287       that the victim has received some other message and is
4288       about to stop its waiting/to break deadlock loop.
4289       Even when the initiator of the deadlock search is
4290       chosen the victim, we need to set the respective wait
4291       result in order to "close" it for any attempt to
4292       schedule the request.
4293       This is needed to avoid a possible race during
4294       cleanup in case when the lock request on which the
4295       context was waiting is concurrently satisfied.
4296     */
4297     (void) victim->m_wait.set_status(MDL_wait::VICTIM);
4298     victim->unlock_deadlock_victim();
4299 
4300     if (victim == this)
4301       break;
4302     /*
4303       After adding a new edge to the waiting graph we found that it
4304       creates a loop (i.e. there is a deadlock). We decided to destroy
4305       this loop by removing an edge, but not the one that we added.
4306       Since this doesn't guarantee that all loops created by addition
4307       of the new edge are destroyed, we have to repeat the search.
4308     */
4309   }
4310 }
4311 
4312 
4313 /**
4314   Release lock.
4315 
4316   @param duration Lock duration.
4317   @param ticket   Ticket for lock to be released.
4318 
4319 */
4320 
release_lock(enum_mdl_duration duration,MDL_ticket * ticket)4321 void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket)
4322 {
4323   MDL_lock *lock= ticket->m_lock;
4324   MDL_key key_for_hton;
4325   DBUG_ENTER("MDL_context::release_lock");
4326   DBUG_PRINT("enter", ("db=%s name=%s", lock->key.db_name(),
4327                                         lock->key.name()));
4328 
4329   assert(this == ticket->get_ctx());
4330   mysql_mutex_assert_not_owner(&LOCK_open);
4331 
4332 
4333   /*
4334     If lock we are about to release requires post-release notification
4335     of SEs, we need to save its MDL_key on stack. This is necessary to
4336     be able to pass this key to SEs after corresponding MDL_lock object
4337     might be freed as result of lock release.
4338   */
4339   if (ticket->m_hton_notified)
4340     key_for_hton.mdl_key_init(&lock->key);
4341 
4342   if (ticket->m_is_fast_path)
4343   {
4344     /*
4345       We are releasing ticket which represents lock request which was
4346       satisfied using "fast path". We can use "fast path" release
4347       algorithm of release for it as well.
4348     */
4349     MDL_lock::fast_path_state_t unobtrusive_lock_increment=
4350       lock->get_unobtrusive_lock_increment(ticket->get_type());
4351     bool is_singleton= mdl_locks.is_lock_object_singleton(&lock->key);
4352 
4353     /* We should not have "fast path" tickets for "obtrusive" lock types. */
4354     assert(unobtrusive_lock_increment != 0);
4355 
4356     /*
4357       We need decrement part of m_fast_path_state which holds number of
4358       acquired "fast path" locks of this type. This needs to be done
4359       by atomic compare-and-swap.
4360 
4361       The same atomic compare-and-swap needs to check:
4362 
4363       *) If HAS_OBSTRUSIVE flag is set. In this case we need to acquire
4364          MDL_lock::m_rwlock before changing m_fast_path_state. This is
4365          needed to enforce invariant [INV1] and also because we might
4366          have to atomically wake-up some waiters for our "unobtrusive"
4367          lock to go away.
4368       *) If we are about to release last "fast path" lock and there
4369          are no "slow path" locks. In this case we need to count
4370          MDL_lock object as unused and maybe even delete some
4371          unused MDL_lock objects eventually.
4372 
4373       Similarly to the case with "fast path" acquisition it is OK to
4374       perform ordinary read of MDL_lock::m_fast_path_state as correctness
4375       of value returned by it will be validated by atomic compare-and-swap.
4376       Again, in theory, this algorithm will work correctly if the read will
4377       return random values.
4378     */
4379     MDL_lock::fast_path_state_t old_state= lock->m_fast_path_state;
4380     bool last_use;
4381 
4382     do
4383     {
4384       if (old_state & MDL_lock::HAS_OBTRUSIVE)
4385       {
4386         mysql_prlock_wrlock(&lock->m_rwlock);
4387         /*
4388           It is possible that obtrusive lock has gone away since we have
4389           read m_fast_path_state value. This means that there is possibility
4390           that there are no "slow path" locks (HAS_SLOW_PATH is not set) and
4391           we are about to release last "fast path" lock. In this case MDL_lock
4392           will become unused and needs to be counted as such eventually.
4393         */
4394         last_use= (lock->fast_path_state_add(-unobtrusive_lock_increment) ==
4395                    unobtrusive_lock_increment);
4396         /*
4397           There might be some lock requests waiting for ticket being released
4398           to go away. Since this is "fast path" ticket it represents
4399           "unobtrusive" type of lock. In this case if there are any waiters
4400           for it there should be "obtrusive" type of request among them.
4401         */
4402         if (lock->m_obtrusive_locks_granted_waiting_count)
4403           lock->reschedule_waiters();
4404         mysql_prlock_unlock(&lock->m_rwlock);
4405         goto end_fast_path;
4406       }
4407       /*
4408         If there are no "slow path" locks (HAS_SLOW_PATH is not set) and
4409         we are about to release last "fast path" lock - MDL_lock object
4410         will become unused and needs to be counted as such.
4411       */
4412       last_use= (old_state == unobtrusive_lock_increment);
4413     }
4414     while (! lock->fast_path_state_cas(&old_state,
4415                                        old_state - unobtrusive_lock_increment));
4416 
4417 end_fast_path:
4418     /* Don't count singleton MDL_lock objects as unused. */
4419     if (last_use && ! is_singleton)
4420       mdl_locks.lock_object_unused(this, m_pins);
4421   }
4422   else
4423   {
4424     /*
4425       Lock request represented by ticket was acquired using "slow path"
4426       or ticket was materialized later. We need to use "slow path" release.
4427     */
4428     lock->remove_ticket(this, m_pins, &MDL_lock::m_granted, ticket);
4429   }
4430 
4431   m_tickets[duration].remove(ticket);
4432 
4433   if (ticket->m_hton_notified)
4434   {
4435     mysql_mdl_set_status(ticket->m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
4436     m_owner->notify_hton_post_release_exclusive(&key_for_hton);
4437   }
4438 
4439   MDL_ticket::destroy(ticket);
4440 
4441   DBUG_VOID_RETURN;
4442 }
4443 
4444 
4445 /**
4446   Release lock with explicit duration.
4447 
4448   @param ticket   Ticket for lock to be released.
4449 
4450 */
4451 
release_lock(MDL_ticket * ticket)4452 void MDL_context::release_lock(MDL_ticket *ticket)
4453 {
4454   assert(ticket->m_duration == MDL_EXPLICIT);
4455 
4456   release_lock(MDL_EXPLICIT, ticket);
4457 }
4458 
4459 
4460 /**
4461   Release all locks associated with the context. If the sentinel
4462   is not NULL, do not release locks stored in the list after and
4463   including the sentinel.
4464 
4465   Statement and transactional locks are added to the beginning of
4466   the corresponding lists, i.e. stored in reverse temporal order.
4467   This allows to employ this function to:
4468   - back off in case of a lock conflict.
4469   - release all locks in the end of a statement or transaction
4470   - rollback to a savepoint.
4471 */
4472 
release_locks_stored_before(enum_mdl_duration duration,MDL_ticket * sentinel)4473 void MDL_context::release_locks_stored_before(enum_mdl_duration duration,
4474                                               MDL_ticket *sentinel)
4475 {
4476   MDL_ticket *ticket;
4477   Ticket_iterator it(m_tickets[duration]);
4478   DBUG_ENTER("MDL_context::release_locks_stored_before");
4479 
4480   if (m_tickets[duration].is_empty())
4481     DBUG_VOID_RETURN;
4482 
4483   while ((ticket= it++) && ticket != sentinel)
4484   {
4485     DBUG_PRINT("info", ("found lock to release ticket=%p", ticket));
4486     release_lock(duration, ticket);
4487   }
4488 
4489   DBUG_VOID_RETURN;
4490 }
4491 
4492 
4493 /**
4494   Release all explicit locks in the context which correspond to the
4495   same name/object as this lock request.
4496 
4497   @param name      One of the locks for the name/object for which all
4498                    locks should be released.
4499 */
4500 
release_all_locks_for_name(MDL_ticket * name)4501 void MDL_context::release_all_locks_for_name(MDL_ticket *name)
4502 {
4503   /* Use MDL_ticket::m_lock to identify other locks for the same object. */
4504   MDL_lock *lock= name->m_lock;
4505 
4506   /* Remove matching lock tickets from the context. */
4507   MDL_ticket *ticket;
4508   Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
4509 
4510   while ((ticket= it_ticket++))
4511   {
4512     assert(ticket->m_lock);
4513     if (ticket->m_lock == lock)
4514       release_lock(MDL_EXPLICIT, ticket);
4515   }
4516 }
4517 
4518 
4519 /**
4520   Release all explicit locks in the context for which the release()
4521   method of the provided visitor evalates to true.
4522 
4523   @param visitor   Object to ask if the lock should be released.
4524 */
4525 
release_locks(MDL_release_locks_visitor * visitor)4526 void MDL_context::release_locks(MDL_release_locks_visitor *visitor)
4527 {
4528   /* Remove matching lock tickets from the context. */
4529   MDL_ticket *ticket;
4530   Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
4531 
4532   while ((ticket= it_ticket++))
4533   {
4534     assert(ticket->m_lock);
4535     if (visitor->release(ticket))
4536       release_lock(MDL_EXPLICIT, ticket);
4537   }
4538 }
4539 
4540 
4541 /**
4542   Downgrade an EXCLUSIVE or SHARED_NO_WRITE lock to shared metadata lock.
4543 
4544   @param type  Type of lock to which exclusive lock should be downgraded.
4545 */
4546 
downgrade_lock(enum_mdl_type new_type)4547 void MDL_ticket::downgrade_lock(enum_mdl_type new_type)
4548 {
4549   bool new_type_is_unobtrusive;
4550   mysql_mutex_assert_not_owner(&LOCK_open);
4551 
4552   /*
4553     Do nothing if already downgraded. Used when we FLUSH TABLE under
4554     LOCK TABLES and a table is listed twice in LOCK TABLES list.
4555     Note that this code might even try to "downgrade" a weak lock
4556     (e.g. SW) to a stronger one (e.g SNRW). So we can't even assert
4557     here that target lock is weaker than existing lock.
4558   */
4559   if (m_type == new_type || !has_stronger_or_equal_type(new_type))
4560     return;
4561 
4562   /* Only allow downgrade from EXCLUSIVE and SHARED_NO_WRITE. */
4563   assert(m_type == MDL_EXCLUSIVE ||
4564          m_type == MDL_SHARED_NO_WRITE);
4565 
4566   /* Below we assume that we always downgrade "obtrusive" locks. */
4567   assert(m_lock->is_obtrusive_lock(m_type));
4568 
4569   new_type_is_unobtrusive= ! m_lock->is_obtrusive_lock(new_type);
4570 
4571   mysql_prlock_wrlock(&m_lock->m_rwlock);
4572   /*
4573     To update state of MDL_lock object correctly we need to temporarily
4574     exclude ticket from the granted queue and then include it back.
4575 
4576     Since we downgrade only "obtrusive" locks we can always assume that the
4577     ticket for the lock being downgraded is a "slow path" ticket.
4578     If we are downgrading to non-"obtrusive" lock we also should decrement
4579     counter of waiting and granted "obtrusive" locks.
4580   */
4581   m_lock->m_granted.remove_ticket(this);
4582   if (new_type_is_unobtrusive)
4583   {
4584     if ((--m_lock->m_obtrusive_locks_granted_waiting_count) == 0)
4585     {
4586       /*
4587         We are downgrading the last "obtrusive" lock. So we need to clear
4588         HAS_OBTRUSIVE flag.
4589         Note that it doesn't matter that we do this before including ticket
4590         to MDL_lock::m_granted list. Threads requesting "obtrusive" locks
4591         won't see this until MDL_lock::m_rwlock is released. And threads
4592         requesting "unobtrusive" locks don't care about this ticket.
4593       */
4594       MDL_lock::fast_path_state_t old_state= m_lock->m_fast_path_state;
4595       while (! m_lock->fast_path_state_cas(&old_state,
4596                          old_state & ~MDL_lock::HAS_OBTRUSIVE))
4597       { }
4598     }
4599   }
4600   m_type= new_type;
4601   m_lock->m_granted.add_ticket(this);
4602   m_lock->reschedule_waiters();
4603   mysql_prlock_unlock(&m_lock->m_rwlock);
4604 
4605   /*
4606     When we downgrade X lock for which SEs were notified about lock
4607     acquisition we treat situation in the same way as lock release
4608     (from SEs notification point of view).
4609   */
4610   if (m_hton_notified)
4611   {
4612     mysql_mdl_set_status(m_psi, MDL_ticket::POST_RELEASE_NOTIFY);
4613     m_ctx->get_owner()->notify_hton_post_release_exclusive(&m_lock->key);
4614     m_hton_notified= false;
4615     mysql_mdl_set_status(m_psi, MDL_ticket::GRANTED);
4616   }
4617 }
4618 
4619 
4620 /**
4621   Auxiliary function which allows to check if we have some kind of lock on
4622   a object. Returns TRUE if we have a lock of an equal to given or stronger
4623   type.
4624 
4625   @param mdl_namespace Id of object namespace
4626   @param db            Name of the database
4627   @param name          Name of the object
4628   @param mdl_type      Lock type. Pass in the weakest type to find
4629                        out if there is at least some lock.
4630 
4631   @return TRUE if current context contains satisfied lock for the object,
4632           FALSE otherwise.
4633 */
4634 
4635 bool
owns_equal_or_stronger_lock(MDL_key::enum_mdl_namespace mdl_namespace,const char * db,const char * name,enum_mdl_type mdl_type)4636 MDL_context::owns_equal_or_stronger_lock(
4637                MDL_key::enum_mdl_namespace mdl_namespace,
4638                const char *db, const char *name,
4639                enum_mdl_type mdl_type)
4640 {
4641   MDL_request mdl_request;
4642   enum_mdl_duration not_unused;
4643   /* We don't care about exact duration of lock here. */
4644   MDL_REQUEST_INIT(&mdl_request,
4645                    mdl_namespace, db, name, mdl_type, MDL_TRANSACTION);
4646   MDL_ticket *ticket= find_ticket(&mdl_request, &not_unused);
4647 
4648   assert(ticket == NULL || ticket->m_lock);
4649 
4650   return ticket;
4651 }
4652 
4653 
4654 /**
4655   Find the first context which owns the lock and inspect it by
4656   calling MDL_context_visitor::visit_context() method.
4657 
4658   @return True in case error (e.g. OOM). False otherwise. There
4659           is no guarantee that owner was found in either case.
4660   @note This method only works properly for locks which were
4661         acquired using "slow" path.
4662 */
4663 
find_lock_owner(const MDL_key * mdl_key,MDL_context_visitor * visitor)4664 bool MDL_context::find_lock_owner(const MDL_key *mdl_key,
4665                                   MDL_context_visitor *visitor)
4666 {
4667   MDL_lock *lock;
4668   MDL_context *owner;
4669   bool pinned;
4670 
4671   if (fix_pins())
4672     return true;
4673 
4674 retry:
4675   if ((lock= mdl_locks.find(m_pins, mdl_key, &pinned)) == MY_ERRPTR)
4676     return true;
4677 
4678   /* No MDL_lock object, no owner, nothing to visit. */
4679   if (lock == NULL)
4680     return false;
4681 
4682   mysql_prlock_rdlock(&lock->m_rwlock);
4683 
4684   if (lock->m_fast_path_state & MDL_lock::IS_DESTROYED)
4685   {
4686     mysql_prlock_unlock(&lock->m_rwlock);
4687     if (pinned)
4688       lf_hash_search_unpin(m_pins);
4689     DEBUG_SYNC(get_thd(), "mdl_find_lock_owner_is_destroyed");
4690     goto retry;
4691   }
4692 
4693   if (pinned)
4694     lf_hash_search_unpin(m_pins);
4695 
4696   if ((owner= lock->get_lock_owner()))
4697     visitor->visit_context(owner);
4698 
4699   mysql_prlock_unlock(&lock->m_rwlock);
4700 
4701   return false;
4702 }
4703 
4704 
4705 /**
4706   Check if we have any pending locks which conflict with existing shared lock.
4707 
4708   @pre The ticket must match an acquired lock.
4709 
4710   @return TRUE if there is a conflicting lock request, FALSE otherwise.
4711 */
4712 
has_pending_conflicting_lock() const4713 bool MDL_ticket::has_pending_conflicting_lock() const
4714 {
4715   return m_lock->has_pending_conflicting_lock(m_type);
4716 }
4717 
4718 /** Return a key identifying this lock. */
4719 
get_key() const4720 const MDL_key *MDL_ticket::get_key() const
4721 {
4722   return &m_lock->key;
4723 }
4724 
4725 /**
4726   Releases metadata locks that were acquired after a specific savepoint.
4727 
4728   @note Used to release tickets acquired during a savepoint unit.
4729   @note It's safe to iterate and unlock any locks after taken after this
4730         savepoint because other statements that take other special locks
4731         cause a implicit commit (ie LOCK TABLES).
4732 */
4733 
rollback_to_savepoint(const MDL_savepoint & mdl_savepoint)4734 void MDL_context::rollback_to_savepoint(const MDL_savepoint &mdl_savepoint)
4735 {
4736   DBUG_ENTER("MDL_context::rollback_to_savepoint");
4737 
4738   /* If savepoint is NULL, it is from the start of the transaction. */
4739   release_locks_stored_before(MDL_STATEMENT, mdl_savepoint.m_stmt_ticket);
4740   release_locks_stored_before(MDL_TRANSACTION, mdl_savepoint.m_trans_ticket);
4741 
4742   DBUG_VOID_RETURN;
4743 }
4744 
4745 
4746 /**
4747   Release locks acquired by normal statements (SELECT, UPDATE,
4748   DELETE, etc) in the course of a transaction. Do not release
4749   HANDLER locks, if there are any.
4750 
4751   This method is used at the end of a transaction, in
4752   implementation of COMMIT (implicit or explicit) and ROLLBACK.
4753 */
4754 
release_transactional_locks()4755 void MDL_context::release_transactional_locks()
4756 {
4757   DBUG_ENTER("MDL_context::release_transactional_locks");
4758   release_locks_stored_before(MDL_STATEMENT, NULL);
4759   release_locks_stored_before(MDL_TRANSACTION, NULL);
4760   DBUG_VOID_RETURN;
4761 }
4762 
4763 
release_statement_locks()4764 void MDL_context::release_statement_locks()
4765 {
4766   DBUG_ENTER("MDL_context::release_transactional_locks");
4767   release_locks_stored_before(MDL_STATEMENT, NULL);
4768   DBUG_VOID_RETURN;
4769 }
4770 
4771 
4772 /**
4773   Does this savepoint have this lock?
4774 
4775   @retval TRUE  The ticket is older than the savepoint or
4776                 is an LT, HA or GLR ticket. Thus it belongs
4777                 to the savepoint or has explicit duration.
4778   @retval FALSE The ticket is newer than the savepoint.
4779                 and is not an LT, HA or GLR ticket.
4780 */
4781 
has_lock(const MDL_savepoint & mdl_savepoint,MDL_ticket * mdl_ticket)4782 bool MDL_context::has_lock(const MDL_savepoint &mdl_savepoint,
4783                            MDL_ticket *mdl_ticket)
4784 {
4785   MDL_ticket *ticket;
4786   /* Start from the beginning, most likely mdl_ticket's been just acquired. */
4787   MDL_context::Ticket_iterator s_it(m_tickets[MDL_STATEMENT]);
4788   MDL_context::Ticket_iterator t_it(m_tickets[MDL_TRANSACTION]);
4789 
4790   while ((ticket= s_it++) && ticket != mdl_savepoint.m_stmt_ticket)
4791   {
4792     if (ticket == mdl_ticket)
4793       return FALSE;
4794   }
4795 
4796   while ((ticket= t_it++) && ticket != mdl_savepoint.m_trans_ticket)
4797   {
4798     if (ticket == mdl_ticket)
4799       return FALSE;
4800   }
4801   return TRUE;
4802 }
4803 
4804 
4805 /**
4806   Does this context have an lock of the given namespace?
4807 
4808   @retval true    At least one lock of given namespace held
4809   @retval false   No locks of the given namespace held
4810 */
4811 
has_locks(MDL_key::enum_mdl_namespace mdl_namespace) const4812 bool MDL_context::has_locks(MDL_key::enum_mdl_namespace mdl_namespace) const
4813 {
4814   MDL_ticket *ticket;
4815 
4816   for (int i=0; i < MDL_DURATION_END; i++)
4817   {
4818     enum_mdl_duration duration= static_cast<enum_mdl_duration>(i);
4819 
4820     Ticket_iterator it(m_tickets[duration]);
4821     while ((ticket= it++))
4822     {
4823       if (ticket->get_key()->mdl_namespace() == mdl_namespace)
4824         return true;
4825     }
4826   }
4827   return false;
4828 }
4829 
4830 
4831 /**
4832   Do we hold any locks which are possibly being waited
4833   for by another MDL_context?
4834 
4835   @retval TRUE  A lock being 'waited_for' was found.
4836   @retval FALSE No one waits for the lock(s) we hold.
4837 
4838   @note Should only be called from the thread which
4839         owns the MDL_context
4840 */
4841 
has_locks_waited_for() const4842 bool MDL_context::has_locks_waited_for() const
4843 {
4844   MDL_ticket *ticket;
4845 
4846   for (int i=0; i < MDL_DURATION_END; i++)
4847   {
4848     const enum_mdl_duration duration= static_cast<enum_mdl_duration>(i);
4849     Ticket_iterator it(m_tickets[duration]);
4850     while ((ticket= it++))
4851     {
4852       MDL_lock *const lock= ticket->m_lock;
4853 
4854       mysql_prlock_rdlock(&lock->m_rwlock);
4855       const bool has_waiters= !lock->m_waiting.is_empty();
4856       mysql_prlock_unlock(&lock->m_rwlock);
4857 
4858       if (!has_waiters)
4859         return true;
4860     }
4861   }
4862   return false;
4863 }
4864 
4865 
4866 
4867 /**
4868   Change lock duration for transactional lock.
4869 
4870   @param ticket   Ticket representing lock.
4871   @param duration Lock duration to be set.
4872 
4873   @note This method only supports changing duration of
4874         transactional lock to some other duration.
4875 */
4876 
set_lock_duration(MDL_ticket * mdl_ticket,enum_mdl_duration duration)4877 void MDL_context::set_lock_duration(MDL_ticket *mdl_ticket,
4878                                     enum_mdl_duration duration)
4879 {
4880   assert(mdl_ticket->m_duration == MDL_TRANSACTION &&
4881          duration != MDL_TRANSACTION);
4882 
4883   m_tickets[MDL_TRANSACTION].remove(mdl_ticket);
4884   m_tickets[duration].push_front(mdl_ticket);
4885 #ifndef NDEBUG
4886   mdl_ticket->m_duration= duration;
4887 #endif
4888 }
4889 
4890 
4891 /**
4892   Set explicit duration for all locks in the context.
4893 */
4894 
set_explicit_duration_for_all_locks()4895 void MDL_context::set_explicit_duration_for_all_locks()
4896 {
4897   int i;
4898   MDL_ticket *ticket;
4899 
4900   /*
4901     In the most common case when this function is called list
4902     of transactional locks is bigger than list of locks with
4903     explicit duration. So we start by swapping these two lists
4904     and then move elements from new list of transactional
4905     locks and list of statement locks to list of locks with
4906     explicit duration.
4907   */
4908 
4909   m_tickets[MDL_EXPLICIT].swap(m_tickets[MDL_TRANSACTION]);
4910 
4911   for (i= 0; i < MDL_EXPLICIT; i++)
4912   {
4913     Ticket_iterator it_ticket(m_tickets[i]);
4914 
4915     while ((ticket= it_ticket++))
4916     {
4917       m_tickets[i].remove(ticket);
4918       m_tickets[MDL_EXPLICIT].push_front(ticket);
4919     }
4920   }
4921 
4922 #ifndef NDEBUG
4923   Ticket_iterator exp_it(m_tickets[MDL_EXPLICIT]);
4924 
4925   while ((ticket= exp_it++))
4926     ticket->m_duration= MDL_EXPLICIT;
4927 #endif
4928 }
4929 
4930 
4931 /**
4932   Set transactional duration for all locks in the context.
4933 */
4934 
set_transaction_duration_for_all_locks()4935 void MDL_context::set_transaction_duration_for_all_locks()
4936 {
4937   MDL_ticket *ticket;
4938 
4939   /*
4940     In the most common case when this function is called list
4941     of explicit locks is bigger than two other lists (in fact,
4942     list of statement locks is always empty). So we start by
4943     swapping list of explicit and transactional locks and then
4944     move contents of new list of explicit locks to list of
4945     locks with transactional duration.
4946   */
4947 
4948   assert(m_tickets[MDL_STATEMENT].is_empty());
4949 
4950   m_tickets[MDL_TRANSACTION].swap(m_tickets[MDL_EXPLICIT]);
4951 
4952   Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
4953 
4954   while ((ticket= it_ticket++))
4955   {
4956     m_tickets[MDL_EXPLICIT].remove(ticket);
4957     m_tickets[MDL_TRANSACTION].push_front(ticket);
4958   }
4959 
4960 #ifndef NDEBUG
4961   Ticket_iterator trans_it(m_tickets[MDL_TRANSACTION]);
4962 
4963   while ((ticket= trans_it++))
4964     ticket->m_duration= MDL_TRANSACTION;
4965 #endif
4966 }
4967