1 /* Copyright (c) 2007, 2012, 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 as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software Foundation,
14    51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
15 
16 
17 #include "mariadb.h"
18 #include "sql_class.h"
19 #include "debug_sync.h"
20 #include "sql_array.h"
21 #include "rpl_rli.h"
22 #include <lf.h>
23 #include "unireg.h"
24 #include <mysql/plugin.h>
25 #include <mysql/service_thd_wait.h>
26 #include <mysql/psi/mysql_stage.h>
27 #ifdef HAVE_PSI_INTERFACE
28 static PSI_mutex_key key_MDL_wait_LOCK_wait_status;
29 
30 static PSI_mutex_info all_mdl_mutexes[]=
31 {
32   { &key_MDL_wait_LOCK_wait_status, "MDL_wait::LOCK_wait_status", 0}
33 };
34 
35 static PSI_rwlock_key key_MDL_lock_rwlock;
36 static PSI_rwlock_key key_MDL_context_LOCK_waiting_for;
37 
38 static PSI_rwlock_info all_mdl_rwlocks[]=
39 {
40   { &key_MDL_lock_rwlock, "MDL_lock::rwlock", 0},
41   { &key_MDL_context_LOCK_waiting_for, "MDL_context::LOCK_waiting_for", 0}
42 };
43 
44 static PSI_cond_key key_MDL_wait_COND_wait_status;
45 
46 static PSI_cond_info all_mdl_conds[]=
47 {
48   { &key_MDL_wait_COND_wait_status, "MDL_context::COND_wait_status", 0}
49 };
50 
51 /**
52   Initialise all the performance schema instrumentation points
53   used by the MDL subsystem.
54 */
init_mdl_psi_keys(void)55 static void init_mdl_psi_keys(void)
56 {
57   int count;
58 
59   count= array_elements(all_mdl_mutexes);
60   mysql_mutex_register("sql", all_mdl_mutexes, count);
61 
62   count= array_elements(all_mdl_rwlocks);
63   mysql_rwlock_register("sql", all_mdl_rwlocks, count);
64 
65   count= array_elements(all_mdl_conds);
66   mysql_cond_register("sql", all_mdl_conds, count);
67 
68   MDL_key::init_psi_keys();
69 }
70 #endif /* HAVE_PSI_INTERFACE */
71 
72 
73 /**
74   Thread state names to be used in case when we have to wait on resource
75   belonging to certain namespace.
76 */
77 
78 PSI_stage_info MDL_key::m_namespace_to_wait_state_name[NAMESPACE_END]=
79 {
80   {0, "Waiting for backup lock", 0},
81   {0, "Waiting for schema metadata lock", 0},
82   {0, "Waiting for table metadata lock", 0},
83   {0, "Waiting for stored function metadata lock", 0},
84   {0, "Waiting for stored procedure metadata lock", 0},
85   {0, "Waiting for stored package body metadata lock", 0},
86   {0, "Waiting for trigger metadata lock", 0},
87   {0, "Waiting for event metadata lock", 0},
88   {0, "User lock", 0} /* Be compatible with old status. */
89 };
90 
91 
92 static const LEX_STRING lock_types[]=
93 {
94   { C_STRING_WITH_LEN("MDL_INTENTION_EXCLUSIVE") },
95   { C_STRING_WITH_LEN("MDL_SHARED") },
96   { C_STRING_WITH_LEN("MDL_SHARED_HIGH_PRIO") },
97   { C_STRING_WITH_LEN("MDL_SHARED_READ") },
98   { C_STRING_WITH_LEN("MDL_SHARED_WRITE") },
99   { C_STRING_WITH_LEN("MDL_SHARED_UPGRADABLE") },
100   { C_STRING_WITH_LEN("MDL_SHARED_READ_ONLY") },
101   { C_STRING_WITH_LEN("MDL_SHARED_NO_WRITE") },
102   { C_STRING_WITH_LEN("MDL_SHARED_NO_READ_WRITE") },
103   { C_STRING_WITH_LEN("MDL_EXCLUSIVE") },
104 };
105 
106 
107 static const LEX_STRING backup_lock_types[]=
108 {
109   { C_STRING_WITH_LEN("MDL_BACKUP_START") },
110   { C_STRING_WITH_LEN("MDL_BACKUP_FLUSH") },
111   { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_FLUSH") },
112   { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_DDL") },
113   { C_STRING_WITH_LEN("MDL_BACKUP_WAIT_COMMIT") },
114   { C_STRING_WITH_LEN("MDL_BACKUP_FTWRL1") },
115   { C_STRING_WITH_LEN("MDL_BACKUP_FTWRL2") },
116   { C_STRING_WITH_LEN("MDL_BACKUP_DML") },
117   { C_STRING_WITH_LEN("MDL_BACKUP_TRANS_DML") },
118   { C_STRING_WITH_LEN("MDL_BACKUP_SYS_DML") },
119   { C_STRING_WITH_LEN("MDL_BACKUP_DDL") },
120   { C_STRING_WITH_LEN("MDL_BACKUP_BLOCK_DDL") },
121   { C_STRING_WITH_LEN("MDL_BACKUP_ALTER_COPY") },
122   { C_STRING_WITH_LEN("MDL_BACKUP_COMMIT") }
123 };
124 
125 
126 #ifdef HAVE_PSI_INTERFACE
init_psi_keys()127 void MDL_key::init_psi_keys()
128 {
129   int i;
130   int count;
131   PSI_stage_info *info __attribute__((unused));
132 
133   count= array_elements(MDL_key::m_namespace_to_wait_state_name);
134   for (i= 0; i<count; i++)
135   {
136     /* mysql_stage_register wants an array of pointers, registering 1 by 1. */
137     info= & MDL_key::m_namespace_to_wait_state_name[i];
138     mysql_stage_register("sql", &info, 1);
139   }
140 }
141 #endif
142 
143 static bool mdl_initialized= 0;
144 
145 
146 /**
147   A collection of all MDL locks. A singleton,
148   there is only one instance of the map in the server.
149 */
150 
151 class MDL_map
152 {
153 public:
154   void init();
155   void destroy();
156   MDL_lock *find_or_insert(LF_PINS *pins, const MDL_key *key);
157   unsigned long get_lock_owner(LF_PINS *pins, const MDL_key *key);
158   void remove(LF_PINS *pins, MDL_lock *lock);
get_pins()159   LF_PINS *get_pins() { return lf_hash_get_pins(&m_locks); }
160 private:
161   LF_HASH m_locks; /**< All acquired locks in the server. */
162   /** Pre-allocated MDL_lock object for BACKUP namespace. */
163   MDL_lock *m_backup_lock;
164   friend int mdl_iterate(mdl_iterator_callback, void *);
165 };
166 
167 
168 /**
169   A context of the recursive traversal through all contexts
170   in all sessions in search for deadlock.
171 */
172 
173 class Deadlock_detection_visitor: public MDL_wait_for_graph_visitor
174 {
175 public:
Deadlock_detection_visitor(MDL_context * start_node_arg)176   Deadlock_detection_visitor(MDL_context *start_node_arg)
177     : m_start_node(start_node_arg),
178       m_victim(NULL),
179       m_current_search_depth(0),
180       m_found_deadlock(FALSE)
181   {}
182   virtual bool enter_node(MDL_context *node);
183   virtual void leave_node(MDL_context *node);
184 
185   virtual bool inspect_edge(MDL_context *dest);
186 
get_victim() const187   MDL_context *get_victim() const { return m_victim; }
188 private:
189   /**
190     Change the deadlock victim to a new one if it has lower deadlock
191     weight.
192   */
193   void opt_change_victim_to(MDL_context *new_victim);
194 private:
195   /**
196     The context which has initiated the search. There
197     can be multiple searches happening in parallel at the same time.
198   */
199   MDL_context *m_start_node;
200   /** If a deadlock is found, the context that identifies the victim. */
201   MDL_context *m_victim;
202   /** Set to the 0 at start. Increased whenever
203     we descend into another MDL context (aka traverse to the next
204     wait-for graph node). When MAX_SEARCH_DEPTH is reached, we
205     assume that a deadlock is found, even if we have not found a
206     loop.
207   */
208   uint m_current_search_depth;
209   /** TRUE if we found a deadlock. */
210   bool m_found_deadlock;
211   /**
212     Maximum depth for deadlock searches. After this depth is
213     achieved we will unconditionally declare that there is a
214     deadlock.
215 
216     @note This depth should be small enough to avoid stack
217           being exhausted by recursive search algorithm.
218 
219     TODO: Find out what is the optimal value for this parameter.
220           Current value is safe, but probably sub-optimal,
221           as there is an anecdotal evidence that real-life
222           deadlocks are even shorter typically.
223   */
224   static const uint MAX_SEARCH_DEPTH= 32;
225 };
226 
227 #ifndef DBUG_OFF
228 
229 /*
230   Print a list of all locks to DBUG trace to help with debugging
231 */
232 
mdl_dbug_print_lock(MDL_ticket * mdl_ticket,void * arg,bool granted)233 static int mdl_dbug_print_lock(MDL_ticket *mdl_ticket, void *arg, bool granted)
234 {
235   String *tmp= (String*) arg;
236   char buffer[128];
237   MDL_key *mdl_key= mdl_ticket->get_key();
238   size_t length;
239   length= my_snprintf(buffer, sizeof(buffer)-1,
240                       "\nname: %s  db: %.*s  key_name: %.*s (%s)",
241                       mdl_ticket->get_type_name()->str,
242                       (int) mdl_key->db_name_length(), mdl_key->db_name(),
243                       (int) mdl_key->name_length(),    mdl_key->name(),
244                       granted ? "granted" : "waiting");
245   tmp->append(buffer, length);
246   return 0;
247 }
248 
mdl_dbug_print_locks()249 const char *mdl_dbug_print_locks()
250 {
251   static String tmp;
252   mdl_iterate(mdl_dbug_print_lock, (void*) &tmp);
253   return tmp.c_ptr();
254 }
255 #endif /* DBUG_OFF */
256 
257 /**
258   Enter a node of a wait-for graph. After
259   a node is entered, inspect_edge() will be called
260   for all wait-for destinations of this node. Then
261   leave_node() will be called.
262   We call "enter_node()" for all nodes we inspect,
263   including the starting node.
264 
265   @retval  TRUE  Maximum search depth exceeded.
266   @retval  FALSE OK.
267 */
268 
enter_node(MDL_context * node)269 bool Deadlock_detection_visitor::enter_node(MDL_context *node)
270 {
271   m_found_deadlock= ++m_current_search_depth >= MAX_SEARCH_DEPTH;
272   if (m_found_deadlock)
273   {
274     DBUG_ASSERT(! m_victim);
275     opt_change_victim_to(node);
276   }
277   return m_found_deadlock;
278 }
279 
280 
281 /**
282   Done inspecting this node. Decrease the search
283   depth. If a deadlock is found, and we are
284   backtracking to the start node, optionally
285   change the deadlock victim to one with lower
286   deadlock weight.
287 */
288 
leave_node(MDL_context * node)289 void Deadlock_detection_visitor::leave_node(MDL_context *node)
290 {
291   --m_current_search_depth;
292   if (m_found_deadlock)
293     opt_change_victim_to(node);
294 }
295 
296 
297 /**
298   Inspect a wait-for graph edge from one MDL context to another.
299 
300   @retval TRUE   A loop is found.
301   @retval FALSE  No loop is found.
302 */
303 
inspect_edge(MDL_context * node)304 bool Deadlock_detection_visitor::inspect_edge(MDL_context *node)
305 {
306   m_found_deadlock= node == m_start_node;
307   return m_found_deadlock;
308 }
309 
310 
311 /**
312   Change the deadlock victim to a new one if it has lower deadlock
313   weight.
314 
315   @retval new_victim  Victim is not changed.
316   @retval !new_victim New victim became the current.
317 */
318 
319 void
opt_change_victim_to(MDL_context * new_victim)320 Deadlock_detection_visitor::opt_change_victim_to(MDL_context *new_victim)
321 {
322   if (m_victim == NULL ||
323       m_victim->get_deadlock_weight() >= new_victim->get_deadlock_weight())
324   {
325     /* Swap victims, unlock the old one. */
326     MDL_context *tmp= m_victim;
327     m_victim= new_victim;
328     m_victim->lock_deadlock_victim();
329     if (tmp)
330       tmp->unlock_deadlock_victim();
331   }
332 }
333 
334 
335 /**
336   Get a bit corresponding to enum_mdl_type value in a granted/waiting bitmaps
337   and compatibility matrices.
338 */
339 
340 /**
341   The lock context. Created internally for an acquired lock.
342   For a given name, there exists only one MDL_lock instance,
343   and it exists only when the lock has been granted.
344   Can be seen as an MDL subsystem's version of TABLE_SHARE.
345 
346   This is an abstract class which lacks information about
347   compatibility rules for lock types. They should be specified
348   in its descendants.
349 */
350 
351 class MDL_lock
352 {
353 public:
354   typedef mdl_bitmap_t bitmap_t;
355 
356   class Ticket_list
357   {
358   public:
359     typedef I_P_List<MDL_ticket,
360                      I_P_List_adapter<MDL_ticket,
361                                       &MDL_ticket::next_in_lock,
362                                       &MDL_ticket::prev_in_lock>,
363                      I_P_List_null_counter,
364                      I_P_List_fast_push_back<MDL_ticket> >
365             List;
operator const List&() const366     operator const List &() const { return m_list; }
Ticket_list()367     Ticket_list() :m_bitmap(0) {}
368 
369     void add_ticket(MDL_ticket *ticket);
370     void remove_ticket(MDL_ticket *ticket);
is_empty() const371     bool is_empty() const { return m_list.is_empty(); }
bitmap() const372     bitmap_t bitmap() const { return m_bitmap; }
373   private:
374     void clear_bit_if_not_in_list(enum_mdl_type type);
375   private:
376     /** List of tickets. */
377     List m_list;
378     /** Bitmap of types of tickets in this list. */
379     bitmap_t m_bitmap;
380   };
381 
382   typedef Ticket_list::List::Iterator Ticket_iterator;
383 
384 
385   /**
386     Helper struct which defines how different types of locks are handled
387     for a specific MDL_lock. In practice we use only three strategies:
388     "backup" lock strategy for locks in BACKUP namespace, "scoped" lock
389     strategy for locks in SCHEMA namespace and "object" lock strategy for
390     all other namespaces.
391   */
392   struct MDL_lock_strategy
393   {
394     virtual const bitmap_t *incompatible_granted_types_bitmap() const = 0;
395     virtual const bitmap_t *incompatible_waiting_types_bitmap() const = 0;
396     virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
397     virtual bool conflicting_locks(const MDL_ticket *ticket) const = 0;
398     virtual bitmap_t hog_lock_types_bitmap() const = 0;
~MDL_lock_strategyMDL_lock::MDL_lock_strategy399     virtual ~MDL_lock_strategy() {}
400   };
401 
402 
403   /**
404     An implementation of the scoped metadata lock. The only locking modes
405     which are supported at the moment are SHARED and INTENTION EXCLUSIVE
406     and EXCLUSIVE
407   */
408   struct MDL_scoped_lock : public MDL_lock_strategy
409   {
MDL_scoped_lockMDL_lock::MDL_scoped_lock410     MDL_scoped_lock() {}
incompatible_granted_types_bitmapMDL_lock::MDL_scoped_lock411     virtual const bitmap_t *incompatible_granted_types_bitmap() const
412     { return m_granted_incompatible; }
incompatible_waiting_types_bitmapMDL_lock::MDL_scoped_lock413     virtual const bitmap_t *incompatible_waiting_types_bitmap() const
414     { return m_waiting_incompatible; }
needs_notificationMDL_lock::MDL_scoped_lock415     virtual bool needs_notification(const MDL_ticket *ticket) const
416     { return (ticket->get_type() == MDL_SHARED); }
417 
418     /**
419       Notify threads holding scoped IX locks which conflict with a pending
420       S lock.
421 
422       Thread which holds global IX lock can be a handler thread for
423       insert delayed. We need to kill such threads in order to get
424       global shared lock. We do this my calling code outside of MDL.
425     */
conflicting_locksMDL_lock::MDL_scoped_lock426     virtual bool conflicting_locks(const MDL_ticket *ticket) const
427     { return ticket->get_type() == MDL_INTENTION_EXCLUSIVE; }
428 
429     /*
430       In scoped locks, only IX lock request would starve because of X/S. But that
431       is practically very rare case. So just return 0 from this function.
432     */
hog_lock_types_bitmapMDL_lock::MDL_scoped_lock433     virtual bitmap_t hog_lock_types_bitmap() const
434     { return 0; }
435   private:
436     static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
437     static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
438   };
439 
440 
441   /**
442     An implementation of a per-object lock. Supports SHARED, SHARED_UPGRADABLE,
443     SHARED HIGH PRIORITY and EXCLUSIVE locks.
444   */
445   struct MDL_object_lock : public MDL_lock_strategy
446   {
MDL_object_lockMDL_lock::MDL_object_lock447     MDL_object_lock() {}
incompatible_granted_types_bitmapMDL_lock::MDL_object_lock448     virtual const bitmap_t *incompatible_granted_types_bitmap() const
449     { return m_granted_incompatible; }
incompatible_waiting_types_bitmapMDL_lock::MDL_object_lock450     virtual const bitmap_t *incompatible_waiting_types_bitmap() const
451     { return m_waiting_incompatible; }
needs_notificationMDL_lock::MDL_object_lock452     virtual bool needs_notification(const MDL_ticket *ticket) const
453     {
454       return (MDL_BIT(ticket->get_type()) &
455               (MDL_BIT(MDL_SHARED_NO_WRITE) |
456                MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
457                MDL_BIT(MDL_EXCLUSIVE)));
458     }
459 
460     /**
461       Notify threads holding a shared metadata locks on object which
462       conflict with a pending X, SNW or SNRW lock.
463 
464       If thread which holds conflicting lock is waiting on table-level
465       lock or some other non-MDL resource we might need to wake it up
466       by calling code outside of MDL.
467     */
conflicting_locksMDL_lock::MDL_object_lock468     virtual bool conflicting_locks(const MDL_ticket *ticket) const
469     { return ticket->get_type() < MDL_SHARED_UPGRADABLE; }
470 
471     /*
472       To prevent starvation, these lock types that are only granted
473       max_write_lock_count times in a row while other lock types are
474       waiting.
475     */
hog_lock_types_bitmapMDL_lock::MDL_object_lock476     virtual bitmap_t hog_lock_types_bitmap() const
477     {
478       return (MDL_BIT(MDL_SHARED_NO_WRITE) |
479               MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
480               MDL_BIT(MDL_EXCLUSIVE));
481     }
482 
483   private:
484     static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
485     static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
486   };
487 
488 
489   struct MDL_backup_lock: public MDL_lock_strategy
490   {
MDL_backup_lockMDL_lock::MDL_backup_lock491     MDL_backup_lock() {}
incompatible_granted_types_bitmapMDL_lock::MDL_backup_lock492     virtual const bitmap_t *incompatible_granted_types_bitmap() const
493     { return m_granted_incompatible; }
incompatible_waiting_types_bitmapMDL_lock::MDL_backup_lock494     virtual const bitmap_t *incompatible_waiting_types_bitmap() const
495     { return m_waiting_incompatible; }
needs_notificationMDL_lock::MDL_backup_lock496     virtual bool needs_notification(const MDL_ticket *ticket) const
497     {
498       return (MDL_BIT(ticket->get_type()) & MDL_BIT(MDL_BACKUP_FTWRL1));
499     }
500 
501     /**
502        Insert delayed threads may hold DML or TRANS_DML lock.
503        We need to kill such threads in order to get lock for FTWRL statements.
504        We do this by calling code outside of MDL.
505     */
conflicting_locksMDL_lock::MDL_backup_lock506     virtual bool conflicting_locks(const MDL_ticket *ticket) const
507     {
508       return (MDL_BIT(ticket->get_type()) &
509               (MDL_BIT(MDL_BACKUP_DML) |
510                MDL_BIT(MDL_BACKUP_TRANS_DML)));
511     }
512 
513     /*
514       In backup namespace DML/DDL may starve because of concurrent FTWRL or
515       BACKUP statements. This scenario is partically useless in real world,
516       so we just return 0 here.
517     */
hog_lock_types_bitmapMDL_lock::MDL_backup_lock518     virtual bitmap_t hog_lock_types_bitmap() const
519     { return 0; }
520   private:
521     static const bitmap_t m_granted_incompatible[MDL_BACKUP_END];
522     static const bitmap_t m_waiting_incompatible[MDL_BACKUP_END];
523   };
524 
525 public:
526   /** The key of the object (data) being protected. */
527   MDL_key key;
528   /**
529     Read-write lock protecting this lock context.
530 
531     @note The fact that we use read-write lock prefers readers here is
532           important as deadlock detector won't work correctly otherwise.
533 
534           For example, imagine that we have following waiters graph:
535 
536                        ctxA -> obj1 -> ctxB -> obj1 -|
537                         ^                            |
538                         |----------------------------|
539 
540           and both ctxA and ctxB start deadlock detection process:
541 
542             ctxA read-locks obj1             ctxB read-locks obj2
543             ctxA goes deeper                 ctxB goes deeper
544 
545           Now ctxC comes in who wants to start waiting on obj1, also
546           ctxD comes in who wants to start waiting on obj2.
547 
548             ctxC tries to write-lock obj1   ctxD tries to write-lock obj2
549             ctxC is blocked                 ctxD is blocked
550 
551           Now ctxA and ctxB resume their search:
552 
553             ctxA tries to read-lock obj2    ctxB tries to read-lock obj1
554 
555           If m_rwlock prefers writes (or fair) both ctxA and ctxB would be
556           blocked because of pending write locks from ctxD and ctxC
557           correspondingly. Thus we will get a deadlock in deadlock detector.
558           If m_wrlock prefers readers (actually ignoring pending writers is
559           enough) ctxA and ctxB will continue and no deadlock will occur.
560   */
561   mysql_prlock_t m_rwlock;
562 
is_empty() const563   bool is_empty() const
564   {
565     return (m_granted.is_empty() && m_waiting.is_empty());
566   }
567 
incompatible_granted_types_bitmap() const568   const bitmap_t *incompatible_granted_types_bitmap() const
569   { return m_strategy->incompatible_granted_types_bitmap(); }
incompatible_waiting_types_bitmap() const570   const bitmap_t *incompatible_waiting_types_bitmap() const
571   { return m_strategy->incompatible_waiting_types_bitmap(); }
572 
573   bool has_pending_conflicting_lock(enum_mdl_type type);
574 
575   bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
576                       bool ignore_lock_priority) const;
577 
578   inline unsigned long get_lock_owner() const;
579 
580   void reschedule_waiters();
581 
582   void remove_ticket(LF_PINS *pins, Ticket_list MDL_lock::*queue,
583                      MDL_ticket *ticket);
584 
585   bool visit_subgraph(MDL_ticket *waiting_ticket,
586                       MDL_wait_for_graph_visitor *gvisitor);
587 
needs_notification(const MDL_ticket * ticket) const588   bool needs_notification(const MDL_ticket *ticket) const
589   { return m_strategy->needs_notification(ticket); }
notify_conflicting_locks(MDL_context * ctx)590   void notify_conflicting_locks(MDL_context *ctx)
591   {
592     Ticket_iterator it(m_granted);
593     MDL_ticket *conflicting_ticket;
594     while ((conflicting_ticket= it++))
595     {
596       if (conflicting_ticket->get_ctx() != ctx &&
597           m_strategy->conflicting_locks(conflicting_ticket))
598       {
599         MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
600 
601         ctx->get_owner()->
602           notify_shared_lock(conflicting_ctx->get_owner(),
603                              conflicting_ctx->get_needs_thr_lock_abort());
604       }
605     }
606   }
607 
hog_lock_types_bitmap() const608   bitmap_t hog_lock_types_bitmap() const
609   { return m_strategy->hog_lock_types_bitmap(); }
610 
611 #ifndef DBUG_OFF
612   bool check_if_conflicting_replication_locks(MDL_context *ctx);
613 #endif
614 
615   /** List of granted tickets for this lock. */
616   Ticket_list m_granted;
617   /** Tickets for contexts waiting to acquire a lock. */
618   Ticket_list m_waiting;
619 
620   /**
621     Number of times high priority lock requests have been granted while
622     low priority lock requests were waiting.
623   */
624   ulong m_hog_lock_count;
625 
626 public:
627 
MDL_lock()628   MDL_lock()
629     : m_hog_lock_count(0),
630       m_strategy(0)
631   { mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock); }
632 
MDL_lock(const MDL_key * key_arg)633   MDL_lock(const MDL_key *key_arg)
634   : key(key_arg),
635     m_hog_lock_count(0),
636     m_strategy(&m_backup_lock_strategy)
637   {
638     DBUG_ASSERT(key_arg->mdl_namespace() == MDL_key::BACKUP);
639     mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock);
640   }
641 
~MDL_lock()642   ~MDL_lock()
643   { mysql_prlock_destroy(&m_rwlock); }
644 
lf_alloc_constructor(uchar * arg)645   static void lf_alloc_constructor(uchar *arg)
646   { new (arg + LF_HASH_OVERHEAD) MDL_lock(); }
647 
lf_alloc_destructor(uchar * arg)648   static void lf_alloc_destructor(uchar *arg)
649   { ((MDL_lock*)(arg + LF_HASH_OVERHEAD))->~MDL_lock(); }
650 
lf_hash_initializer(LF_HASH * hash,MDL_lock * lock,MDL_key * key_arg)651   static void lf_hash_initializer(LF_HASH *hash __attribute__((unused)),
652                                   MDL_lock *lock, MDL_key *key_arg)
653   {
654     DBUG_ASSERT(key_arg->mdl_namespace() != MDL_key::BACKUP);
655     new (&lock->key) MDL_key(key_arg);
656     if (key_arg->mdl_namespace() == MDL_key::SCHEMA)
657       lock->m_strategy= &m_scoped_lock_strategy;
658     else
659       lock->m_strategy= &m_object_lock_strategy;
660   }
661 
662   const MDL_lock_strategy *m_strategy;
663 private:
664   static const MDL_backup_lock m_backup_lock_strategy;
665   static const MDL_scoped_lock m_scoped_lock_strategy;
666   static const MDL_object_lock m_object_lock_strategy;
667 };
668 
669 
670 const MDL_lock::MDL_backup_lock MDL_lock::m_backup_lock_strategy;
671 const MDL_lock::MDL_scoped_lock MDL_lock::m_scoped_lock_strategy;
672 const MDL_lock::MDL_object_lock MDL_lock::m_object_lock_strategy;
673 
674 
675 static MDL_map mdl_locks;
676 
677 
678 extern "C"
679 {
680 static uchar *
mdl_locks_key(const uchar * record,size_t * length,my_bool not_used)681 mdl_locks_key(const uchar *record, size_t *length,
682               my_bool not_used __attribute__((unused)))
683 {
684   MDL_lock *lock=(MDL_lock*) record;
685   *length= lock->key.length();
686   return (uchar*) lock->key.ptr();
687 }
688 } /* extern "C" */
689 
690 
691 /**
692   Initialize the metadata locking subsystem.
693 
694   This function is called at server startup.
695 
696   In particular, initializes the new global mutex and
697   the associated condition variable: LOCK_mdl and COND_mdl.
698   These locking primitives are implementation details of the MDL
699   subsystem and are private to it.
700 */
701 
mdl_init()702 void mdl_init()
703 {
704   DBUG_ASSERT(! mdl_initialized);
705   mdl_initialized= TRUE;
706 
707 #ifdef HAVE_PSI_INTERFACE
708   init_mdl_psi_keys();
709 #endif
710 
711   mdl_locks.init();
712 }
713 
714 
715 /**
716   Release resources of metadata locking subsystem.
717 
718   Destroys the global mutex and the condition variable.
719   Called at server shutdown.
720 */
721 
mdl_destroy()722 void mdl_destroy()
723 {
724   if (mdl_initialized)
725   {
726     mdl_initialized= FALSE;
727     mdl_locks.destroy();
728   }
729 }
730 
731 
732 struct mdl_iterate_arg
733 {
734   mdl_iterator_callback callback;
735   void *argument;
736 };
737 
738 
mdl_iterate_lock(MDL_lock * lock,mdl_iterate_arg * arg)739 static my_bool mdl_iterate_lock(MDL_lock *lock, mdl_iterate_arg *arg)
740 {
741   int res= FALSE;
742   /*
743     We can skip check for m_strategy here, becase m_granted
744     must be empty for such locks anyway.
745   */
746   mysql_prlock_rdlock(&lock->m_rwlock);
747   MDL_lock::Ticket_iterator granted_it(lock->m_granted);
748   MDL_lock::Ticket_iterator waiting_it(lock->m_waiting);
749   MDL_ticket *ticket;
750   while ((ticket= granted_it++) && !(res= arg->callback(ticket, arg->argument, true)))
751     /* no-op */;
752   while ((ticket= waiting_it++) && !(res= arg->callback(ticket, arg->argument, false)))
753     /* no-op */;
754   mysql_prlock_unlock(&lock->m_rwlock);
755   return MY_TEST(res);
756 }
757 
758 
mdl_iterate(mdl_iterator_callback callback,void * arg)759 int mdl_iterate(mdl_iterator_callback callback, void *arg)
760 {
761   DBUG_ENTER("mdl_iterate");
762   mdl_iterate_arg argument= { callback, arg };
763   LF_PINS *pins= mdl_locks.get_pins();
764   int res= 1;
765 
766   if (pins)
767   {
768     res= mdl_iterate_lock(mdl_locks.m_backup_lock, &argument) ||
769          lf_hash_iterate(&mdl_locks.m_locks, pins,
770                          (my_hash_walk_action) mdl_iterate_lock, &argument);
771     lf_hash_put_pins(pins);
772   }
773   DBUG_RETURN(res);
774 }
775 
776 
mdl_hash_function(CHARSET_INFO * cs,const uchar * key,size_t length)777 my_hash_value_type mdl_hash_function(CHARSET_INFO *cs,
778                                      const uchar *key, size_t length)
779 {
780   MDL_key *mdl_key= (MDL_key*) (key - offsetof(MDL_key, m_ptr));
781   return mdl_key->hash_value();
782 }
783 
784 
785 /** Initialize the container for all MDL locks. */
786 
init()787 void MDL_map::init()
788 {
789   MDL_key backup_lock_key(MDL_key::BACKUP, "", "");
790 
791   m_backup_lock= new (std::nothrow) MDL_lock(&backup_lock_key);
792 
793   lf_hash_init(&m_locks, sizeof(MDL_lock), LF_HASH_UNIQUE, 0, 0,
794                mdl_locks_key, &my_charset_bin);
795   m_locks.alloc.constructor= MDL_lock::lf_alloc_constructor;
796   m_locks.alloc.destructor= MDL_lock::lf_alloc_destructor;
797   m_locks.initializer= (lf_hash_initializer) MDL_lock::lf_hash_initializer;
798   m_locks.hash_function= mdl_hash_function;
799 }
800 
801 
802 /**
803   Destroy the container for all MDL locks.
804   @pre It must be empty.
805 */
806 
destroy()807 void MDL_map::destroy()
808 {
809   delete m_backup_lock;
810 
811   DBUG_ASSERT(!lf_hash_size(&m_locks));
812   lf_hash_destroy(&m_locks);
813 }
814 
815 
816 /**
817   Find MDL_lock object corresponding to the key, create it
818   if it does not exist.
819 
820   @retval non-NULL - Success. MDL_lock instance for the key with
821                      locked MDL_lock::m_rwlock.
822   @retval NULL     - Failure (OOM).
823 */
824 
find_or_insert(LF_PINS * pins,const MDL_key * mdl_key)825 MDL_lock* MDL_map::find_or_insert(LF_PINS *pins, const MDL_key *mdl_key)
826 {
827   MDL_lock *lock;
828 
829   if (mdl_key->mdl_namespace() == MDL_key::BACKUP)
830   {
831     /*
832       Return pointer to pre-allocated MDL_lock instance. Such an optimization
833       allows to save one hash lookup for any statement changing data.
834 
835       It works since this namespace contains only one element so keys
836       for them look like '<namespace-id>\0\0'.
837     */
838     DBUG_ASSERT(mdl_key->length() == 3);
839     mysql_prlock_wrlock(&m_backup_lock->m_rwlock);
840     return m_backup_lock;
841   }
842 
843 retry:
844   while (!(lock= (MDL_lock*) lf_hash_search(&m_locks, pins, mdl_key->ptr(),
845                                             mdl_key->length())))
846     if (lf_hash_insert(&m_locks, pins, (uchar*) mdl_key) == -1)
847       return NULL;
848 
849   mysql_prlock_wrlock(&lock->m_rwlock);
850   if (unlikely(!lock->m_strategy))
851   {
852     mysql_prlock_unlock(&lock->m_rwlock);
853     lf_hash_search_unpin(pins);
854     goto retry;
855   }
856   lf_hash_search_unpin(pins);
857 
858   return lock;
859 }
860 
861 
862 /**
863  * Return thread id of the owner of the lock, if it is owned.
864  */
865 
866 unsigned long
get_lock_owner(LF_PINS * pins,const MDL_key * mdl_key)867 MDL_map::get_lock_owner(LF_PINS *pins, const MDL_key *mdl_key)
868 {
869   unsigned long res= 0;
870 
871   if (mdl_key->mdl_namespace() == MDL_key::BACKUP)
872   {
873     mysql_prlock_rdlock(&m_backup_lock->m_rwlock);
874     res= m_backup_lock->get_lock_owner();
875     mysql_prlock_unlock(&m_backup_lock->m_rwlock);
876   }
877   else
878   {
879     MDL_lock *lock= (MDL_lock*) lf_hash_search(&m_locks, pins, mdl_key->ptr(),
880                                                mdl_key->length());
881     if (lock)
882     {
883       /*
884         We can skip check for m_strategy here, becase m_granted
885         must be empty for such locks anyway.
886       */
887       mysql_prlock_rdlock(&lock->m_rwlock);
888       res= lock->get_lock_owner();
889       mysql_prlock_unlock(&lock->m_rwlock);
890       lf_hash_search_unpin(pins);
891     }
892   }
893   return res;
894 }
895 
896 
897 /**
898   Destroy MDL_lock object or delegate this responsibility to
899   whatever thread that holds the last outstanding reference to
900   it.
901 */
902 
remove(LF_PINS * pins,MDL_lock * lock)903 void MDL_map::remove(LF_PINS *pins, MDL_lock *lock)
904 {
905   if (lock->key.mdl_namespace() == MDL_key::BACKUP)
906   {
907     /* Never destroy pre-allocated MDL_lock object in BACKUP namespace. */
908     mysql_prlock_unlock(&lock->m_rwlock);
909     return;
910   }
911 
912   lock->m_strategy= 0;
913   mysql_prlock_unlock(&lock->m_rwlock);
914   lf_hash_delete(&m_locks, pins, lock->key.ptr(), lock->key.length());
915 }
916 
917 
918 /**
919   Initialize a metadata locking context.
920 
921   This is to be called when a new server connection is created.
922 */
923 
MDL_context()924 MDL_context::MDL_context()
925   :
926   m_owner(NULL),
927   m_needs_thr_lock_abort(FALSE),
928   m_waiting_for(NULL),
929   m_pins(NULL)
930 {
931   mysql_prlock_init(key_MDL_context_LOCK_waiting_for, &m_LOCK_waiting_for);
932 }
933 
934 
935 /**
936   Destroy metadata locking context.
937 
938   Assumes and asserts that there are no active or pending locks
939   associated with this context at the time of the destruction.
940 
941   Currently does nothing. Asserts that there are no pending
942   or satisfied lock requests. The pending locks must be released
943   prior to destruction. This is a new way to express the assertion
944   that all tables are closed before a connection is destroyed.
945 */
946 
destroy()947 void MDL_context::destroy()
948 {
949   DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty());
950   DBUG_ASSERT(m_tickets[MDL_TRANSACTION].is_empty());
951   DBUG_ASSERT(m_tickets[MDL_EXPLICIT].is_empty());
952 
953   mysql_prlock_destroy(&m_LOCK_waiting_for);
954   if (m_pins)
955     lf_hash_put_pins(m_pins);
956 }
957 
958 
fix_pins()959 bool MDL_context::fix_pins()
960 {
961   return m_pins ? false : (m_pins= mdl_locks.get_pins()) == 0;
962 }
963 
964 
965 /**
966   Initialize a lock request.
967 
968   This is to be used for every lock request.
969 
970   Note that initialization and allocation are split into two
971   calls. This is to allow flexible memory management of lock
972   requests. Normally a lock request is stored in statement memory
973   (e.g. is a member of struct TABLE_LIST), but we would also like
974   to allow allocation of lock requests in other memory roots,
975   for example in the grant subsystem, to lock privilege tables.
976 
977   The MDL subsystem does not own or manage memory of lock requests.
978 
979   @param  mdl_namespace  Id of namespace of object to be locked
980   @param  db             Name of database to which the object belongs
981   @param  name           Name of of the object
982   @param  mdl_type       The MDL lock type for the request.
983 */
984 
init(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)985 void MDL_request::init(MDL_key::enum_mdl_namespace mdl_namespace,
986                        const char *db_arg,
987                        const char *name_arg,
988                        enum_mdl_type mdl_type_arg,
989                        enum_mdl_duration mdl_duration_arg)
990 {
991   key.mdl_key_init(mdl_namespace, db_arg, name_arg);
992   type= mdl_type_arg;
993   duration= mdl_duration_arg;
994   ticket= NULL;
995 }
996 
997 
998 /**
999   Initialize a lock request using pre-built MDL_key.
1000 
1001   @sa MDL_request::init(namespace, db, name, type).
1002 
1003   @param key_arg       The pre-built MDL key for the request.
1004   @param mdl_type_arg  The MDL lock type for the request.
1005 */
1006 
init(const MDL_key * key_arg,enum_mdl_type mdl_type_arg,enum_mdl_duration mdl_duration_arg)1007 void MDL_request::init(const MDL_key *key_arg,
1008                        enum_mdl_type mdl_type_arg,
1009                        enum_mdl_duration mdl_duration_arg)
1010 {
1011   key.mdl_key_init(key_arg);
1012   type= mdl_type_arg;
1013   duration= mdl_duration_arg;
1014   ticket= NULL;
1015 }
1016 
1017 
1018 /**
1019   Auxiliary functions needed for creation/destruction of MDL_ticket
1020   objects.
1021 
1022   @todo This naive implementation should be replaced with one that saves
1023         on memory allocation by reusing released objects.
1024 */
1025 
create(MDL_context * ctx_arg,enum_mdl_type type_arg,enum_mdl_duration duration_arg)1026 MDL_ticket *MDL_ticket::create(MDL_context *ctx_arg, enum_mdl_type type_arg
1027 #ifndef DBUG_OFF
1028                                , enum_mdl_duration duration_arg
1029 #endif
1030                                )
1031 {
1032   return new (std::nothrow)
1033              MDL_ticket(ctx_arg, type_arg
1034 #ifndef DBUG_OFF
1035                         , duration_arg
1036 #endif
1037                         );
1038 }
1039 
1040 
destroy(MDL_ticket * ticket)1041 void MDL_ticket::destroy(MDL_ticket *ticket)
1042 {
1043   delete ticket;
1044 }
1045 
1046 
1047 /**
1048   Return the 'weight' of this ticket for the
1049   victim selection algorithm. Requests with
1050   lower weight are preferred to requests
1051   with higher weight when choosing a victim.
1052 */
1053 
get_deadlock_weight() const1054 uint MDL_ticket::get_deadlock_weight() const
1055 {
1056   if (m_lock->key.mdl_namespace() == MDL_key::BACKUP)
1057   {
1058     if (m_type == MDL_BACKUP_FTWRL1)
1059       return DEADLOCK_WEIGHT_FTWRL1;
1060     return DEADLOCK_WEIGHT_DDL;
1061   }
1062   return m_type >= MDL_SHARED_UPGRADABLE ?
1063          DEADLOCK_WEIGHT_DDL : DEADLOCK_WEIGHT_DML;
1064 }
1065 
1066 
1067 /** Construct an empty wait slot. */
1068 
MDL_wait()1069 MDL_wait::MDL_wait()
1070   :m_wait_status(EMPTY)
1071 {
1072   mysql_mutex_init(key_MDL_wait_LOCK_wait_status, &m_LOCK_wait_status, NULL);
1073   mysql_cond_init(key_MDL_wait_COND_wait_status, &m_COND_wait_status, NULL);
1074 }
1075 
1076 
1077 /** Destroy system resources. */
1078 
~MDL_wait()1079 MDL_wait::~MDL_wait()
1080 {
1081   mysql_mutex_destroy(&m_LOCK_wait_status);
1082   mysql_cond_destroy(&m_COND_wait_status);
1083 }
1084 
1085 
1086 /**
1087   Set the status unless it's already set. Return FALSE if set,
1088   TRUE otherwise.
1089 */
1090 
set_status(enum_wait_status status_arg)1091 bool MDL_wait::set_status(enum_wait_status status_arg)
1092 {
1093   bool was_occupied= TRUE;
1094   mysql_mutex_lock(&m_LOCK_wait_status);
1095   if (m_wait_status == EMPTY)
1096   {
1097     was_occupied= FALSE;
1098     m_wait_status= status_arg;
1099     mysql_cond_signal(&m_COND_wait_status);
1100   }
1101   mysql_mutex_unlock(&m_LOCK_wait_status);
1102   return was_occupied;
1103 }
1104 
1105 
1106 /** Query the current value of the wait slot. */
1107 
get_status()1108 MDL_wait::enum_wait_status MDL_wait::get_status()
1109 {
1110   enum_wait_status result;
1111   mysql_mutex_lock(&m_LOCK_wait_status);
1112   result= m_wait_status;
1113   mysql_mutex_unlock(&m_LOCK_wait_status);
1114   return result;
1115 }
1116 
1117 
1118 /** Clear the current value of the wait slot. */
1119 
reset_status()1120 void MDL_wait::reset_status()
1121 {
1122   mysql_mutex_lock(&m_LOCK_wait_status);
1123   m_wait_status= EMPTY;
1124   mysql_mutex_unlock(&m_LOCK_wait_status);
1125 }
1126 
1127 
1128 /**
1129   Wait for the status to be assigned to this wait slot.
1130 
1131   @param owner           MDL context owner.
1132   @param abs_timeout     Absolute time after which waiting should stop.
1133   @param set_status_on_timeout TRUE  - If in case of timeout waiting
1134                                        context should close the wait slot by
1135                                        sending TIMEOUT to itself.
1136                                FALSE - Otherwise.
1137   @param wait_state_name  Thread state name to be set for duration of wait.
1138 
1139   @returns Signal posted.
1140 */
1141 
1142 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)1143 MDL_wait::timed_wait(MDL_context_owner *owner, struct timespec *abs_timeout,
1144                      bool set_status_on_timeout,
1145                      const PSI_stage_info *wait_state_name)
1146 {
1147   PSI_stage_info old_stage;
1148   enum_wait_status result;
1149   int wait_result= 0;
1150   DBUG_ENTER("MDL_wait::timed_wait");
1151 
1152   mysql_mutex_lock(&m_LOCK_wait_status);
1153 
1154   owner->ENTER_COND(&m_COND_wait_status, &m_LOCK_wait_status,
1155                     wait_state_name, & old_stage);
1156   thd_wait_begin(NULL, THD_WAIT_META_DATA_LOCK);
1157   while (!m_wait_status && !owner->is_killed() &&
1158          wait_result != ETIMEDOUT && wait_result != ETIME)
1159   {
1160 #ifdef WITH_WSREP
1161     // Allow tests to block the applier thread using the DBUG facilities
1162     DBUG_EXECUTE_IF("sync.wsrep_before_mdl_wait",
1163                  {
1164                    const char act[]=
1165                      "now "
1166                      "wait_for signal.wsrep_before_mdl_wait";
1167                    DBUG_ASSERT(!debug_sync_set_action((owner->get_thd()),
1168                                                       STRING_WITH_LEN(act)));
1169                  };);
1170     if (WSREP_ON && wsrep_thd_is_BF(owner->get_thd(), false))
1171     {
1172       wait_result= mysql_cond_wait(&m_COND_wait_status, &m_LOCK_wait_status);
1173     }
1174     else
1175 #endif /* WITH_WSREP */
1176     wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status,
1177                                       abs_timeout);
1178   }
1179   thd_wait_end(NULL);
1180 
1181   if (m_wait_status == EMPTY)
1182   {
1183     /*
1184       Wait has ended not due to a status being set from another
1185       thread but due to this connection/statement being killed or a
1186       time out.
1187       To avoid races, which may occur if another thread sets
1188       GRANTED status before the code which calls this method
1189       processes the abort/timeout, we assign the status under
1190       protection of the m_LOCK_wait_status, within the critical
1191       section. An exception is when set_status_on_timeout is
1192       false, which means that the caller intends to restart the
1193       wait.
1194     */
1195     if (owner->is_killed())
1196       m_wait_status= KILLED;
1197     else if (set_status_on_timeout)
1198       m_wait_status= TIMEOUT;
1199   }
1200   result= m_wait_status;
1201 
1202   owner->EXIT_COND(& old_stage);
1203 
1204   DBUG_RETURN(result);
1205 }
1206 
1207 
1208 /**
1209   Clear bit corresponding to the type of metadata lock in bitmap representing
1210   set of such types if list of tickets does not contain ticket with such type.
1211 
1212   @param[in,out]  bitmap  Bitmap representing set of types of locks.
1213   @param[in]      list    List to inspect.
1214   @param[in]      type    Type of metadata lock to look up in the list.
1215 */
1216 
clear_bit_if_not_in_list(enum_mdl_type type)1217 void MDL_lock::Ticket_list::clear_bit_if_not_in_list(enum_mdl_type type)
1218 {
1219   MDL_lock::Ticket_iterator it(m_list);
1220   const MDL_ticket *ticket;
1221 
1222   while ((ticket= it++))
1223     if (ticket->get_type() == type)
1224       return;
1225   m_bitmap&= ~ MDL_BIT(type);
1226 }
1227 
1228 
1229 /**
1230   Add ticket to MDL_lock's list of waiting requests and
1231   update corresponding bitmap of lock types.
1232 */
1233 
add_ticket(MDL_ticket * ticket)1234 void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
1235 {
1236   /*
1237     Ticket being added to the list must have MDL_ticket::m_lock set,
1238     since for such tickets methods accessing this member might be
1239     called by other threads.
1240   */
1241   DBUG_ASSERT(ticket->get_lock());
1242 #ifdef WITH_WSREP
1243   if (WSREP_ON && (this == &(ticket->get_lock()->m_waiting)) &&
1244       wsrep_thd_is_BF(ticket->get_ctx()->get_thd(), false))
1245   {
1246     Ticket_iterator itw(ticket->get_lock()->m_waiting);
1247     MDL_ticket *waiting;
1248     MDL_ticket *prev=NULL;
1249     bool added= false;
1250 
1251     DBUG_ASSERT(WSREP(ticket->get_ctx()->get_thd()));
1252 
1253     while ((waiting= itw++) && !added)
1254     {
1255       if (!wsrep_thd_is_BF(waiting->get_ctx()->get_thd(), true))
1256       {
1257         WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
1258                     thd_get_thread_id(waiting->get_ctx()->get_thd()),
1259                     wsrep_thd_query(waiting->get_ctx()->get_thd()));
1260         /* Insert the ticket before the first non-BF waiting thd. */
1261         m_list.insert_after(prev, ticket);
1262         added= true;
1263       }
1264       prev= waiting;
1265     }
1266 
1267     /* Otherwise, insert the ticket at the back of the waiting list. */
1268     if (!added)
1269       m_list.push_back(ticket);
1270   }
1271   else
1272 #endif /* WITH_WSREP */
1273   {
1274     /*
1275       Add ticket to the *back* of the queue to ensure fairness
1276       among requests with the same priority.
1277     */
1278     m_list.push_back(ticket);
1279   }
1280   m_bitmap|= MDL_BIT(ticket->get_type());
1281 }
1282 
1283 
1284 /**
1285   Remove ticket from MDL_lock's list of requests and
1286   update corresponding bitmap of lock types.
1287 */
1288 
remove_ticket(MDL_ticket * ticket)1289 void MDL_lock::Ticket_list::remove_ticket(MDL_ticket *ticket)
1290 {
1291   m_list.remove(ticket);
1292   /*
1293     Check if waiting queue has another ticket with the same type as
1294     one which was removed. If there is no such ticket, i.e. we have
1295     removed last ticket of particular type, then we need to update
1296     bitmap of waiting ticket's types.
1297     Note that in most common case, i.e. when shared lock is removed
1298     from waiting queue, we are likely to find ticket of the same
1299     type early without performing full iteration through the list.
1300     So this method should not be too expensive.
1301   */
1302   clear_bit_if_not_in_list(ticket->get_type());
1303 }
1304 
1305 
1306 /**
1307   Determine waiting contexts which requests for the lock can be
1308   satisfied, grant lock to them and wake them up.
1309 
1310   @note Together with MDL_lock::add_ticket() this method implements
1311         fair scheduling among requests with the same priority.
1312         It tries to grant lock from the head of waiters list, while
1313         add_ticket() adds new requests to the back of this list.
1314 
1315 */
1316 
reschedule_waiters()1317 void MDL_lock::reschedule_waiters()
1318 {
1319   MDL_lock::Ticket_iterator it(m_waiting);
1320   MDL_ticket *ticket;
1321   bool skip_high_priority= false;
1322   bitmap_t hog_lock_types= hog_lock_types_bitmap();
1323 
1324   if (m_hog_lock_count >= max_write_lock_count)
1325   {
1326     /*
1327       If number of successively granted high-prio, strong locks has exceeded
1328       max_write_lock_count give a way to low-prio, weak locks to avoid their
1329       starvation.
1330     */
1331 
1332     if ((m_waiting.bitmap() & ~hog_lock_types) != 0)
1333     {
1334       /*
1335         Even though normally when m_hog_lock_count is non-0 there is
1336         some pending low-prio lock, we still can encounter situation
1337         when m_hog_lock_count is non-0 and there are no pending low-prio
1338         locks. This, for example, can happen when a ticket for pending
1339         low-prio lock was removed from waiters list due to timeout,
1340         and reschedule_waiters() is called after that to update the
1341         waiters queue. m_hog_lock_count will be reset to 0 at the
1342         end of this call in such case.
1343 
1344         Note that it is not an issue if we fail to wake up any pending
1345         waiters for weak locks in the loop below. This would mean that
1346         all of them are either killed, timed out or chosen as a victim
1347         by deadlock resolver, but have not managed to remove ticket
1348         from the waiters list yet. After tickets will be removed from
1349         the waiters queue there will be another call to
1350         reschedule_waiters() with pending bitmap updated to reflect new
1351         state of waiters queue.
1352       */
1353       skip_high_priority= true;
1354     }
1355   }
1356 
1357   /*
1358     Find the first (and hence the oldest) waiting request which
1359     can be satisfied (taking into account priority). Grant lock to it.
1360     Repeat the process for the remainder of waiters.
1361     Note we don't need to re-start iteration from the head of the
1362     list after satisfying the first suitable request as in our case
1363     all compatible types of requests have the same priority.
1364 
1365     TODO/FIXME: We should:
1366                 - Either switch to scheduling without priorities
1367                   which will allow to stop iteration through the
1368                   list of waiters once we found the first ticket
1369                   which can't be  satisfied
1370                 - Or implement some check using bitmaps which will
1371                   allow to stop iteration in cases when, e.g., we
1372                   grant SNRW lock and there are no pending S or
1373                   SH locks.
1374   */
1375   while ((ticket= it++))
1376   {
1377     /*
1378       Skip high-prio, strong locks if earlier we have decided to give way to
1379       low-prio, weaker locks.
1380     */
1381     if (skip_high_priority &&
1382         ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0))
1383       continue;
1384 
1385     if (can_grant_lock(ticket->get_type(), ticket->get_ctx(),
1386                        skip_high_priority))
1387     {
1388       if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))
1389       {
1390         /*
1391           Satisfy the found request by updating lock structures.
1392           It is OK to do so even after waking up the waiter since any
1393           session which tries to get any information about the state of
1394           this lock has to acquire MDL_lock::m_rwlock first and thus,
1395           when manages to do so, already sees an updated state of the
1396           MDL_lock object.
1397         */
1398         m_waiting.remove_ticket(ticket);
1399         m_granted.add_ticket(ticket);
1400 
1401         /*
1402           Increase counter of successively granted high-priority strong locks,
1403           if we have granted one.
1404         */
1405         if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)
1406           m_hog_lock_count++;
1407       }
1408       /*
1409         If we could not update the wait slot of the waiter,
1410         it can be due to fact that its connection/statement was
1411         killed or it has timed out (i.e. the slot is not empty).
1412         Since in all such cases the waiter assumes that the lock was
1413         not been granted, we should keep the request in the waiting
1414         queue and look for another request to reschedule.
1415       */
1416     }
1417   }
1418 
1419   if ((m_waiting.bitmap() & ~hog_lock_types) == 0)
1420   {
1421     /*
1422       Reset number of successively granted high-prio, strong locks
1423       if there are no pending low-prio, weak locks.
1424       This ensures:
1425       - That m_hog_lock_count is correctly reset after strong lock
1426       is released and weak locks are granted (or there are no
1427       other lock requests).
1428       - That situation when SNW lock is granted along with some SR
1429       locks, but SW locks are still blocked are handled correctly.
1430       - That m_hog_lock_count is zero in most cases when there are no pending
1431       weak locks (see comment at the start of this method for example of
1432       exception). This allows to save on checks at the start of this method.
1433     */
1434     m_hog_lock_count= 0;
1435   }
1436 }
1437 
1438 
1439 /**
1440   Compatibility (or rather "incompatibility") matrices for scoped metadata
1441   lock.
1442   Scoped locks are database (or schema) locks.
1443   Arrays of bitmaps which elements specify which granted/waiting locks
1444   are incompatible with type of lock being requested.
1445 
1446   The first array specifies if particular type of request can be satisfied
1447   if there is granted scoped lock of certain type.
1448 
1449   (*)  Since intention shared scoped locks (IS) are compatible with all other
1450        type of locks, they don't need to be implemented and there is no code
1451        for them.
1452 
1453              | Type of active   |
1454      Request |   scoped lock    |
1455       type   | IS(*)  IX   S  X |
1456     ---------+------------------+
1457     IS(*)    |  +      +   +  + |
1458     IX       |  +      +   -  - |
1459     S        |  +      -   +  - |
1460     X        |  +      -   -  - |
1461 
1462   The second array specifies if particular type of request can be satisfied
1463   if there is already waiting request for the scoped lock of certain type.
1464   I.e. it specifies what is the priority of different lock types.
1465 
1466              |    Pending      |
1467      Request |  scoped lock    |
1468       type   | IS(*)  IX  S  X |
1469     ---------+-----------------+
1470     IS(*)    |  +      +  +  + |
1471     IX       |  +      +  -  - |
1472     S        |  +      +  +  - |
1473     X        |  +      +  +  + |
1474 
1475   Here: "+" -- means that request can be satisfied
1476         "-" -- means that request can't be satisfied and should wait
1477 
1478   Note that relation between scoped locks and objects locks requested
1479   by statement is not straightforward and is therefore fully defined
1480   by SQL-layer.
1481   For example, in order to support global read lock implementation
1482   SQL-layer acquires IX lock in GLOBAL namespace for each statement
1483   that can modify metadata or data (i.e. for each statement that
1484   needs SW, SU, SNW, SNRW or X object locks). OTOH, to ensure that
1485   DROP DATABASE works correctly with concurrent DDL, IX metadata locks
1486   in SCHEMA namespace are acquired for DDL statements which can update
1487   metadata in the schema (i.e. which acquire SU, SNW, SNRW and X locks
1488   on schema objects) and aren't acquired for DML.
1489 */
1490 
1491 const MDL_lock::bitmap_t
1492 MDL_lock::MDL_scoped_lock::m_granted_incompatible[MDL_TYPE_END]=
1493 {
1494   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
1495   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_INTENTION_EXCLUSIVE),
1496   0, 0, 0, 0, 0, 0, 0,
1497   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED) | MDL_BIT(MDL_INTENTION_EXCLUSIVE)
1498 };
1499 
1500 const MDL_lock::bitmap_t
1501 MDL_lock::MDL_scoped_lock::m_waiting_incompatible[MDL_TYPE_END]=
1502 {
1503   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED),
1504   MDL_BIT(MDL_EXCLUSIVE), 0, 0, 0, 0, 0, 0, 0, 0
1505 };
1506 
1507 
1508 /**
1509   Compatibility (or rather "incompatibility") matrices for per-object
1510   metadata lock. Arrays of bitmaps which elements specify which granted/
1511   waiting locks are incompatible with type of lock being requested.
1512 
1513   The first array specifies if particular type of request can be satisfied
1514   if there is granted lock of certain type.
1515 
1516      Request  |  Granted requests for lock         |
1517       type    | S  SH  SR  SW  SU  SRO SNW SNRW X  |
1518     ----------+------------------------------------+
1519     S         | +   +   +   +   +   +   +   +   -  |
1520     SH        | +   +   +   +   +   +   +   +   -  |
1521     SR        | +   +   +   +   +   +   +   -   -  |
1522     SW        | +   +   +   +   +   -   -   -   -  |
1523     SU        | +   +   +   +   -   +   -   -   -  |
1524     SRO       | +   +   +   -   +   +   +   -   -  |
1525     SNW       | +   +   +   -   -   +   -   -   -  |
1526     SNRW      | +   +   -   -   -   -   -   -   -  |
1527     X         | -   -   -   -   -   -   -   -   -  |
1528     SU -> X   | -   -   -   -   0   -   0   0   0  |
1529     SNW -> X  | -   -   -   0   0   -   0   0   0  |
1530     SNRW -> X | -   -   0   0   0   0   0   0   0  |
1531 
1532   The second array specifies if particular type of request can be satisfied
1533   if there is waiting request for the same lock of certain type. In other
1534   words it specifies what is the priority of different lock types.
1535 
1536      Request  |  Pending requests for lock        |
1537       type    | S  SH  SR  SW  SU  SRO SNW SNRW X |
1538     ----------+-----------------------------------+
1539     S         | +   +   +   +   +   +   +   +   - |
1540     SH        | +   +   +   +   +   +   +   +   + |
1541     SR        | +   +   +   +   +   +   +   -   - |
1542     SW        | +   +   +   +   +   +   -   -   - |
1543     SU        | +   +   +   +   +   +   +   +   - |
1544     SRO       | +   +   +   -   +   +   +   -   - |
1545     SNW       | +   +   +   +   +   +   +   +   - |
1546     SNRW      | +   +   +   +   +   +   +   +   - |
1547     X         | +   +   +   +   +   +   +   +   + |
1548     SU -> X   | +   +   +   +   +   +   +   +   + |
1549     SNW -> X  | +   +   +   +   +   +   +   +   + |
1550     SNRW -> X | +   +   +   +   +   +   +   +   + |
1551 
1552   Here: "+" -- means that request can be satisfied
1553         "-" -- means that request can't be satisfied and should wait
1554         "0" -- means impossible situation which will trigger assert
1555 
1556   @note In cases then current context already has "stronger" type
1557         of lock on the object it will be automatically granted
1558         thanks to usage of the MDL_context::find_ticket() method.
1559 
1560   @note IX locks are excluded since they are not used for per-object
1561         metadata locks.
1562 */
1563 
1564 const MDL_lock::bitmap_t
1565 MDL_lock::MDL_object_lock::m_granted_incompatible[MDL_TYPE_END]=
1566 {
1567   0,
1568   MDL_BIT(MDL_EXCLUSIVE),
1569   MDL_BIT(MDL_EXCLUSIVE),
1570   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
1571   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1572     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY),
1573   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1574     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE),
1575   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1576     MDL_BIT(MDL_SHARED_WRITE),
1577   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1578     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_UPGRADABLE) |
1579     MDL_BIT(MDL_SHARED_WRITE),
1580   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1581     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
1582     MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_WRITE) |
1583     MDL_BIT(MDL_SHARED_READ),
1584   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1585     MDL_BIT(MDL_SHARED_NO_WRITE) | MDL_BIT(MDL_SHARED_READ_ONLY) |
1586     MDL_BIT(MDL_SHARED_UPGRADABLE) | MDL_BIT(MDL_SHARED_WRITE) |
1587     MDL_BIT(MDL_SHARED_READ) | MDL_BIT(MDL_SHARED_HIGH_PRIO) |
1588     MDL_BIT(MDL_SHARED)
1589 };
1590 
1591 
1592 const MDL_lock::bitmap_t
1593 MDL_lock::MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END]=
1594 {
1595   0,
1596   MDL_BIT(MDL_EXCLUSIVE),
1597   0,
1598   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE),
1599   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1600     MDL_BIT(MDL_SHARED_NO_WRITE),
1601   MDL_BIT(MDL_EXCLUSIVE),
1602   MDL_BIT(MDL_EXCLUSIVE) | MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
1603     MDL_BIT(MDL_SHARED_WRITE),
1604   MDL_BIT(MDL_EXCLUSIVE),
1605   MDL_BIT(MDL_EXCLUSIVE),
1606   0
1607 };
1608 
1609 
1610 /**
1611   Compatibility (or rather "incompatibility") matrices for backup metadata
1612   lock. Arrays of bitmaps which elements specify which granted/waiting locks
1613   are incompatible with type of lock being requested.
1614 
1615   The first array specifies if particular type of request can be satisfied
1616   if there is granted backup lock of certain type.
1617 
1618      Request  |           Type of active backup lock                    |
1619       type    | S0  S1  S2  S3  S4  F1  F2   D  TD  SD   DD  BL  AC  C  |
1620     ----------+---------------------------------------------------------+
1621     S0        |  -   -   -   -   -   +   +   +   +   +   +   +   +   +  |
1622     S1        |  -   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1623     S2        |  -   +   +   +   +   +   +   -   +   +   +   +   +   +  |
1624     S3        |  -   +   +   +   +   +   +   -   +   +   -   +   +   +  |
1625     S4        |  -   +   +   +   +   +   +   -   +   -   -   +   +   -  |
1626     FTWRL1    |  +   +   +   +   +   +   +   -   -   -   -   +   -   +  |
1627     FTWRL2    |  +   +   +   +   +   +   +   -   -   -   -   +   -   -  |
1628     D         |  +   -   -   -   -   -   -   +   +   +   +   +   +   +  |
1629     TD        |  +   +   +   +   +   -   -   +   +   +   +   +   +   +  |
1630     SD        |  +   +   +   +   -   -   -   +   +   +   +   +   +   +  |
1631     DDL       |  +   +   +   -   -   -   -   +   +   +   +   -   +   +  |
1632     BLOCK_DDL |  +   +   +   +   +   +   +   +   +   +   -   +   +   +  |
1633     ALTER_COP |  +   +   +   +   +   -   -   +   +   +   +   +   +   +  |
1634     COMMIT    |  +   +   +   +   -   +   -   +   +   +   +   +   +   +  |
1635 
1636   The second array specifies if particular type of request can be satisfied
1637   if there is already waiting request for the backup lock of certain type.
1638   I.e. it specifies what is the priority of different lock types.
1639 
1640      Request  |               Pending backup lock                       |
1641       type    | S0  S1  S2  S3  S4  F1  F2   D  TD  SD   DD  BL  AC  C  |
1642     ----------+---------------------------------------------------------+
1643     S0        |  +   -   -   -   -   +   +   +   +   +   +   +   +   +  |
1644     S1        |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1645     S2        |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1646     S3        |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1647     S4        |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1648     FTWRL1    |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1649     FTWRL2    |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1650     D         |  +   -   -   -   -   -   -   +   +   +   +   +   +   +  |
1651     TD        |  +   +   +   +   +   -   -   +   +   +   +   +   +   +  |
1652     SD        |  +   +   +   +   -   -   -   +   +   +   +   +   +   +  |
1653     DDL       |  +   +   +   -   -   -   -   +   +   +   +   -   +   +  |
1654     BLOCK_DDL |  +   +   +   +   +   +   +   +   +   +   +   +   +   +  |
1655     ALTER_COP |  +   +   +   +   +   -   -   +   +   +   +   +   +   +  |
1656     COMMIT    |  +   +   +   +   -   +   -   +   +   +   +   +   +   +  |
1657 
1658   Here: "+" -- means that request can be satisfied
1659         "-" -- means that request can't be satisfied and should wait
1660 */
1661 
1662 /*
1663   NOTE: If you add a new MDL_BACKUP_XXX level lock, you have to also add it
1664   to MDL_BACKUP_START in the two arrays below!
1665 */
1666 
1667 const MDL_lock::bitmap_t
1668 MDL_lock::MDL_backup_lock::m_granted_incompatible[MDL_BACKUP_END]=
1669 {
1670   /* MDL_BACKUP_START */
1671   MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT),
1672   MDL_BIT(MDL_BACKUP_START),
1673   MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML),
1674   MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_DDL),
1675   MDL_BIT(MDL_BACKUP_START) | MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_COMMIT),
1676 
1677   /* MDL_BACKUP_FTWRL1 */
1678   MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_TRANS_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_ALTER_COPY),
1679   MDL_BIT(MDL_BACKUP_DML) | MDL_BIT(MDL_BACKUP_TRANS_DML) | MDL_BIT(MDL_BACKUP_SYS_DML) | MDL_BIT(MDL_BACKUP_DDL) | MDL_BIT(MDL_BACKUP_ALTER_COPY) | MDL_BIT(MDL_BACKUP_COMMIT),
1680   /* MDL_BACKUP_DML */
1681   MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1682   MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1683   MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1684   /* MDL_BACKUP_DDL */
1685   MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
1686   /* MDL_BACKUP_BLOCK_DDL */
1687   MDL_BIT(MDL_BACKUP_DDL),
1688   MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1689   /* MDL_BACKUP_COMMIT */
1690   MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2)
1691 };
1692 
1693 
1694 const MDL_lock::bitmap_t
1695 MDL_lock::MDL_backup_lock::m_waiting_incompatible[MDL_BACKUP_END]=
1696 {
1697   /* MDL_BACKUP_START */
1698   MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT),
1699   0,
1700   0,
1701   0,
1702   0,
1703   /* MDL_BACKUP_FTWRL1 */
1704   0,
1705   0,
1706 
1707   /* MDL_BACKUP_DML */
1708   MDL_BIT(MDL_BACKUP_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_FLUSH) | MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1709   MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1710   MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1711   /* MDL_BACKUP_DDL */
1712   MDL_BIT(MDL_BACKUP_WAIT_DDL) | MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2) | MDL_BIT(MDL_BACKUP_BLOCK_DDL),
1713   /* MDL_BACKUP_BLOCK_DDL */
1714   0,
1715   MDL_BIT(MDL_BACKUP_FTWRL1) | MDL_BIT(MDL_BACKUP_FTWRL2),
1716   /* MDL_BACKUP_COMMIT */
1717   MDL_BIT(MDL_BACKUP_WAIT_COMMIT) | MDL_BIT(MDL_BACKUP_FTWRL2)
1718 };
1719 
1720 
1721 /**
1722   Check if request for the metadata lock can be satisfied given its
1723   current state.
1724 
1725   New lock request can be satisfied iff:
1726   - There are no incompatible types of satisfied requests
1727     in other contexts
1728   - There are no waiting requests which have higher priority
1729     than this request when priority was not ignored.
1730 
1731   @param  type_arg             The requested lock type.
1732   @param  requestor_ctx        The MDL context of the requestor.
1733   @param  ignore_lock_priority Ignore lock priority.
1734 
1735   @retval TRUE   Lock request can be satisfied
1736   @retval FALSE  There is some conflicting lock.
1737 
1738   @note In cases then current context already has "stronger" type
1739         of lock on the object it will be automatically granted
1740         thanks to usage of the MDL_context::find_ticket() method.
1741 */
1742 
1743 bool
can_grant_lock(enum_mdl_type type_arg,MDL_context * requestor_ctx,bool ignore_lock_priority) const1744 MDL_lock::can_grant_lock(enum_mdl_type type_arg,
1745                          MDL_context *requestor_ctx,
1746                          bool ignore_lock_priority) const
1747 {
1748   bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
1749   bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
1750 
1751 #ifdef WITH_WSREP
1752   /*
1753     Approve lock request in BACKUP namespace for BF threads.
1754     We should get rid of this code and forbid FTWRL/BACKUP statements
1755     when wsrep is active.
1756   */
1757   if ((wsrep_thd_is_toi(requestor_ctx->get_thd()) ||
1758        wsrep_thd_is_applying(requestor_ctx->get_thd())) &&
1759       key.mdl_namespace() == MDL_key::BACKUP)
1760   {
1761     bool waiting_incompatible= m_waiting.bitmap() & waiting_incompat_map;
1762     bool granted_incompatible= m_granted.bitmap() & granted_incompat_map;
1763     if (waiting_incompatible || granted_incompatible)
1764     {
1765       WSREP_DEBUG("global lock granted for BF%s: %lu %s",
1766                   waiting_incompatible ? " (waiting queue)" : "",
1767                   thd_get_thread_id(requestor_ctx->get_thd()),
1768                   wsrep_thd_query(requestor_ctx->get_thd()));
1769     }
1770     return true;
1771   }
1772 #endif /* WITH_WSREP */
1773 
1774   if (!ignore_lock_priority && (m_waiting.bitmap() & waiting_incompat_map))
1775     return false;
1776 
1777   if (m_granted.bitmap() & granted_incompat_map)
1778   {
1779     Ticket_iterator it(m_granted);
1780     bool can_grant= true;
1781 
1782     /* Check that the incompatible lock belongs to some other context. */
1783     while (auto ticket= it++)
1784     {
1785       if (ticket->get_ctx() != requestor_ctx &&
1786           ticket->is_incompatible_when_granted(type_arg))
1787       {
1788         can_grant= false;
1789 #ifdef WITH_WSREP
1790         /*
1791           non WSREP threads must report conflict immediately
1792           note: RSU processing wsrep threads, have wsrep_on==OFF
1793         */
1794         if (WSREP(requestor_ctx->get_thd()) ||
1795             requestor_ctx->get_thd()->wsrep_cs().mode() ==
1796             wsrep::client_state::m_rsu)
1797         {
1798           wsrep_handle_mdl_conflict(requestor_ctx, ticket, &key);
1799           if (wsrep_log_conflicts)
1800           {
1801             auto key= ticket->get_key();
1802             WSREP_INFO("MDL conflict db=%s table=%s ticket=%d solved by abort",
1803                        key->db_name(), key->name(), ticket->get_type());
1804           }
1805           continue;
1806         }
1807 #endif /* WITH_WSREP */
1808         break;
1809       }
1810     }
1811     return can_grant;
1812   }
1813   return true;
1814 }
1815 
1816 
1817 /**
1818   Return thread id of the thread to which the first ticket was
1819   granted.
1820 */
1821 
1822 inline unsigned long
get_lock_owner() const1823 MDL_lock::get_lock_owner() const
1824 {
1825   Ticket_iterator it(m_granted);
1826   MDL_ticket *ticket;
1827 
1828   if ((ticket= it++))
1829     return ticket->get_ctx()->get_thread_id();
1830   return 0;
1831 }
1832 
1833 
1834 /** Remove a ticket from waiting or pending queue and wakeup up waiters. */
1835 
remove_ticket(LF_PINS * pins,Ticket_list MDL_lock::* list,MDL_ticket * ticket)1836 void MDL_lock::remove_ticket(LF_PINS *pins, Ticket_list MDL_lock::*list,
1837                              MDL_ticket *ticket)
1838 {
1839   mysql_prlock_wrlock(&m_rwlock);
1840   (this->*list).remove_ticket(ticket);
1841   if (is_empty())
1842     mdl_locks.remove(pins, this);
1843   else
1844   {
1845     /*
1846       There can be some contexts waiting to acquire a lock
1847       which now might be able to do it. Grant the lock to
1848       them and wake them up!
1849 
1850       We always try to reschedule locks, since there is no easy way
1851       (i.e. by looking at the bitmaps) to find out whether it is
1852       required or not.
1853       In a general case, even when the queue's bitmap is not changed
1854       after removal of the ticket, there is a chance that some request
1855       can be satisfied (due to the fact that a granted request
1856       reflected in the bitmap might belong to the same context as a
1857       pending request).
1858     */
1859     reschedule_waiters();
1860     mysql_prlock_unlock(&m_rwlock);
1861   }
1862 }
1863 
1864 
1865 /**
1866   Check if we have any pending locks which conflict with existing
1867   shared lock.
1868 
1869   @pre The ticket must match an acquired lock.
1870 
1871   @return TRUE if there is a conflicting lock request, FALSE otherwise.
1872 */
1873 
has_pending_conflicting_lock(enum_mdl_type type)1874 bool MDL_lock::has_pending_conflicting_lock(enum_mdl_type type)
1875 {
1876   bool result;
1877 
1878   mysql_prlock_rdlock(&m_rwlock);
1879   result= (m_waiting.bitmap() & incompatible_granted_types_bitmap()[type]);
1880   mysql_prlock_unlock(&m_rwlock);
1881   return result;
1882 }
1883 
1884 
~MDL_wait_for_graph_visitor()1885 MDL_wait_for_graph_visitor::~MDL_wait_for_graph_visitor()
1886 {
1887 }
1888 
1889 
~MDL_wait_for_subgraph()1890 MDL_wait_for_subgraph::~MDL_wait_for_subgraph()
1891 {
1892 }
1893 
1894 /**
1895   Check if ticket represents metadata lock of "stronger" or equal type
1896   than specified one. I.e. if metadata lock represented by ticket won't
1897   allow any of locks which are not allowed by specified type of lock.
1898 
1899   @return TRUE  if ticket has stronger or equal type
1900           FALSE otherwise.
1901 */
1902 
has_stronger_or_equal_type(enum_mdl_type type) const1903 bool MDL_ticket::has_stronger_or_equal_type(enum_mdl_type type) const
1904 {
1905   const MDL_lock::bitmap_t *
1906     granted_incompat_map= m_lock->incompatible_granted_types_bitmap();
1907 
1908   return ! (granted_incompat_map[type] & ~(granted_incompat_map[m_type]));
1909 }
1910 
1911 
is_incompatible_when_granted(enum_mdl_type type) const1912 bool MDL_ticket::is_incompatible_when_granted(enum_mdl_type type) const
1913 {
1914   return (MDL_BIT(m_type) &
1915           m_lock->incompatible_granted_types_bitmap()[type]);
1916 }
1917 
1918 
is_incompatible_when_waiting(enum_mdl_type type) const1919 bool MDL_ticket::is_incompatible_when_waiting(enum_mdl_type type) const
1920 {
1921   return (MDL_BIT(m_type) &
1922           m_lock->incompatible_waiting_types_bitmap()[type]);
1923 }
1924 
1925 
1926 static const LEX_STRING
get_mdl_lock_name(MDL_key::enum_mdl_namespace mdl_namespace,enum_mdl_type type)1927 *get_mdl_lock_name(MDL_key::enum_mdl_namespace mdl_namespace,
1928                    enum_mdl_type type)
1929 {
1930   return mdl_namespace == MDL_key::BACKUP ?
1931          &backup_lock_types[type] :
1932          &lock_types[type];
1933 }
1934 
1935 
get_type_name() const1936 const LEX_STRING *MDL_ticket::get_type_name() const
1937 {
1938   return get_mdl_lock_name(get_key()->mdl_namespace(), m_type);
1939 }
1940 
get_type_name(enum_mdl_type type) const1941 const LEX_STRING *MDL_ticket::get_type_name(enum_mdl_type type) const
1942 {
1943   return get_mdl_lock_name(get_key()->mdl_namespace(), type);
1944 }
1945 
1946 
1947 /**
1948   Check whether the context already holds a compatible lock ticket
1949   on an object.
1950   Start searching from list of locks for the same duration as lock
1951   being requested. If not look at lists for other durations.
1952 
1953   @param mdl_request  Lock request object for lock to be acquired
1954   @param[out] result_duration  Duration of lock which was found.
1955 
1956   @note Tickets which correspond to lock types "stronger" than one
1957         being requested are also considered compatible.
1958 
1959   @return A pointer to the lock ticket for the object or NULL otherwise.
1960 */
1961 
1962 MDL_ticket *
find_ticket(MDL_request * mdl_request,enum_mdl_duration * result_duration)1963 MDL_context::find_ticket(MDL_request *mdl_request,
1964                          enum_mdl_duration *result_duration)
1965 {
1966   MDL_ticket *ticket;
1967   int i;
1968 
1969   for (i= 0; i < MDL_DURATION_END; i++)
1970   {
1971     enum_mdl_duration duration= (enum_mdl_duration)((mdl_request->duration+i) %
1972                                                     MDL_DURATION_END);
1973     Ticket_iterator it(m_tickets[duration]);
1974 
1975     while ((ticket= it++))
1976     {
1977       if (mdl_request->key.is_equal(&ticket->m_lock->key) &&
1978           ticket->has_stronger_or_equal_type(mdl_request->type))
1979       {
1980         DBUG_PRINT("info", ("Adding mdl lock %s to %s",
1981                             get_mdl_lock_name(mdl_request->key.mdl_namespace(),
1982                                               mdl_request->type)->str,
1983                             ticket->get_type_name()->str));
1984         *result_duration= duration;
1985         return ticket;
1986       }
1987     }
1988   }
1989   return NULL;
1990 }
1991 
1992 
1993 /**
1994   Try to acquire one lock.
1995 
1996   Unlike exclusive locks, shared locks are acquired one by
1997   one. This is interface is chosen to simplify introduction of
1998   the new locking API to the system. MDL_context::try_acquire_lock()
1999   is currently used from open_table(), and there we have only one
2000   table to work with.
2001 
2002   This function may also be used to try to acquire an exclusive
2003   lock on a destination table, by ALTER TABLE ... RENAME.
2004 
2005   Returns immediately without any side effect if encounters a lock
2006   conflict. Otherwise takes the lock.
2007 
2008   FIXME: Compared to lock_table_name_if_not_cached() (from 5.1)
2009          it gives slightly more false negatives.
2010 
2011   @param mdl_request [in/out] Lock request object for lock to be acquired
2012 
2013   @retval  FALSE   Success. The lock may have not been acquired.
2014                    Check the ticket, if it's NULL, a conflicting lock
2015                    exists.
2016   @retval  TRUE    Out of resources, an error has been reported.
2017 */
2018 
2019 bool
try_acquire_lock(MDL_request * mdl_request)2020 MDL_context::try_acquire_lock(MDL_request *mdl_request)
2021 {
2022   MDL_ticket *ticket;
2023 
2024   if (try_acquire_lock_impl(mdl_request, &ticket))
2025     return TRUE;
2026 
2027   if (! mdl_request->ticket)
2028   {
2029     /*
2030       Our attempt to acquire lock without waiting has failed.
2031       Let us release resources which were acquired in the process.
2032       We can't get here if we allocated a new lock object so there
2033       is no need to release it.
2034     */
2035     DBUG_ASSERT(! ticket->m_lock->is_empty());
2036     mysql_prlock_unlock(&ticket->m_lock->m_rwlock);
2037     MDL_ticket::destroy(ticket);
2038   }
2039 
2040   return FALSE;
2041 }
2042 
2043 
2044 /**
2045   Auxiliary method for acquiring lock without waiting.
2046 
2047   @param mdl_request [in/out] Lock request object for lock to be acquired
2048   @param out_ticket  [out]    Ticket for the request in case when lock
2049                               has not been acquired.
2050 
2051   @retval  FALSE   Success. The lock may have not been acquired.
2052                    Check MDL_request::ticket, if it's NULL, a conflicting
2053                    lock exists. In this case "out_ticket" out parameter
2054                    points to ticket which was constructed for the request.
2055                    MDL_ticket::m_lock points to the corresponding MDL_lock
2056                    object and MDL_lock::m_rwlock write-locked.
2057   @retval  TRUE    Out of resources, an error has been reported.
2058 */
2059 
2060 bool
try_acquire_lock_impl(MDL_request * mdl_request,MDL_ticket ** out_ticket)2061 MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
2062                                    MDL_ticket **out_ticket)
2063 {
2064   MDL_lock *lock;
2065   MDL_key *key= &mdl_request->key;
2066   MDL_ticket *ticket;
2067   enum_mdl_duration found_duration;
2068 
2069   /* Don't take chances in production. */
2070   DBUG_ASSERT(mdl_request->ticket == NULL);
2071   mdl_request->ticket= NULL;
2072 
2073   /*
2074     Check whether the context already holds a shared lock on the object,
2075     and if so, grant the request.
2076   */
2077   if ((ticket= find_ticket(mdl_request, &found_duration)))
2078   {
2079     DBUG_ASSERT(ticket->m_lock);
2080     DBUG_ASSERT(ticket->has_stronger_or_equal_type(mdl_request->type));
2081     /*
2082       If the request is for a transactional lock, and we found
2083       a transactional lock, just reuse the found ticket.
2084 
2085       It's possible that we found a transactional lock,
2086       but the request is for a HANDLER lock. In that case HANDLER
2087       code will clone the ticket (see below why it's needed).
2088 
2089       If the request is for a transactional lock, and we found
2090       a HANDLER lock, create a copy, to make sure that when user
2091       does HANDLER CLOSE, the transactional lock is not released.
2092 
2093       If the request is for a handler lock, and we found a
2094       HANDLER lock, also do the clone. HANDLER CLOSE for one alias
2095       should not release the lock on the table HANDLER opened through
2096       a different alias.
2097     */
2098     mdl_request->ticket= ticket;
2099     if ((found_duration != mdl_request->duration ||
2100          mdl_request->duration == MDL_EXPLICIT) &&
2101         clone_ticket(mdl_request))
2102     {
2103       /* Clone failed. */
2104       mdl_request->ticket= NULL;
2105       return TRUE;
2106     }
2107     return FALSE;
2108   }
2109 
2110   if (fix_pins())
2111     return TRUE;
2112 
2113   if (!(ticket= MDL_ticket::create(this, mdl_request->type
2114 #ifndef DBUG_OFF
2115                                    , mdl_request->duration
2116 #endif
2117                                    )))
2118     return TRUE;
2119 
2120   /* The below call implicitly locks MDL_lock::m_rwlock on success. */
2121   if (!(lock= mdl_locks.find_or_insert(m_pins, key)))
2122   {
2123     MDL_ticket::destroy(ticket);
2124     return TRUE;
2125   }
2126 
2127   ticket->m_lock= lock;
2128 
2129   if (lock->can_grant_lock(mdl_request->type, this, false))
2130   {
2131     lock->m_granted.add_ticket(ticket);
2132 
2133     mysql_prlock_unlock(&lock->m_rwlock);
2134 
2135     m_tickets[mdl_request->duration].push_front(ticket);
2136 
2137     mdl_request->ticket= ticket;
2138   }
2139   else
2140     *out_ticket= ticket;
2141 
2142   return FALSE;
2143 }
2144 
2145 
2146 /**
2147   Create a copy of a granted ticket.
2148   This is used to make sure that HANDLER ticket
2149   is never shared with a ticket that belongs to
2150   a transaction, so that when we HANDLER CLOSE,
2151   we don't release a transactional ticket, and
2152   vice versa -- when we COMMIT, we don't mistakenly
2153   release a ticket for an open HANDLER.
2154 
2155   @retval TRUE   Out of memory.
2156   @retval FALSE  Success.
2157 */
2158 
2159 bool
clone_ticket(MDL_request * mdl_request)2160 MDL_context::clone_ticket(MDL_request *mdl_request)
2161 {
2162   MDL_ticket *ticket;
2163 
2164 
2165   /*
2166     Since in theory we can clone ticket belonging to a different context
2167     we need to prepare target context for possible attempts to release
2168     lock and thus possible removal of MDL_lock from MDL_map container.
2169     So we allocate pins to be able to work with this container if they
2170     are not allocated already.
2171   */
2172   if (fix_pins())
2173     return TRUE;
2174 
2175   /*
2176     By submitting mdl_request->type to MDL_ticket::create()
2177     we effectively downgrade the cloned lock to the level of
2178     the request.
2179   */
2180   if (!(ticket= MDL_ticket::create(this, mdl_request->type
2181 #ifndef DBUG_OFF
2182                                    , mdl_request->duration
2183 #endif
2184                                    )))
2185     return TRUE;
2186 
2187   /* clone() is not supposed to be used to get a stronger lock. */
2188   DBUG_ASSERT(mdl_request->ticket->has_stronger_or_equal_type(ticket->m_type));
2189 
2190   ticket->m_lock= mdl_request->ticket->m_lock;
2191   mdl_request->ticket= ticket;
2192 
2193   mysql_prlock_wrlock(&ticket->m_lock->m_rwlock);
2194   ticket->m_lock->m_granted.add_ticket(ticket);
2195   mysql_prlock_unlock(&ticket->m_lock->m_rwlock);
2196 
2197   m_tickets[mdl_request->duration].push_front(ticket);
2198 
2199   return FALSE;
2200 }
2201 
2202 
2203 /**
2204   Check if there is any conflicting lock that could cause this thread
2205   to wait for another thread which is not ready to commit.
2206   This is always an error, as the upper level of parallel replication
2207   should not allow a scheduling of a conflicting DDL until all earlier
2208   transactions has commited.
2209 
2210   This function is only called for a slave using parallel replication
2211   and trying to get an exclusive lock for the table.
2212 */
2213 
2214 #ifndef DBUG_OFF
check_if_conflicting_replication_locks(MDL_context * ctx)2215 bool MDL_lock::check_if_conflicting_replication_locks(MDL_context *ctx)
2216 {
2217   Ticket_iterator it(m_granted);
2218   MDL_ticket *conflicting_ticket;
2219   rpl_group_info *rgi_slave= ctx->get_thd()->rgi_slave;
2220 
2221   if (!rgi_slave->gtid_sub_id)
2222     return 0;
2223 
2224   while ((conflicting_ticket= it++))
2225   {
2226     if (conflicting_ticket->get_ctx() != ctx)
2227     {
2228       MDL_context *conflicting_ctx= conflicting_ticket->get_ctx();
2229       rpl_group_info *conflicting_rgi_slave;
2230       conflicting_rgi_slave= conflicting_ctx->get_thd()->rgi_slave;
2231 
2232       /*
2233         If the conflicting thread is another parallel replication
2234         thread for the same master and it's not in commit stage, then
2235         the current transaction has started too early and something is
2236         seriously wrong.
2237       */
2238       if (conflicting_rgi_slave &&
2239           conflicting_rgi_slave->gtid_sub_id &&
2240           conflicting_rgi_slave->rli == rgi_slave->rli &&
2241           conflicting_rgi_slave->current_gtid.domain_id ==
2242           rgi_slave->current_gtid.domain_id &&
2243           !conflicting_rgi_slave->did_mark_start_commit)
2244         return 1;                               // Fatal error
2245     }
2246   }
2247   return 0;
2248 }
2249 #endif
2250 
2251 
2252 /**
2253   Acquire one lock with waiting for conflicting locks to go away if needed.
2254 
2255   @param mdl_request [in/out] Lock request object for lock to be acquired
2256 
2257   @param lock_wait_timeout [in] Seconds to wait before timeout.
2258 
2259   @retval  FALSE   Success. MDL_request::ticket points to the ticket
2260                    for the lock.
2261   @retval  TRUE    Failure (Out of resources or waiting is aborted),
2262 */
2263 
2264 bool
acquire_lock(MDL_request * mdl_request,double lock_wait_timeout)2265 MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
2266 {
2267   MDL_lock *lock;
2268   MDL_ticket *ticket;
2269   MDL_wait::enum_wait_status wait_status;
2270   DBUG_ENTER("MDL_context::acquire_lock");
2271   DBUG_PRINT("enter", ("lock_type: %s  timeout: %f",
2272                        get_mdl_lock_name(mdl_request->key.mdl_namespace(),
2273                                          mdl_request->type)->str,
2274                        lock_wait_timeout));
2275 
2276   if (try_acquire_lock_impl(mdl_request, &ticket))
2277     DBUG_RETURN(TRUE);
2278 
2279   if (mdl_request->ticket)
2280   {
2281     /*
2282       We have managed to acquire lock without waiting.
2283       MDL_lock, MDL_context and MDL_request were updated
2284       accordingly, so we can simply return success.
2285     */
2286     DBUG_PRINT("info", ("Got lock without waiting"));
2287     DBUG_RETURN(FALSE);
2288   }
2289 
2290   /*
2291     Our attempt to acquire lock without waiting has failed.
2292     As a result of this attempt we got MDL_ticket with m_lock
2293     member pointing to the corresponding MDL_lock object which
2294     has MDL_lock::m_rwlock write-locked.
2295   */
2296   lock= ticket->m_lock;
2297 
2298   if (lock_wait_timeout == 0)
2299   {
2300     mysql_prlock_unlock(&lock->m_rwlock);
2301     MDL_ticket::destroy(ticket);
2302     my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
2303     DBUG_RETURN(TRUE);
2304   }
2305 
2306   lock->m_waiting.add_ticket(ticket);
2307 
2308   /*
2309     Once we added a pending ticket to the waiting queue,
2310     we must ensure that our wait slot is empty, so
2311     that our lock request can be scheduled. Do that in the
2312     critical section formed by the acquired write lock on MDL_lock.
2313   */
2314   m_wait.reset_status();
2315 
2316   /*
2317     Don't break conflicting locks if timeout is 0 as 0 is used
2318     To check if there is any conflicting locks...
2319   */
2320   if (lock->needs_notification(ticket) && lock_wait_timeout)
2321     lock->notify_conflicting_locks(this);
2322 
2323   /*
2324     Ensure that if we are trying to get an exclusive lock for a slave
2325     running parallel replication, then we are not blocked by another
2326     parallel slave thread that is not committed. This should never happen as
2327     the parallel replication scheduler should never schedule a DDL while
2328     DML's are still running.
2329   */
2330   DBUG_SLOW_ASSERT((mdl_request->type != MDL_INTENTION_EXCLUSIVE &&
2331                     mdl_request->type != MDL_EXCLUSIVE) ||
2332                    !(get_thd()->rgi_slave &&
2333                      get_thd()->rgi_slave->is_parallel_exec &&
2334                      lock->check_if_conflicting_replication_locks(this)));
2335 
2336   mysql_prlock_unlock(&lock->m_rwlock);
2337 
2338   will_wait_for(ticket);
2339 
2340   /* There is a shared or exclusive lock on the object. */
2341   DEBUG_SYNC(get_thd(), "mdl_acquire_lock_wait");
2342 
2343   find_deadlock();
2344 
2345   struct timespec abs_timeout, abs_shortwait;
2346   set_timespec_nsec(abs_timeout,
2347                     (ulonglong)(lock_wait_timeout * 1000000000ULL));
2348   set_timespec(abs_shortwait, 1);
2349   wait_status= MDL_wait::EMPTY;
2350 
2351   while (cmp_timespec(abs_shortwait, abs_timeout) <= 0)
2352   {
2353     /* abs_timeout is far away. Wait a short while and notify locks. */
2354     wait_status= m_wait.timed_wait(m_owner, &abs_shortwait, FALSE,
2355                                    mdl_request->key.get_wait_state_name());
2356 
2357     if (wait_status != MDL_wait::EMPTY)
2358       break;
2359     /* Check if the client is gone while we were waiting. */
2360     if (! thd_is_connected(m_owner->get_thd()))
2361     {
2362       /*
2363        * The client is disconnected. Don't wait forever:
2364        * assume it's the same as a wait timeout, this
2365        * ensures all error handling is correct.
2366        */
2367       wait_status= MDL_wait::TIMEOUT;
2368       break;
2369     }
2370 
2371     mysql_prlock_wrlock(&lock->m_rwlock);
2372     if (lock->needs_notification(ticket))
2373       lock->notify_conflicting_locks(this);
2374     mysql_prlock_unlock(&lock->m_rwlock);
2375     set_timespec(abs_shortwait, 1);
2376   }
2377   if (wait_status == MDL_wait::EMPTY)
2378     wait_status= m_wait.timed_wait(m_owner, &abs_timeout, TRUE,
2379                                    mdl_request->key.get_wait_state_name());
2380 
2381   done_waiting_for();
2382 
2383   if (wait_status != MDL_wait::GRANTED)
2384   {
2385     lock->remove_ticket(m_pins, &MDL_lock::m_waiting, ticket);
2386     MDL_ticket::destroy(ticket);
2387     switch (wait_status)
2388     {
2389     case MDL_wait::VICTIM:
2390       DBUG_LOCK_FILE;
2391       DBUG_PRINT("mdl_locks", ("%s", mdl_dbug_print_locks()));
2392       DBUG_UNLOCK_FILE;
2393       my_error(ER_LOCK_DEADLOCK, MYF(0));
2394       break;
2395     case MDL_wait::TIMEOUT:
2396       my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
2397       break;
2398     case MDL_wait::KILLED:
2399       get_thd()->send_kill_message();
2400       break;
2401     default:
2402       DBUG_ASSERT(0);
2403       break;
2404     }
2405     DBUG_RETURN(TRUE);
2406   }
2407 
2408   /*
2409     We have been granted our request.
2410     State of MDL_lock object is already being appropriately updated by a
2411     concurrent thread (@sa MDL_lock:reschedule_waiters()).
2412     So all we need to do is to update MDL_context and MDL_request objects.
2413   */
2414   DBUG_ASSERT(wait_status == MDL_wait::GRANTED);
2415 
2416   m_tickets[mdl_request->duration].push_front(ticket);
2417 
2418   mdl_request->ticket= ticket;
2419 
2420   DBUG_RETURN(FALSE);
2421 }
2422 
2423 
mdl_request_ptr_cmp(const void * ptr1,const void * ptr2)2424 extern "C" int mdl_request_ptr_cmp(const void* ptr1, const void* ptr2)
2425 {
2426   MDL_request *req1= *(MDL_request**)ptr1;
2427   MDL_request *req2= *(MDL_request**)ptr2;
2428   return req1->key.cmp(&req2->key);
2429 }
2430 
2431 
2432 /**
2433   Acquire exclusive locks. There must be no granted locks in the
2434   context.
2435 
2436   This is a replacement of lock_table_names(). It is used in
2437   RENAME, DROP and other DDL SQL statements.
2438 
2439   @param  mdl_requests  List of requests for locks to be acquired.
2440 
2441   @param lock_wait_timeout  Seconds to wait before timeout.
2442 
2443   @note The list of requests should not contain non-exclusive lock requests.
2444         There should not be any acquired locks in the context.
2445 
2446   @note Assumes that one already owns scoped intention exclusive lock.
2447 
2448   @retval FALSE  Success
2449   @retval TRUE   Failure
2450 */
2451 
acquire_locks(MDL_request_list * mdl_requests,double lock_wait_timeout)2452 bool MDL_context::acquire_locks(MDL_request_list *mdl_requests,
2453                                 double lock_wait_timeout)
2454 {
2455   MDL_request_list::Iterator it(*mdl_requests);
2456   MDL_request **sort_buf, **p_req;
2457   MDL_savepoint mdl_svp= mdl_savepoint();
2458   ssize_t req_count= static_cast<ssize_t>(mdl_requests->elements());
2459   DBUG_ENTER("MDL_context::acquire_locks");
2460 
2461   if (req_count == 0)
2462     DBUG_RETURN(FALSE);
2463 
2464   /* Sort requests according to MDL_key. */
2465   if (! (sort_buf= (MDL_request **)my_malloc(req_count *
2466                                              sizeof(MDL_request*),
2467                                              MYF(MY_WME))))
2468     DBUG_RETURN(TRUE);
2469 
2470   for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++)
2471     *p_req= it++;
2472 
2473   my_qsort(sort_buf, req_count, sizeof(MDL_request*),
2474            mdl_request_ptr_cmp);
2475 
2476   for (p_req= sort_buf; p_req < sort_buf + req_count; p_req++)
2477   {
2478     if (acquire_lock(*p_req, lock_wait_timeout))
2479       goto err;
2480   }
2481   my_free(sort_buf);
2482   DBUG_RETURN(FALSE);
2483 
2484 err:
2485   /*
2486     Release locks we have managed to acquire so far.
2487     Use rollback_to_savepoint() since there may be duplicate
2488     requests that got assigned the same ticket.
2489   */
2490   rollback_to_savepoint(mdl_svp);
2491   /* Reset lock requests back to its initial state. */
2492   for (req_count= p_req - sort_buf, p_req= sort_buf;
2493        p_req < sort_buf + req_count; p_req++)
2494   {
2495     (*p_req)->ticket= NULL;
2496   }
2497   my_free(sort_buf);
2498   DBUG_RETURN(TRUE);
2499 }
2500 
2501 
2502 /**
2503   Upgrade a shared metadata lock.
2504 
2505   Used in ALTER TABLE.
2506 
2507   @param mdl_ticket         Lock to upgrade.
2508   @param new_type           Lock type to upgrade to.
2509   @param lock_wait_timeout  Seconds to wait before timeout.
2510 
2511   @note In case of failure to upgrade lock (e.g. because upgrader
2512         was killed) leaves lock in its original state (locked in
2513         shared mode).
2514 
2515   @note There can be only one upgrader for a lock or we will have deadlock.
2516         This invariant is ensured by the fact that upgradeable locks SU, SNW
2517         and SNRW are not compatible with each other and themselves.
2518 
2519   @retval FALSE  Success
2520   @retval TRUE   Failure (thread was killed)
2521 */
2522 
2523 bool
upgrade_shared_lock(MDL_ticket * mdl_ticket,enum_mdl_type new_type,double lock_wait_timeout)2524 MDL_context::upgrade_shared_lock(MDL_ticket *mdl_ticket,
2525                                  enum_mdl_type new_type,
2526                                  double lock_wait_timeout)
2527 {
2528   MDL_request mdl_xlock_request;
2529   MDL_savepoint mdl_svp= mdl_savepoint();
2530   bool is_new_ticket;
2531   DBUG_ENTER("MDL_context::upgrade_shared_lock");
2532   DBUG_PRINT("enter",("old_type: %s  new_type: %s  lock_wait_timeout: %f",
2533                       mdl_ticket->get_type_name()->str,
2534                       mdl_ticket->get_type_name(new_type)->str,
2535                       lock_wait_timeout));
2536   DEBUG_SYNC(get_thd(), "mdl_upgrade_lock");
2537 
2538   /*
2539     Do nothing if already upgraded. Used when we FLUSH TABLE under
2540     LOCK TABLES and a table is listed twice in LOCK TABLES list.
2541 
2542     In BACKUP namespace upgrade must always happen. Even though
2543     MDL_BACKUP_START is not stronger than MDL_BACKUP_FLUSH from
2544     has_stronger_or_equal_type(), the latter effectively blocks
2545     new MDL_BACKUP_DML while the former doesn't.
2546   */
2547   if (mdl_ticket->has_stronger_or_equal_type(new_type) &&
2548       mdl_ticket->get_key()->mdl_namespace() != MDL_key::BACKUP)
2549     DBUG_RETURN(FALSE);
2550 
2551   mdl_xlock_request.init(&mdl_ticket->m_lock->key, new_type,
2552                          MDL_TRANSACTION);
2553 
2554   if (acquire_lock(&mdl_xlock_request, lock_wait_timeout))
2555     DBUG_RETURN(TRUE);
2556 
2557   is_new_ticket= ! has_lock(mdl_svp, mdl_xlock_request.ticket);
2558 
2559   /* Merge the acquired and the original lock. @todo: move to a method. */
2560   mysql_prlock_wrlock(&mdl_ticket->m_lock->m_rwlock);
2561   if (is_new_ticket)
2562     mdl_ticket->m_lock->m_granted.remove_ticket(mdl_xlock_request.ticket);
2563   /*
2564     Set the new type of lock in the ticket. To update state of
2565     MDL_lock object correctly we need to temporarily exclude
2566     ticket from the granted queue and then include it back.
2567   */
2568   mdl_ticket->m_lock->m_granted.remove_ticket(mdl_ticket);
2569   mdl_ticket->m_type= new_type;
2570   mdl_ticket->m_lock->m_granted.add_ticket(mdl_ticket);
2571 
2572   mysql_prlock_unlock(&mdl_ticket->m_lock->m_rwlock);
2573 
2574   if (is_new_ticket)
2575   {
2576     m_tickets[MDL_TRANSACTION].remove(mdl_xlock_request.ticket);
2577     MDL_ticket::destroy(mdl_xlock_request.ticket);
2578   }
2579 
2580   DBUG_RETURN(FALSE);
2581 }
2582 
2583 
2584 /**
2585   A fragment of recursive traversal of the wait-for graph
2586   in search for deadlocks. Direct the deadlock visitor to all
2587   contexts that own the lock the current node in the wait-for
2588   graph is waiting for.
2589   As long as the initial node is remembered in the visitor,
2590   a deadlock is found when the same node is seen twice.
2591 */
2592 
visit_subgraph(MDL_ticket * waiting_ticket,MDL_wait_for_graph_visitor * gvisitor)2593 bool MDL_lock::visit_subgraph(MDL_ticket *waiting_ticket,
2594                               MDL_wait_for_graph_visitor *gvisitor)
2595 {
2596   MDL_ticket *ticket;
2597   MDL_context *src_ctx= waiting_ticket->get_ctx();
2598   bool result= TRUE;
2599 
2600   mysql_prlock_rdlock(&m_rwlock);
2601 
2602   /* Must be initialized after taking a read lock. */
2603   Ticket_iterator granted_it(m_granted);
2604   Ticket_iterator waiting_it(m_waiting);
2605 
2606   /*
2607     MDL_lock's waiting and granted queues and MDL_context::m_waiting_for
2608     member are updated by different threads when the lock is granted
2609     (see MDL_context::acquire_lock() and MDL_lock::reschedule_waiters()).
2610     As a result, here we may encounter a situation when MDL_lock data
2611     already reflects the fact that the lock was granted but
2612     m_waiting_for member has not been updated yet.
2613 
2614     For example, imagine that:
2615 
2616     thread1: Owns SNW lock on table t1.
2617     thread2: Attempts to acquire SW lock on t1,
2618              but sees an active SNW lock.
2619              Thus adds the ticket to the waiting queue and
2620              sets m_waiting_for to point to the ticket.
2621     thread1: Releases SNW lock, updates MDL_lock object to
2622              grant SW lock to thread2 (moves the ticket for
2623              SW from waiting to the active queue).
2624              Attempts to acquire a new SNW lock on t1,
2625              sees an active SW lock (since it is present in the
2626              active queue), adds ticket for SNW lock to the waiting
2627              queue, sets m_waiting_for to point to this ticket.
2628 
2629     At this point deadlock detection algorithm run by thread1 will see that:
2630     - Thread1 waits for SNW lock on t1 (since m_waiting_for is set).
2631     - SNW lock is not granted, because it conflicts with active SW lock
2632       owned by thread 2 (since ticket for SW is present in granted queue).
2633     - Thread2 waits for SW lock (since its m_waiting_for has not been
2634       updated yet!).
2635     - SW lock is not granted because there is pending SNW lock from thread1.
2636       Therefore deadlock should exist [sic!].
2637 
2638     To avoid detection of such false deadlocks we need to check the "actual"
2639     status of the ticket being waited for, before analyzing its blockers.
2640     We do this by checking the wait status of the context which is waiting
2641     for it. To avoid races this has to be done under protection of
2642     MDL_lock::m_rwlock lock.
2643   */
2644   if (src_ctx->m_wait.get_status() != MDL_wait::EMPTY)
2645   {
2646     result= FALSE;
2647     goto end;
2648   }
2649 
2650   /*
2651     To avoid visiting nodes which were already marked as victims of
2652     deadlock detection (or whose requests were already satisfied) we
2653     enter the node only after peeking at its wait status.
2654     This is necessary to avoid active waiting in a situation
2655     when previous searches for a deadlock already selected the
2656     node we're about to enter as a victim (see the comment
2657     in MDL_context::find_deadlock() for explanation why several searches
2658     can be performed for the same wait).
2659     There is no guarantee that the node isn't chosen a victim while we
2660     are visiting it but this is OK: in the worst case we might do some
2661     extra work and one more context might be chosen as a victim.
2662   */
2663   if (gvisitor->enter_node(src_ctx))
2664     goto end;
2665 
2666   /*
2667     We do a breadth-first search first -- that is, inspect all
2668     edges of the current node, and only then follow up to the next
2669     node. In workloads that involve wait-for graph loops this
2670     has proven to be a more efficient strategy [citation missing].
2671   */
2672   while ((ticket= granted_it++))
2673   {
2674     /* Filter out edges that point to the same node. */
2675     if (ticket->get_ctx() != src_ctx &&
2676         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
2677         gvisitor->inspect_edge(ticket->get_ctx()))
2678     {
2679       goto end_leave_node;
2680     }
2681   }
2682 
2683   while ((ticket= waiting_it++))
2684   {
2685     /* Filter out edges that point to the same node. */
2686     if (ticket->get_ctx() != src_ctx &&
2687         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
2688         gvisitor->inspect_edge(ticket->get_ctx()))
2689     {
2690       goto end_leave_node;
2691     }
2692   }
2693 
2694   /* Recurse and inspect all adjacent nodes. */
2695   granted_it.rewind();
2696   while ((ticket= granted_it++))
2697   {
2698     if (ticket->get_ctx() != src_ctx &&
2699         ticket->is_incompatible_when_granted(waiting_ticket->get_type()) &&
2700         ticket->get_ctx()->visit_subgraph(gvisitor))
2701     {
2702       goto end_leave_node;
2703     }
2704   }
2705 
2706   waiting_it.rewind();
2707   while ((ticket= waiting_it++))
2708   {
2709     if (ticket->get_ctx() != src_ctx &&
2710         ticket->is_incompatible_when_waiting(waiting_ticket->get_type()) &&
2711         ticket->get_ctx()->visit_subgraph(gvisitor))
2712     {
2713       goto end_leave_node;
2714     }
2715   }
2716 
2717   result= FALSE;
2718 
2719 end_leave_node:
2720   gvisitor->leave_node(src_ctx);
2721 
2722 end:
2723   mysql_prlock_unlock(&m_rwlock);
2724   return result;
2725 }
2726 
2727 
2728 /**
2729   Traverse a portion of wait-for graph which is reachable
2730   through the edge represented by this ticket and search
2731   for deadlocks.
2732 
2733   @retval TRUE  A deadlock is found. A pointer to deadlock
2734                  victim is saved in the visitor.
2735   @retval FALSE
2736 */
2737 
accept_visitor(MDL_wait_for_graph_visitor * gvisitor)2738 bool MDL_ticket::accept_visitor(MDL_wait_for_graph_visitor *gvisitor)
2739 {
2740   return m_lock->visit_subgraph(this, gvisitor);
2741 }
2742 
2743 
2744 /**
2745   A fragment of recursive traversal of the wait-for graph of
2746   MDL contexts in the server in search for deadlocks.
2747   Assume this MDL context is a node in the wait-for graph,
2748   and direct the visitor to all adjacent nodes. As long
2749   as the starting node is remembered in the visitor, a
2750   deadlock is found when the same node is visited twice.
2751   One MDL context is connected to another in the wait-for
2752   graph if it waits on a resource that is held by the other
2753   context.
2754 
2755   @retval TRUE  A deadlock is found. A pointer to deadlock
2756                 victim is saved in the visitor.
2757   @retval FALSE
2758 */
2759 
visit_subgraph(MDL_wait_for_graph_visitor * gvisitor)2760 bool MDL_context::visit_subgraph(MDL_wait_for_graph_visitor *gvisitor)
2761 {
2762   bool result= FALSE;
2763 
2764   mysql_prlock_rdlock(&m_LOCK_waiting_for);
2765 
2766   if (m_waiting_for)
2767     result= m_waiting_for->accept_visitor(gvisitor);
2768 
2769   mysql_prlock_unlock(&m_LOCK_waiting_for);
2770 
2771   return result;
2772 }
2773 
2774 
2775 /**
2776   Try to find a deadlock. This function produces no errors.
2777 
2778   @note If during deadlock resolution context which performs deadlock
2779         detection is chosen as a victim it will be informed about the
2780         fact by setting VICTIM status to its wait slot.
2781 */
2782 
find_deadlock()2783 void MDL_context::find_deadlock()
2784 {
2785   while (1)
2786   {
2787     /*
2788       The fact that we use fresh instance of gvisitor for each
2789       search performed by find_deadlock() below is important,
2790       the code responsible for victim selection relies on this.
2791     */
2792     Deadlock_detection_visitor dvisitor(this);
2793     MDL_context *victim;
2794 
2795     if (! visit_subgraph(&dvisitor))
2796     {
2797       /* No deadlocks are found! */
2798       break;
2799     }
2800 
2801     victim= dvisitor.get_victim();
2802 
2803     /*
2804       Failure to change status of the victim is OK as it means
2805       that the victim has received some other message and is
2806       about to stop its waiting/to break deadlock loop.
2807       Even when the initiator of the deadlock search is
2808       chosen the victim, we need to set the respective wait
2809       result in order to "close" it for any attempt to
2810       schedule the request.
2811       This is needed to avoid a possible race during
2812       cleanup in case when the lock request on which the
2813       context was waiting is concurrently satisfied.
2814     */
2815     (void) victim->m_wait.set_status(MDL_wait::VICTIM);
2816     victim->inc_deadlock_overweight();
2817     victim->unlock_deadlock_victim();
2818 
2819     if (victim == this)
2820       break;
2821     /*
2822       After adding a new edge to the waiting graph we found that it
2823       creates a loop (i.e. there is a deadlock). We decided to destroy
2824       this loop by removing an edge, but not the one that we added.
2825       Since this doesn't guarantee that all loops created by addition
2826       of the new edge are destroyed, we have to repeat the search.
2827     */
2828   }
2829 }
2830 
2831 
2832 /**
2833   Release lock.
2834 
2835   @param duration Lock duration.
2836   @param ticket   Ticket for lock to be released.
2837 
2838 */
2839 
release_lock(enum_mdl_duration duration,MDL_ticket * ticket)2840 void MDL_context::release_lock(enum_mdl_duration duration, MDL_ticket *ticket)
2841 {
2842   MDL_lock *lock= ticket->m_lock;
2843   DBUG_ENTER("MDL_context::release_lock");
2844   DBUG_PRINT("enter", ("db: '%s' name: '%s'",
2845                        lock->key.db_name(), lock->key.name()));
2846 
2847   DBUG_ASSERT(this == ticket->get_ctx());
2848 
2849   lock->remove_ticket(m_pins, &MDL_lock::m_granted, ticket);
2850 
2851   m_tickets[duration].remove(ticket);
2852   MDL_ticket::destroy(ticket);
2853 
2854   DBUG_VOID_RETURN;
2855 }
2856 
2857 
2858 /**
2859   Release lock with explicit duration.
2860 
2861   @param ticket   Ticket for lock to be released.
2862 
2863 */
2864 
release_lock(MDL_ticket * ticket)2865 void MDL_context::release_lock(MDL_ticket *ticket)
2866 {
2867   DBUG_SLOW_ASSERT(ticket->m_duration == MDL_EXPLICIT);
2868 
2869   release_lock(MDL_EXPLICIT, ticket);
2870 }
2871 
2872 
2873 /**
2874   Release all locks associated with the context. If the sentinel
2875   is not NULL, do not release locks stored in the list after and
2876   including the sentinel.
2877 
2878   Statement and transactional locks are added to the beginning of
2879   the corresponding lists, i.e. stored in reverse temporal order.
2880   This allows to employ this function to:
2881   - back off in case of a lock conflict.
2882   - release all locks in the end of a statement or transaction
2883   - rollback to a savepoint.
2884 */
2885 
release_locks_stored_before(enum_mdl_duration duration,MDL_ticket * sentinel)2886 void MDL_context::release_locks_stored_before(enum_mdl_duration duration,
2887                                               MDL_ticket *sentinel)
2888 {
2889   MDL_ticket *ticket;
2890   Ticket_iterator it(m_tickets[duration]);
2891   DBUG_ENTER("MDL_context::release_locks_stored_before");
2892 
2893   if (m_tickets[duration].is_empty())
2894     DBUG_VOID_RETURN;
2895 
2896   while ((ticket= it++) && ticket != sentinel)
2897   {
2898     DBUG_PRINT("info", ("found lock to release ticket=%p", ticket));
2899     release_lock(duration, ticket);
2900   }
2901 
2902   DBUG_VOID_RETURN;
2903 }
2904 
2905 
2906 /**
2907   Release all explicit locks in the context which correspond to the
2908   same name/object as this lock request.
2909 
2910   @param ticket    One of the locks for the name/object for which all
2911                    locks should be released.
2912 */
2913 
release_all_locks_for_name(MDL_ticket * name)2914 void MDL_context::release_all_locks_for_name(MDL_ticket *name)
2915 {
2916   /* Use MDL_ticket::m_lock to identify other locks for the same object. */
2917   MDL_lock *lock= name->m_lock;
2918 
2919   /* Remove matching lock tickets from the context. */
2920   MDL_ticket *ticket;
2921   Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
2922 
2923   while ((ticket= it_ticket++))
2924   {
2925     DBUG_ASSERT(ticket->m_lock);
2926     if (ticket->m_lock == lock)
2927       release_lock(MDL_EXPLICIT, ticket);
2928   }
2929 }
2930 
2931 
2932 /**
2933   Downgrade an EXCLUSIVE or SHARED_NO_WRITE lock to shared metadata lock.
2934 
2935   @param type  Type of lock to which exclusive lock should be downgraded.
2936 */
2937 
downgrade_lock(enum_mdl_type type)2938 void MDL_ticket::downgrade_lock(enum_mdl_type type)
2939 {
2940   /*
2941     Do nothing if already downgraded. Used when we FLUSH TABLE under
2942     LOCK TABLES and a table is listed twice in LOCK TABLES list.
2943     Note that this code might even try to "downgrade" a weak lock
2944     (e.g. SW) to a stronger one (e.g SNRW). So we can't even assert
2945     here that target lock is weaker than existing lock.
2946   */
2947   if (m_type == type || !has_stronger_or_equal_type(type))
2948     return;
2949 
2950   /* Only allow downgrade in some specific known cases */
2951   DBUG_ASSERT((get_key()->mdl_namespace() != MDL_key::BACKUP &&
2952                (m_type == MDL_EXCLUSIVE ||
2953                 m_type == MDL_SHARED_NO_WRITE)) ||
2954               (get_key()->mdl_namespace() == MDL_key::BACKUP &&
2955                (m_type == MDL_BACKUP_DDL ||
2956                 m_type == MDL_BACKUP_WAIT_FLUSH)));
2957 
2958   mysql_prlock_wrlock(&m_lock->m_rwlock);
2959   /*
2960     To update state of MDL_lock object correctly we need to temporarily
2961     exclude ticket from the granted queue and then include it back.
2962   */
2963   m_lock->m_granted.remove_ticket(this);
2964   m_type= type;
2965   m_lock->m_granted.add_ticket(this);
2966   m_lock->reschedule_waiters();
2967   mysql_prlock_unlock(&m_lock->m_rwlock);
2968 }
2969 
2970 
2971 /**
2972   Auxiliary function which allows to check if we have some kind of lock on
2973   a object. Returns TRUE if we have a lock of a given or stronger type.
2974 
2975   @param mdl_namespace Id of object namespace
2976   @param db            Name of the database
2977   @param name          Name of the object
2978   @param mdl_type      Lock type. Pass in the weakest type to find
2979                        out if there is at least some lock.
2980 
2981   @return TRUE if current context contains satisfied lock for the object,
2982           FALSE otherwise.
2983 */
2984 
2985 bool
is_lock_owner(MDL_key::enum_mdl_namespace mdl_namespace,const char * db,const char * name,enum_mdl_type mdl_type)2986 MDL_context::is_lock_owner(MDL_key::enum_mdl_namespace mdl_namespace,
2987                            const char *db, const char *name,
2988                            enum_mdl_type mdl_type)
2989 {
2990   MDL_request mdl_request;
2991   enum_mdl_duration not_unused;
2992   /* We don't care about exact duration of lock here. */
2993   mdl_request.init(mdl_namespace, db, name, mdl_type, MDL_TRANSACTION);
2994   MDL_ticket *ticket= find_ticket(&mdl_request, &not_unused);
2995 
2996   DBUG_ASSERT(ticket == NULL || ticket->m_lock);
2997 
2998   return ticket;
2999 }
3000 
3001 
3002 /**
3003   Return thread id of the owner of the lock or 0 if
3004   there is no owner.
3005   @note: Lock type is not considered at all, the function
3006   simply checks that there is some lock for the given key.
3007 
3008   @return  thread id of the owner of the lock or 0
3009 */
3010 
3011 unsigned long
get_lock_owner(MDL_key * key)3012 MDL_context::get_lock_owner(MDL_key *key)
3013 {
3014   fix_pins();
3015   return mdl_locks.get_lock_owner(m_pins, key);
3016 }
3017 
3018 
3019 /**
3020   Check if we have any pending locks which conflict with existing shared lock.
3021 
3022   @pre The ticket must match an acquired lock.
3023 
3024   @return TRUE if there is a conflicting lock request, FALSE otherwise.
3025 */
3026 
has_pending_conflicting_lock() const3027 bool MDL_ticket::has_pending_conflicting_lock() const
3028 {
3029   return m_lock->has_pending_conflicting_lock(m_type);
3030 }
3031 
3032 /** Return a key identifying this lock. */
get_key() const3033 MDL_key *MDL_ticket::get_key() const
3034 {
3035         return &m_lock->key;
3036 }
3037 
3038 /**
3039   Releases metadata locks that were acquired after a specific savepoint.
3040 
3041   @note Used to release tickets acquired during a savepoint unit.
3042   @note It's safe to iterate and unlock any locks after taken after this
3043         savepoint because other statements that take other special locks
3044         cause a implicit commit (ie LOCK TABLES).
3045 */
3046 
rollback_to_savepoint(const MDL_savepoint & mdl_savepoint)3047 void MDL_context::rollback_to_savepoint(const MDL_savepoint &mdl_savepoint)
3048 {
3049   DBUG_ENTER("MDL_context::rollback_to_savepoint");
3050 
3051   /* If savepoint is NULL, it is from the start of the transaction. */
3052   release_locks_stored_before(MDL_STATEMENT, mdl_savepoint.m_stmt_ticket);
3053   release_locks_stored_before(MDL_TRANSACTION, mdl_savepoint.m_trans_ticket);
3054 
3055   DBUG_VOID_RETURN;
3056 }
3057 
3058 
3059 /**
3060   Release locks acquired by normal statements (SELECT, UPDATE,
3061   DELETE, etc) in the course of a transaction. Do not release
3062   HANDLER locks, if there are any.
3063 
3064   This method is used at the end of a transaction, in
3065   implementation of COMMIT (implicit or explicit) and ROLLBACK.
3066 */
3067 
release_transactional_locks(THD * thd)3068 void MDL_context::release_transactional_locks(THD *thd)
3069 {
3070   DBUG_ENTER("MDL_context::release_transactional_locks");
3071   /* Fail if there are active transactions */
3072   DBUG_ASSERT(!(thd->server_status &
3073                 (SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY)));
3074   release_locks_stored_before(MDL_STATEMENT, NULL);
3075   release_locks_stored_before(MDL_TRANSACTION, NULL);
3076   DBUG_VOID_RETURN;
3077 }
3078 
release_statement_locks()3079 void MDL_context::release_statement_locks()
3080 {
3081   DBUG_ENTER("MDL_context::release_transactional_locks");
3082   release_locks_stored_before(MDL_STATEMENT, NULL);
3083   DBUG_VOID_RETURN;
3084 }
3085 
3086 
3087 /**
3088   Does this savepoint have this lock?
3089 
3090   @retval TRUE  The ticket is older than the savepoint or
3091                 is an LT, HA or GLR ticket. Thus it belongs
3092                 to the savepoint or has explicit duration.
3093   @retval FALSE The ticket is newer than the savepoint.
3094                 and is not an LT, HA or GLR ticket.
3095 */
3096 
has_lock(const MDL_savepoint & mdl_savepoint,MDL_ticket * mdl_ticket)3097 bool MDL_context::has_lock(const MDL_savepoint &mdl_savepoint,
3098                            MDL_ticket *mdl_ticket)
3099 {
3100   MDL_ticket *ticket;
3101   /* Start from the beginning, most likely mdl_ticket's been just acquired. */
3102   MDL_context::Ticket_iterator s_it(m_tickets[MDL_STATEMENT]);
3103   MDL_context::Ticket_iterator t_it(m_tickets[MDL_TRANSACTION]);
3104 
3105   while ((ticket= s_it++) && ticket != mdl_savepoint.m_stmt_ticket)
3106   {
3107     if (ticket == mdl_ticket)
3108       return FALSE;
3109   }
3110 
3111   while ((ticket= t_it++) && ticket != mdl_savepoint.m_trans_ticket)
3112   {
3113     if (ticket == mdl_ticket)
3114       return FALSE;
3115   }
3116   return TRUE;
3117 }
3118 
3119 
3120 /**
3121   Change lock duration for transactional lock.
3122 
3123   @param ticket   Ticket representing lock.
3124   @param duration Lock duration to be set.
3125 
3126   @note This method only supports changing duration of
3127         transactional lock to some other duration.
3128 */
3129 
set_lock_duration(MDL_ticket * mdl_ticket,enum_mdl_duration duration)3130 void MDL_context::set_lock_duration(MDL_ticket *mdl_ticket,
3131                                     enum_mdl_duration duration)
3132 {
3133   DBUG_SLOW_ASSERT(mdl_ticket->m_duration == MDL_TRANSACTION &&
3134                    duration != MDL_TRANSACTION);
3135 
3136   m_tickets[MDL_TRANSACTION].remove(mdl_ticket);
3137   m_tickets[duration].push_front(mdl_ticket);
3138 #ifndef DBUG_OFF
3139   mdl_ticket->m_duration= duration;
3140 #endif
3141 }
3142 
3143 
3144 /**
3145   Set explicit duration for all locks in the context.
3146 */
3147 
set_explicit_duration_for_all_locks()3148 void MDL_context::set_explicit_duration_for_all_locks()
3149 {
3150   int i;
3151   MDL_ticket *ticket;
3152 
3153   /*
3154     In the most common case when this function is called list
3155     of transactional locks is bigger than list of locks with
3156     explicit duration. So we start by swapping these two lists
3157     and then move elements from new list of transactional
3158     locks and list of statement locks to list of locks with
3159     explicit duration.
3160   */
3161 
3162   m_tickets[MDL_EXPLICIT].swap(m_tickets[MDL_TRANSACTION]);
3163 
3164   for (i= 0; i < MDL_EXPLICIT; i++)
3165   {
3166     Ticket_iterator it_ticket(m_tickets[i]);
3167 
3168     while ((ticket= it_ticket++))
3169     {
3170       m_tickets[i].remove(ticket);
3171       m_tickets[MDL_EXPLICIT].push_front(ticket);
3172     }
3173   }
3174 
3175 #ifndef DBUG_OFF
3176   Ticket_iterator exp_it(m_tickets[MDL_EXPLICIT]);
3177 
3178   while ((ticket= exp_it++))
3179     ticket->m_duration= MDL_EXPLICIT;
3180 #endif
3181 }
3182 
3183 
3184 /**
3185   Set transactional duration for all locks in the context.
3186 */
3187 
set_transaction_duration_for_all_locks()3188 void MDL_context::set_transaction_duration_for_all_locks()
3189 {
3190   MDL_ticket *ticket;
3191 
3192   /*
3193     In the most common case when this function is called list
3194     of explicit locks is bigger than two other lists (in fact,
3195     list of statement locks is always empty). So we start by
3196     swapping list of explicit and transactional locks and then
3197     move contents of new list of explicit locks to list of
3198     locks with transactional duration.
3199   */
3200 
3201   DBUG_ASSERT(m_tickets[MDL_STATEMENT].is_empty());
3202 
3203   m_tickets[MDL_TRANSACTION].swap(m_tickets[MDL_EXPLICIT]);
3204 
3205   Ticket_iterator it_ticket(m_tickets[MDL_EXPLICIT]);
3206 
3207   while ((ticket= it_ticket++))
3208   {
3209     m_tickets[MDL_EXPLICIT].remove(ticket);
3210     m_tickets[MDL_TRANSACTION].push_front(ticket);
3211   }
3212 
3213 #ifndef DBUG_OFF
3214   Ticket_iterator trans_it(m_tickets[MDL_TRANSACTION]);
3215 
3216   while ((ticket= trans_it++))
3217     ticket->m_duration= MDL_TRANSACTION;
3218 #endif
3219 }
3220 
3221 
3222 
release_explicit_locks()3223 void MDL_context::release_explicit_locks()
3224 {
3225   release_locks_stored_before(MDL_EXPLICIT, NULL);
3226 }
3227 
has_explicit_locks()3228 bool MDL_context::has_explicit_locks()
3229 {
3230   MDL_ticket *ticket = NULL;
3231 
3232   Ticket_iterator it(m_tickets[MDL_EXPLICIT]);
3233 
3234   while ((ticket = it++))
3235   {
3236     return true;
3237   }
3238 
3239   return false;
3240 }
3241 
3242 #ifdef WITH_WSREP
3243 static
wsrep_get_mdl_namespace_name(MDL_key::enum_mdl_namespace ns)3244 const char *wsrep_get_mdl_namespace_name(MDL_key::enum_mdl_namespace ns)
3245 {
3246   switch (ns)
3247   {
3248   case MDL_key::BACKUP    : return "BACKUP";
3249   case MDL_key::SCHEMA    : return "SCHEMA";
3250   case MDL_key::TABLE     : return "TABLE";
3251   case MDL_key::FUNCTION  : return "FUNCTION";
3252   case MDL_key::PROCEDURE : return "PROCEDURE";
3253   case MDL_key::PACKAGE_BODY: return "PACKAGE BODY";
3254   case MDL_key::TRIGGER   : return "TRIGGER";
3255   case MDL_key::EVENT     : return "EVENT";
3256   case MDL_key::USER_LOCK : return "USER_LOCK";
3257   default: break;
3258   }
3259   return "UNKNOWN";
3260 }
3261 
wsrep_report(bool debug)3262 void MDL_ticket::wsrep_report(bool debug)
3263 {
3264   if (!debug) return;
3265 
3266   const PSI_stage_info *psi_stage= m_lock->key.get_wait_state_name();
3267   WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)",
3268               get_type_name()->str,
3269               wsrep_get_mdl_namespace_name(m_lock->key.mdl_namespace()),
3270               m_lock->key.db_name(),
3271               m_lock->key.name(),
3272               psi_stage->m_name);
3273 }
3274 #endif /* WITH_WSREP */
3275