My Project
mdl.h
00001 #ifndef MDL_H
00002 #define MDL_H
00003 /* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; version 2 of the License.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012    GNU General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; if not, write to the Free Software Foundation,
00016    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00017 
00018 #if defined(__IBMC__) || defined(__IBMCPP__)
00019 /* Further down, "next_in_lock" and "next_in_context" have the same type,
00020    and in "sql_plist.h" this leads to an identical signature, which causes
00021    problems in function overloading.
00022 */
00023 #pragma namemangling(v5)
00024 #endif
00025 
00026 
00027 #include "sql_plist.h"
00028 #include <my_sys.h>
00029 #include <m_string.h>
00030 #include <mysql_com.h>
00031 
00032 #include <algorithm>
00033 
00034 class THD;
00035 
00036 class MDL_context;
00037 class MDL_lock;
00038 class MDL_ticket;
00039 
00049 #define ENTER_COND(C, M, S, O) enter_cond(C, M, S, O, __func__, __FILE__, __LINE__)
00050 
00056 #define EXIT_COND(S) exit_cond(S, __func__, __FILE__, __LINE__)
00057 
00063 class MDL_context_owner
00064 {
00065 public:
00066   virtual ~MDL_context_owner() {}
00067 
00083   virtual void enter_cond(mysql_cond_t *cond, mysql_mutex_t *mutex,
00084                           const PSI_stage_info *stage, PSI_stage_info *old_stage,
00085                           const char *src_function, const char *src_file,
00086                           int src_line) = 0;
00087 
00098   virtual void exit_cond(const PSI_stage_info *stage,
00099                          const char *src_function, const char *src_file,
00100                          int src_line) = 0;
00104   virtual int  is_killed() = 0;
00105 
00110   virtual THD* get_thd() = 0;
00111 
00115   virtual bool notify_shared_lock(MDL_context_owner *in_use,
00116                                   bool needs_thr_lock_abort) = 0;
00117 };
00118 
00126 enum enum_mdl_type {
00127   /*
00128     An intention exclusive metadata lock. Used only for scoped locks.
00129     Owner of this type of lock can acquire upgradable exclusive locks on
00130     individual objects.
00131     Compatible with other IX locks, but is incompatible with scoped S and
00132     X locks.
00133   */
00134   MDL_INTENTION_EXCLUSIVE= 0,
00135   /*
00136     A shared metadata lock.
00137     To be used in cases when we are interested in object metadata only
00138     and there is no intention to access object data (e.g. for stored
00139     routines or during preparing prepared statements).
00140     We also mis-use this type of lock for open HANDLERs, since lock
00141     acquired by this statement has to be compatible with lock acquired
00142     by LOCK TABLES ... WRITE statement, i.e. SNRW (We can't get by by
00143     acquiring S lock at HANDLER ... OPEN time and upgrading it to SR
00144     lock for HANDLER ... READ as it doesn't solve problem with need
00145     to abort DML statements which wait on table level lock while having
00146     open HANDLER in the same connection).
00147     To avoid deadlock which may occur when SNRW lock is being upgraded to
00148     X lock for table on which there is an active S lock which is owned by
00149     thread which waits in its turn for table-level lock owned by thread
00150     performing upgrade we have to use thr_abort_locks_for_thread()
00151     facility in such situation.
00152     This problem does not arise for locks on stored routines as we don't
00153     use SNRW locks for them. It also does not arise when S locks are used
00154     during PREPARE calls as table-level locks are not acquired in this
00155     case.
00156   */
00157   MDL_SHARED,
00158   /*
00159     A high priority shared metadata lock.
00160     Used for cases when there is no intention to access object data (i.e.
00161     data in the table).
00162     "High priority" means that, unlike other shared locks, it is granted
00163     ignoring pending requests for exclusive locks. Intended for use in
00164     cases when we only need to access metadata and not data, e.g. when
00165     filling an INFORMATION_SCHEMA table.
00166     Since SH lock is compatible with SNRW lock, the connection that
00167     holds SH lock lock should not try to acquire any kind of table-level
00168     or row-level lock, as this can lead to a deadlock. Moreover, after
00169     acquiring SH lock, the connection should not wait for any other
00170     resource, as it might cause starvation for X locks and a potential
00171     deadlock during upgrade of SNW or SNRW to X lock (e.g. if the
00172     upgrading connection holds the resource that is being waited for).
00173   */
00174   MDL_SHARED_HIGH_PRIO,
00175   /*
00176     A shared metadata lock for cases when there is an intention to read data
00177     from table.
00178     A connection holding this kind of lock can read table metadata and read
00179     table data (after acquiring appropriate table and row-level locks).
00180     This means that one can only acquire TL_READ, TL_READ_NO_INSERT, and
00181     similar table-level locks on table if one holds SR MDL lock on it.
00182     To be used for tables in SELECTs, subqueries, and LOCK TABLE ...  READ
00183     statements.
00184   */
00185   MDL_SHARED_READ,
00186   /*
00187     A shared metadata lock for cases when there is an intention to modify
00188     (and not just read) data in the table.
00189     A connection holding SW lock can read table metadata and modify or read
00190     table data (after acquiring appropriate table and row-level locks).
00191     To be used for tables to be modified by INSERT, UPDATE, DELETE
00192     statements, but not LOCK TABLE ... WRITE or DDL). Also taken by
00193     SELECT ... FOR UPDATE.
00194   */
00195   MDL_SHARED_WRITE,
00196   /*
00197     An upgradable shared metadata lock for cases when there is an intention
00198     to modify (and not just read) data in the table.
00199     Can be upgraded to MDL_SHARED_NO_WRITE and MDL_EXCLUSIVE.
00200     A connection holding SU lock can read table metadata and modify or read
00201     table data (after acquiring appropriate table and row-level locks).
00202     To be used for the first phase of ALTER TABLE.
00203   */
00204   MDL_SHARED_UPGRADABLE,
00205   /*
00206     An upgradable shared metadata lock which blocks all attempts to update
00207     table data, allowing reads.
00208     A connection holding this kind of lock can read table metadata and read
00209     table data.
00210     Can be upgraded to X metadata lock.
00211     Note, that since this type of lock is not compatible with SNRW or SW
00212     lock types, acquiring appropriate engine-level locks for reading
00213     (TL_READ* for MyISAM, shared row locks in InnoDB) should be
00214     contention-free.
00215     To be used for the first phase of ALTER TABLE, when copying data between
00216     tables, to allow concurrent SELECTs from the table, but not UPDATEs.
00217   */
00218   MDL_SHARED_NO_WRITE,
00219   /*
00220     An upgradable shared metadata lock which allows other connections
00221     to access table metadata, but not data.
00222     It blocks all attempts to read or update table data, while allowing
00223     INFORMATION_SCHEMA and SHOW queries.
00224     A connection holding this kind of lock can read table metadata modify and
00225     read table data.
00226     Can be upgraded to X metadata lock.
00227     To be used for LOCK TABLES WRITE statement.
00228     Not compatible with any other lock type except S and SH.
00229   */
00230   MDL_SHARED_NO_READ_WRITE,
00231   /*
00232     An exclusive metadata lock.
00233     A connection holding this lock can modify both table's metadata and data.
00234     No other type of metadata lock can be granted while this lock is held.
00235     To be used for CREATE/DROP/RENAME TABLE statements and for execution of
00236     certain phases of other DDL statements.
00237   */
00238   MDL_EXCLUSIVE,
00239   /* This should be the last !!! */
00240   MDL_TYPE_END};
00241 
00242 
00245 enum enum_mdl_duration {
00250   MDL_STATEMENT= 0,
00255   MDL_TRANSACTION,
00260   MDL_EXPLICIT,
00261   /* This should be the last ! */
00262   MDL_DURATION_END };
00263 
00264 
00266 #define MAX_MDLKEY_LENGTH (1 + NAME_LEN + 1 + NAME_LEN + 1)
00267 
00268 
00278 class MDL_key
00279 {
00280 public:
00281 #ifdef HAVE_PSI_INTERFACE
00282   static void init_psi_keys();
00283 #endif
00284 
00300   enum enum_mdl_namespace { GLOBAL=0,
00301                             SCHEMA,
00302                             TABLE,
00303                             FUNCTION,
00304                             PROCEDURE,
00305                             TRIGGER,
00306                             EVENT,
00307                             COMMIT,
00308                             /* This should be the last ! */
00309                             NAMESPACE_END };
00310 
00311   const uchar *ptr() const { return (uchar*) m_ptr; }
00312   uint length() const { return m_length; }
00313 
00314   const char *db_name() const { return m_ptr + 1; }
00315   uint db_name_length() const { return m_db_name_length; }
00316 
00317   const char *name() const { return m_ptr + m_db_name_length + 2; }
00318   uint name_length() const { return m_length - m_db_name_length - 3; }
00319 
00320   enum_mdl_namespace mdl_namespace() const
00321   { return (enum_mdl_namespace)(m_ptr[0]); }
00322 
00334   void mdl_key_init(enum_mdl_namespace mdl_namespace,
00335                     const char *db, const char *name)
00336   {
00337     m_ptr[0]= (char) mdl_namespace;
00338     /*
00339       It is responsibility of caller to ensure that db and object names
00340       are not longer than NAME_LEN. Still we play safe and try to avoid
00341       buffer overruns.
00342     */
00343     DBUG_ASSERT(strlen(db) <= NAME_LEN && strlen(name) <= NAME_LEN);
00344     m_db_name_length= static_cast<uint16>(strmake(m_ptr + 1, db, NAME_LEN) -
00345                                           m_ptr - 1);
00346     m_length= static_cast<uint16>(strmake(m_ptr + m_db_name_length + 2, name,
00347                                           NAME_LEN) - m_ptr + 1);
00348   }
00349   void mdl_key_init(const MDL_key *rhs)
00350   {
00351     memcpy(m_ptr, rhs->m_ptr, rhs->m_length);
00352     m_length= rhs->m_length;
00353     m_db_name_length= rhs->m_db_name_length;
00354   }
00355   bool is_equal(const MDL_key *rhs) const
00356   {
00357     return (m_length == rhs->m_length &&
00358             memcmp(m_ptr, rhs->m_ptr, m_length) == 0);
00359   }
00363   int cmp(const MDL_key *rhs) const
00364   {
00365     /*
00366       The key buffer is always '\0'-terminated. Since key
00367       character set is utf-8, we can safely assume that no
00368       character starts with a zero byte.
00369     */
00370     using std::min;
00371     return memcmp(m_ptr, rhs->m_ptr, min(m_length, rhs->m_length));
00372   }
00373 
00374   MDL_key(const MDL_key *rhs)
00375   {
00376     mdl_key_init(rhs);
00377   }
00378   MDL_key(enum_mdl_namespace namespace_arg,
00379           const char *db_arg, const char *name_arg)
00380   {
00381     mdl_key_init(namespace_arg, db_arg, name_arg);
00382   }
00383   MDL_key() {} /* To use when part of MDL_request. */
00384 
00389   const PSI_stage_info * get_wait_state_name() const
00390   {
00391     return & m_namespace_to_wait_state_name[(int)mdl_namespace()];
00392   }
00393 
00394 private:
00395   uint16 m_length;
00396   uint16 m_db_name_length;
00397   char m_ptr[MAX_MDLKEY_LENGTH];
00398   static PSI_stage_info m_namespace_to_wait_state_name[NAMESPACE_END];
00399 private:
00400   MDL_key(const MDL_key &);                     /* not implemented */
00401   MDL_key &operator=(const MDL_key &);          /* not implemented */
00402 };
00403 
00404 
00418 class MDL_request
00419 {
00420 public:
00422   enum          enum_mdl_type type;
00424   enum enum_mdl_duration duration;
00425 
00429   MDL_request *next_in_list;
00430   MDL_request **prev_in_list;
00435   MDL_ticket *ticket;
00436 
00438   MDL_key key;
00439 
00440 public:
00441   static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
00442   { return alloc_root(mem_root, size); }
00443   static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
00444 
00445   void init(MDL_key::enum_mdl_namespace namespace_arg,
00446             const char *db_arg, const char *name_arg,
00447             enum_mdl_type mdl_type_arg,
00448             enum_mdl_duration mdl_duration_arg);
00449   void init(const MDL_key *key_arg, enum_mdl_type mdl_type_arg,
00450             enum_mdl_duration mdl_duration_arg);
00452   inline void set_type(enum_mdl_type type_arg)
00453   {
00454     DBUG_ASSERT(ticket == NULL);
00455     type= type_arg;
00456   }
00457 
00458   /*
00459     This is to work around the ugliness of TABLE_LIST
00460     compiler-generated assignment operator. It is currently used
00461     in several places to quickly copy "most" of the members of the
00462     table list. These places currently never assume that the mdl
00463     request is carried over to the new TABLE_LIST, or shared
00464     between lists.
00465 
00466     This method does not initialize the instance being assigned!
00467     Use of init() for initialization after this assignment operator
00468     is mandatory. Can only be used before the request has been
00469     granted.
00470   */
00471   MDL_request& operator=(const MDL_request &rhs)
00472   {
00473     ticket= NULL;
00474     /* Do nothing, in particular, don't try to copy the key. */
00475     return *this;
00476   }
00477   /* Another piece of ugliness for TABLE_LIST constructor */
00478   MDL_request() {}
00479 
00480   MDL_request(const MDL_request *rhs)
00481     :type(rhs->type),
00482     duration(rhs->duration),
00483     ticket(NULL),
00484     key(&rhs->key)
00485   {}
00486 };
00487 
00488 
00489 typedef void (*mdl_cached_object_release_hook)(void *);
00490 
00491 
00497 class MDL_wait_for_graph_visitor
00498 {
00499 public:
00500   virtual bool enter_node(MDL_context *node) = 0;
00501   virtual void leave_node(MDL_context *node) = 0;
00502 
00503   virtual bool inspect_edge(MDL_context *dest) = 0;
00504   virtual ~MDL_wait_for_graph_visitor();
00505   MDL_wait_for_graph_visitor() :m_lock_open_count(0) {}
00506 public:
00515   uint m_lock_open_count;
00516 };
00517 
00523 class MDL_wait_for_subgraph
00524 {
00525 public:
00526   virtual ~MDL_wait_for_subgraph();
00527 
00532   virtual bool accept_visitor(MDL_wait_for_graph_visitor *gvisitor) = 0;
00533 
00534   enum enum_deadlock_weight
00535   {
00536     DEADLOCK_WEIGHT_DML= 0,
00537     DEADLOCK_WEIGHT_DDL= 100
00538   };
00539   /* A helper used to determine which lock request should be aborted. */
00540   virtual uint get_deadlock_weight() const = 0;
00541 };
00542 
00543 
00564 class MDL_ticket : public MDL_wait_for_subgraph
00565 {
00566 public:
00571   MDL_ticket *next_in_context;
00572   MDL_ticket **prev_in_context;
00577   MDL_ticket *next_in_lock;
00578   MDL_ticket **prev_in_lock;
00579 public:
00580   bool has_pending_conflicting_lock() const;
00581 
00582   MDL_context *get_ctx() const { return m_ctx; }
00583   bool is_upgradable_or_exclusive() const
00584   {
00585     return m_type == MDL_SHARED_UPGRADABLE ||
00586            m_type == MDL_SHARED_NO_WRITE ||
00587            m_type == MDL_SHARED_NO_READ_WRITE ||
00588            m_type == MDL_EXCLUSIVE;
00589   }
00590   enum_mdl_type get_type() const { return m_type; }
00591   MDL_lock *get_lock() const { return m_lock; }
00592   void downgrade_lock(enum_mdl_type type);
00593 
00594   bool has_stronger_or_equal_type(enum_mdl_type type) const;
00595 
00596   bool is_incompatible_when_granted(enum_mdl_type type) const;
00597   bool is_incompatible_when_waiting(enum_mdl_type type) const;
00598 
00600   virtual bool accept_visitor(MDL_wait_for_graph_visitor *dvisitor);
00601   virtual uint get_deadlock_weight() const;
00602 private:
00603   friend class MDL_context;
00604 
00605   MDL_ticket(MDL_context *ctx_arg, enum_mdl_type type_arg
00606 #ifndef DBUG_OFF
00607              , enum_mdl_duration duration_arg
00608 #endif
00609             )
00610    : m_type(type_arg),
00611 #ifndef DBUG_OFF
00612      m_duration(duration_arg),
00613 #endif
00614      m_ctx(ctx_arg),
00615      m_lock(NULL)
00616   {}
00617 
00618   static MDL_ticket *create(MDL_context *ctx_arg, enum_mdl_type type_arg
00619 #ifndef DBUG_OFF
00620                             , enum_mdl_duration duration_arg
00621 #endif
00622                             );
00623   static void destroy(MDL_ticket *ticket);
00624 private:
00626   enum enum_mdl_type m_type;
00627 #ifndef DBUG_OFF
00628 
00632   enum_mdl_duration m_duration;
00633 #endif
00634 
00637   MDL_context *m_ctx;
00638 
00642   MDL_lock *m_lock;
00643 
00644 private:
00645   MDL_ticket(const MDL_ticket &);               /* not implemented */
00646   MDL_ticket &operator=(const MDL_ticket &);    /* not implemented */
00647 };
00648 
00649 
00657 class MDL_savepoint
00658 {
00659 public:
00660   MDL_savepoint() {};
00661 
00662 private:
00663   MDL_savepoint(MDL_ticket *stmt_ticket, MDL_ticket *trans_ticket)
00664     : m_stmt_ticket(stmt_ticket), m_trans_ticket(trans_ticket)
00665   {}
00666 
00667   friend class MDL_context;
00668 
00669 private:
00674   MDL_ticket *m_stmt_ticket;
00679   MDL_ticket *m_trans_ticket;
00680 };
00681 
00682 
00687 class MDL_wait
00688 {
00689 public:
00690   MDL_wait();
00691   ~MDL_wait();
00692 
00693   enum enum_wait_status { EMPTY = 0, GRANTED, VICTIM, TIMEOUT, KILLED };
00694 
00695   bool set_status(enum_wait_status result_arg);
00696   enum_wait_status get_status();
00697   void reset_status();
00698   enum_wait_status timed_wait(MDL_context_owner *owner,
00699                               struct timespec *abs_timeout,
00700                               bool signal_timeout,
00701                               const PSI_stage_info *wait_state_name);
00702 private:
00710   mysql_mutex_t m_LOCK_wait_status;
00711   mysql_cond_t m_COND_wait_status;
00712   enum_wait_status m_wait_status;
00713 };
00714 
00715 
00716 typedef I_P_List<MDL_request, I_P_List_adapter<MDL_request,
00717                  &MDL_request::next_in_list,
00718                  &MDL_request::prev_in_list>,
00719                  I_P_List_counter>
00720         MDL_request_list;
00721 
00727 class MDL_context
00728 {
00729 public:
00730   typedef I_P_List<MDL_ticket,
00731                    I_P_List_adapter<MDL_ticket,
00732                                     &MDL_ticket::next_in_context,
00733                                     &MDL_ticket::prev_in_context> >
00734           Ticket_list;
00735 
00736   typedef Ticket_list::Iterator Ticket_iterator;
00737 
00738   MDL_context();
00739   void destroy();
00740 
00741   bool try_acquire_lock(MDL_request *mdl_request);
00742   bool acquire_lock(MDL_request *mdl_request, ulong lock_wait_timeout);
00743   bool acquire_locks(MDL_request_list *requests, ulong lock_wait_timeout);
00744   bool upgrade_shared_lock(MDL_ticket *mdl_ticket,
00745                            enum_mdl_type new_type,
00746                            ulong lock_wait_timeout);
00747 
00748   bool clone_ticket(MDL_request *mdl_request);
00749 
00750   void release_all_locks_for_name(MDL_ticket *ticket);
00751   void release_lock(MDL_ticket *ticket);
00752 
00753   bool is_lock_owner(MDL_key::enum_mdl_namespace mdl_namespace,
00754                      const char *db, const char *name,
00755                      enum_mdl_type mdl_type);
00756 
00757   bool has_lock(const MDL_savepoint &mdl_savepoint, MDL_ticket *mdl_ticket);
00758 
00759   inline bool has_locks() const
00760   {
00761     return !(m_tickets[MDL_STATEMENT].is_empty() &&
00762              m_tickets[MDL_TRANSACTION].is_empty() &&
00763              m_tickets[MDL_EXPLICIT].is_empty());
00764   }
00765 
00766   MDL_savepoint mdl_savepoint()
00767   {
00768     return MDL_savepoint(m_tickets[MDL_STATEMENT].front(),
00769                          m_tickets[MDL_TRANSACTION].front());
00770   }
00771 
00772   void set_explicit_duration_for_all_locks();
00773   void set_transaction_duration_for_all_locks();
00774   void set_lock_duration(MDL_ticket *mdl_ticket, enum_mdl_duration duration);
00775 
00776   void release_statement_locks();
00777   void release_transactional_locks();
00778   void rollback_to_savepoint(const MDL_savepoint &mdl_savepoint);
00779 
00780   MDL_context_owner *get_owner() { return m_owner; }
00781 
00783   inline uint get_deadlock_weight() const
00784   { return m_waiting_for->get_deadlock_weight(); }
00793   void init(MDL_context_owner *arg) { m_owner= arg; }
00794 
00795   void set_needs_thr_lock_abort(bool needs_thr_lock_abort)
00796   {
00797     /*
00798       @note In theory, this member should be modified under protection
00799             of some lock since it can be accessed from different threads.
00800             In practice, this is not necessary as code which reads this
00801             value and so might miss the fact that value was changed will
00802             always re-try reading it after small timeout and therefore
00803             will see the new value eventually.
00804     */
00805     m_needs_thr_lock_abort= needs_thr_lock_abort;
00806   }
00807   bool get_needs_thr_lock_abort() const
00808   {
00809     return m_needs_thr_lock_abort;
00810   }
00811 public:
00816   MDL_wait m_wait;
00817 private:
00872   Ticket_list m_tickets[MDL_DURATION_END];
00873   MDL_context_owner *m_owner;
00883   bool m_needs_thr_lock_abort;
00884 
00892   mysql_prlock_t m_LOCK_waiting_for;
00900   MDL_wait_for_subgraph *m_waiting_for;
00901 private:
00902   THD *get_thd() const { return m_owner->get_thd(); }
00903   MDL_ticket *find_ticket(MDL_request *mdl_req,
00904                           enum_mdl_duration *duration);
00905   void release_locks_stored_before(enum_mdl_duration duration, MDL_ticket *sentinel);
00906   void release_lock(enum_mdl_duration duration, MDL_ticket *ticket);
00907   bool try_acquire_lock_impl(MDL_request *mdl_request,
00908                              MDL_ticket **out_ticket);
00909 
00910 public:
00911   void find_deadlock();
00912 
00913   bool visit_subgraph(MDL_wait_for_graph_visitor *dvisitor);
00914 
00916   void will_wait_for(MDL_wait_for_subgraph *waiting_for_arg)
00917   {
00918     mysql_prlock_wrlock(&m_LOCK_waiting_for);
00919     m_waiting_for=  waiting_for_arg;
00920     mysql_prlock_unlock(&m_LOCK_waiting_for);
00921   }
00922 
00924   void done_waiting_for()
00925   {
00926     mysql_prlock_wrlock(&m_LOCK_waiting_for);
00927     m_waiting_for= NULL;
00928     mysql_prlock_unlock(&m_LOCK_waiting_for);
00929   }
00930   void lock_deadlock_victim()
00931   {
00932     mysql_prlock_rdlock(&m_LOCK_waiting_for);
00933   }
00934   void unlock_deadlock_victim()
00935   {
00936     mysql_prlock_unlock(&m_LOCK_waiting_for);
00937   }
00938 private:
00939   MDL_context(const MDL_context &rhs);          /* not implemented */
00940   MDL_context &operator=(MDL_context &rhs);     /* not implemented */
00941 };
00942 
00943 
00944 void mdl_init();
00945 void mdl_destroy();
00946 
00947 
00948 #ifndef DBUG_OFF
00949 extern mysql_mutex_t LOCK_open;
00950 #endif
00951 
00952 
00953 /*
00954   Start-up parameter for the maximum size of the unused MDL_lock objects cache
00955   and a constant for its default value.
00956 */
00957 extern ulong mdl_locks_cache_size;
00958 static const ulong MDL_LOCKS_CACHE_SIZE_DEFAULT = 1024;
00959 
00960 /*
00961   Start-up parameter for the number of partitions of the hash
00962   containing all the MDL_lock objects and a constant for
00963   its default value.
00964 */
00965 extern ulong mdl_locks_hash_partitions;
00966 static const ulong MDL_LOCKS_HASH_PARTITIONS_DEFAULT = 8;
00967 
00968 /*
00969   Metadata locking subsystem tries not to grant more than
00970   max_write_lock_count high-prio, strong locks successively,
00971   to avoid starving out weak, low-prio locks.
00972 */
00973 extern "C" ulong max_write_lock_count;
00974 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines