summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/ha_ndbcluster_binlog.cc2
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/mdl.cc136
-rw-r--r--sql/mdl.h19
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/sql_base.cc8
-rw-r--r--sql/sql_handler.cc2
-rw-r--r--sql/sql_show.cc4
8 files changed, 120 insertions, 55 deletions
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index 6f0e4498d75..b9ea87aec52 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -141,7 +141,7 @@ static Uint64 *p_latest_trans_gci= 0;
static TABLE *ndb_binlog_index= 0;
static TABLE_LIST binlog_tables;
static MDL_LOCK_DATA binlog_mdl_lock_data;
-static char binlog_mdlkey[MAX_DBKEY_LENGTH];
+static char binlog_mdlkey[MAX_MDLKEY_LENGTH];
/*
Helper functions
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 92de9933181..b3f6fd58f1a 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -8074,7 +8074,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
&db_mem, (uint) NAME_LEN + 1,
&tname_mem, (uint) NAME_LEN + 1,
&mdl_lock_data, sizeof(MDL_LOCK_DATA),
- &mdlkey, MAX_DBKEY_LENGTH,
+ &mdlkey, MAX_MDLKEY_LENGTH,
NullS)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
diff --git a/sql/mdl.cc b/sql/mdl.cc
index afe3f0eaa7b..0a663ad2e11 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -15,13 +15,9 @@
-/*
- TODO: Remove this dependency on mysql_priv.h. It's not
- trivial step at the moment since currently we access to
- some of THD members and use some of its methods here.
-*/
-#include "mysql_priv.h"
#include "mdl.h"
+#include <hash.h>
+#include <mysqld_error.h>
/**
@@ -308,7 +304,7 @@ MDL_LOCK_DATA *mdl_alloc_lock(int type, const char *db, const char *name,
char *key;
if (!multi_alloc_root(root, &lock_data, sizeof(MDL_LOCK_DATA), &key,
- MAX_DBKEY_LENGTH, NULL))
+ MAX_MDLKEY_LENGTH, NULL))
return NULL;
mdl_init_lock(lock_data, key, type, db, name);
@@ -442,6 +438,58 @@ static bool is_shared(MDL_LOCK_DATA *lock_data)
/**
+ Helper functions and macros to be used for killable waiting in metadata
+ locking subsystem.
+
+ @sa THD::enter_cond()/exit_cond()/killed.
+
+ @note We can't use THD::enter_cond()/exit_cond()/killed directly here
+ since this will make metadata subsystem dependant on THD class
+ and thus prevent us from writing unit tests for it. And usage of
+ wrapper functions to access THD::killed/enter_cond()/exit_cond()
+ will probably introduce too much overhead.
+*/
+
+#define MDL_ENTER_COND(A, B) mdl_enter_cond(A, B, __func__, __FILE__, __LINE__)
+
+static inline const char* mdl_enter_cond(MDL_CONTEXT *context,
+ st_my_thread_var *mysys_var,
+ const char *calling_func,
+ const char *calling_file,
+ const unsigned int calling_line)
+{
+ safe_mutex_assert_owner(&LOCK_mdl);
+
+ mysys_var->current_mutex= &LOCK_mdl;
+ mysys_var->current_cond= &COND_mdl;
+
+ return set_thd_proc_info(context->thd, "Waiting for table",
+ calling_func, calling_file, calling_line);
+}
+
+#define MDL_EXIT_COND(A, B, C) mdl_exit_cond(A, B, C, __func__, __FILE__, __LINE__)
+
+static inline void mdl_exit_cond(MDL_CONTEXT *context,
+ st_my_thread_var *mysys_var,
+ const char* old_msg,
+ const char *calling_func,
+ const char *calling_file,
+ const unsigned int calling_line)
+{
+ DBUG_ASSERT(&LOCK_mdl == mysys_var->current_mutex);
+
+ pthread_mutex_unlock(&LOCK_mdl);
+ pthread_mutex_lock(&mysys_var->mutex);
+ mysys_var->current_mutex= 0;
+ mysys_var->current_cond= 0;
+ pthread_mutex_unlock(&mysys_var->mutex);
+
+ (void) set_thd_proc_info(context->thd, old_msg, calling_func,
+ calling_file, calling_line);
+}
+
+
+/**
Check if request for the lock on particular object can be satisfied given
current state of the global metadata lock.
@@ -752,9 +800,7 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
bool signalled= FALSE;
const char *old_msg;
I_P_List_iterator<MDL_LOCK_DATA, MDL_LOCK_DATA_context> it(context->locks);
- THD *thd= context->thd;
-
- DBUG_ASSERT(thd == current_thd);
+ st_my_thread_var *mysys_var= my_thread_var;
safe_mutex_assert_not_owner(&LOCK_open);
@@ -766,7 +812,7 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
pthread_mutex_lock(&LOCK_mdl);
- old_msg= thd->enter_cond(&COND_mdl, &LOCK_mdl, "Waiting for table");
+ old_msg= MDL_ENTER_COND(context, mysys_var);
while ((lock_data= it++))
{
@@ -826,8 +872,11 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
!lock->active_shared_waiting_upgrade.is_empty();
while ((conf_lock_data= it++))
+ {
signalled|=
- notify_thread_having_shared_lock(thd, conf_lock_data->ctx->thd);
+ mysql_notify_thread_having_shared_lock(context->thd,
+ conf_lock_data->ctx->thd);
+ }
break;
}
@@ -848,7 +897,7 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
set_timespec(abstime, 10);
pthread_cond_timedwait(&COND_mdl, &LOCK_mdl, &abstime);
}
- if (thd->killed)
+ if (mysys_var->abort)
goto err;
}
it.rewind();
@@ -863,8 +912,8 @@ bool mdl_acquire_exclusive_locks(MDL_CONTEXT *context)
(*lock->cached_object_release_hook)(lock->cached_object);
lock->cached_object= NULL;
}
- /* As a side-effect THD::exit_cond() unlocks LOCK_mdl. */
- thd->exit_cond(old_msg);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(context, mysys_var, old_msg);
return FALSE;
err:
@@ -880,7 +929,7 @@ err:
}
/* May be some pending requests for shared locks can be satisfied now. */
pthread_cond_broadcast(&COND_mdl);
- thd->exit_cond(old_msg);
+ MDL_EXIT_COND(context, mysys_var, old_msg);
return TRUE;
}
@@ -907,12 +956,10 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
{
MDL_LOCK *lock;
const char *old_msg;
- THD *thd= context->thd;
+ st_my_thread_var *mysys_var= my_thread_var;
DBUG_ENTER("mdl_upgrade_shared_lock_to_exclusive");
- DBUG_ASSERT(thd == current_thd);
-
safe_mutex_assert_not_owner(&LOCK_open);
DBUG_ASSERT(lock_data->state == MDL_ACQUIRED);
@@ -927,7 +974,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
pthread_mutex_lock(&LOCK_mdl);
- old_msg= thd->enter_cond(&COND_mdl, &LOCK_mdl, "Waiting for table");
+ old_msg= MDL_ENTER_COND(context, mysys_var);
lock_data->state= MDL_PENDING_UPGRADE;
/* Set type of lock request to the type at which we are aiming. */
@@ -960,8 +1007,11 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
while ((conf_lock_data= it++))
{
if (conf_lock_data->ctx != context)
- signalled|= notify_thread_having_shared_lock(thd,
- conf_lock_data->ctx->thd);
+ {
+ signalled|=
+ mysql_notify_thread_having_shared_lock(context->thd,
+ conf_lock_data->ctx->thd);
+ }
}
if (signalled)
@@ -979,7 +1029,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
DBUG_PRINT("info", ("Failed to wake-up from table-level lock ... sleeping"));
pthread_cond_timedwait(&COND_mdl, &LOCK_mdl, &abstime);
}
- if (thd->killed)
+ if (mysys_var->abort)
{
lock_data->state= MDL_ACQUIRED;
lock_data->type= MDL_SHARED_UPGRADABLE;
@@ -987,7 +1037,7 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
lock->active_shared.push_front(lock_data);
/* Pending requests for shared locks can be satisfied now. */
pthread_cond_broadcast(&COND_mdl);
- thd->exit_cond(old_msg);
+ MDL_EXIT_COND(context, mysys_var, old_msg);
DBUG_RETURN(TRUE);
}
}
@@ -999,8 +1049,8 @@ bool mdl_upgrade_shared_lock_to_exclusive(MDL_CONTEXT *context,
(*lock->cached_object_release_hook)(lock->cached_object);
lock->cached_object= 0;
- /* As a side-effect THD::exit_cond() unlocks LOCK_mdl. */
- thd->exit_cond(old_msg);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(context, mysys_var, old_msg);
DBUG_RETURN(FALSE);
}
@@ -1086,32 +1136,31 @@ err:
bool mdl_acquire_global_shared_lock(MDL_CONTEXT *context)
{
- THD *thd= context->thd;
+ st_my_thread_var *mysys_var= my_thread_var;
const char *old_msg;
safe_mutex_assert_not_owner(&LOCK_open);
- DBUG_ASSERT(thd == current_thd);
DBUG_ASSERT(!context->has_global_shared_lock);
pthread_mutex_lock(&LOCK_mdl);
global_lock.waiting_shared++;
- old_msg= thd->enter_cond(&COND_mdl, &LOCK_mdl, "Waiting for table");
+ old_msg= MDL_ENTER_COND(context, mysys_var);
- while (!thd->killed && global_lock.active_intention_exclusive)
+ while (!mysys_var->abort && global_lock.active_intention_exclusive)
pthread_cond_wait(&COND_mdl, &LOCK_mdl);
global_lock.waiting_shared--;
- if (thd->killed)
+ if (mysys_var->abort)
{
- /* As a side-effect THD::exit_cond() unlocks LOCK_mdl. */
- thd->exit_cond(old_msg);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(context, mysys_var, old_msg);
return TRUE;
}
global_lock.active_shared++;
context->has_global_shared_lock= TRUE;
- /* As a side-effect THD::exit_cond() unlocks LOCK_mdl. */
- thd->exit_cond(old_msg);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(context, mysys_var, old_msg);
return FALSE;
}
@@ -1137,12 +1186,11 @@ bool mdl_wait_for_locks(MDL_CONTEXT *context)
MDL_LOCK *lock;
I_P_List_iterator<MDL_LOCK_DATA, MDL_LOCK_DATA_context> it(context->locks);
const char *old_msg;
- THD *thd= context->thd;
+ st_my_thread_var *mysys_var= my_thread_var;
safe_mutex_assert_not_owner(&LOCK_open);
- DBUG_ASSERT(thd == current_thd);
- while (!thd->killed)
+ while (!mysys_var->abort)
{
/*
We have to check if there are some HANDLERs open by this thread
@@ -1156,7 +1204,7 @@ bool mdl_wait_for_locks(MDL_CONTEXT *context)
*/
mysql_ha_flush(context->thd);
pthread_mutex_lock(&LOCK_mdl);
- old_msg= thd->enter_cond(&COND_mdl, &LOCK_mdl, "Waiting for table");
+ old_msg= MDL_ENTER_COND(context, mysys_var);
it.rewind();
while ((lock_data= it++))
{
@@ -1179,10 +1227,10 @@ bool mdl_wait_for_locks(MDL_CONTEXT *context)
break;
}
pthread_cond_wait(&COND_mdl, &LOCK_mdl);
- /* As a side-effect THD::exit_cond() unlocks LOCK_mdl. */
- thd->exit_cond(old_msg);
+ /* As a side-effect MDL_EXIT_COND() unlocks LOCK_mdl. */
+ MDL_EXIT_COND(context, mysys_var, old_msg);
}
- return thd->killed;
+ return mysys_var->abort;
}
@@ -1422,7 +1470,7 @@ void mdl_release_global_shared_lock(MDL_CONTEXT *context)
bool mdl_is_exclusive_lock_owner(MDL_CONTEXT *context, int type,
const char *db, const char *name)
{
- char key[MAX_DBKEY_LENGTH];
+ char key[MAX_MDLKEY_LENGTH];
uint key_length;
MDL_LOCK_DATA *lock_data;
I_P_List_iterator<MDL_LOCK_DATA, MDL_LOCK_DATA_context> it(context->locks);
@@ -1456,7 +1504,7 @@ bool mdl_is_exclusive_lock_owner(MDL_CONTEXT *context, int type,
bool mdl_is_lock_owner(MDL_CONTEXT *context, int type, const char *db,
const char *name)
{
- char key[MAX_DBKEY_LENGTH];
+ char key[MAX_MDLKEY_LENGTH];
uint key_length;
MDL_LOCK_DATA *lock_data;
I_P_List_iterator<MDL_LOCK_DATA, MDL_LOCK_DATA_context> it(context->locks);
diff --git a/sql/mdl.h b/sql/mdl.h
index 92bd83038e5..b4b84a9ab24 100644
--- a/sql/mdl.h
+++ b/sql/mdl.h
@@ -19,6 +19,7 @@
#include "sql_plist.h"
#include <my_sys.h>
#include <m_string.h>
+#include <mysql_com.h>
class THD;
@@ -148,6 +149,9 @@ void mdl_context_backup_and_reset(MDL_CONTEXT *ctx, MDL_CONTEXT *backup);
void mdl_context_restore(MDL_CONTEXT *ctx, MDL_CONTEXT *backup);
void mdl_context_merge(MDL_CONTEXT *target, MDL_CONTEXT *source);
+/** Maximal length of key for metadata locking subsystem. */
+#define MAX_MDLKEY_LENGTH (4 + NAME_LEN + 1 + NAME_LEN + 1)
+
void mdl_init_lock(MDL_LOCK_DATA *lock_data, char *key, int type,
const char *db, const char *name);
MDL_LOCK_DATA *mdl_alloc_lock(int type, const char *db, const char *name,
@@ -237,4 +241,19 @@ void* mdl_get_cached_object(MDL_LOCK_DATA *lock_data);
void mdl_set_cached_object(MDL_LOCK_DATA *lock_data, void *cached_object,
mdl_cached_object_release_hook release_hook);
+
+/*
+ Functions in the server's kernel used by metadata locking subsystem.
+*/
+
+extern bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use);
+extern void mysql_ha_flush(THD *thd);
+extern "C" const char *set_thd_proc_info(THD *thd, const char *info,
+ const char *calling_function,
+ const char *calling_file,
+ const unsigned int calling_line);
+#ifndef DBUG_OFF
+extern pthread_mutex_t LOCK_open;
+#endif
+
#endif
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 12d7e46e821..2f15ecb2b71 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1534,8 +1534,6 @@ char *generate_partition_syntax(partition_info *part_info,
Alter_info *alter_info);
#endif
-bool notify_thread_having_shared_lock(THD *thd, THD *in_use);
-
enum enum_tdc_remove_table_type {TDC_RT_REMOVE_ALL, TDC_RT_REMOVE_NOT_OWN,
TDC_RT_REMOVE_UNUSED};
void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6c344ad1d4e..7803bd0ba11 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1275,7 +1275,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
/*
We need to hold LOCK_open while changing the open_tables
list, since another thread may work on it.
- @sa notify_thread_having_shared_lock()
+ @sa mysql_notify_thread_having_shared_lock()
*/
pthread_mutex_lock(&LOCK_open);
@@ -1455,7 +1455,7 @@ void close_thread_tables(THD *thd,
/*
Note that we need to hold LOCK_open while changing the
open_tables list. Another thread may work on it.
- (See: notify_thread_having_shared_lock())
+ (See: mysql_notify_thread_having_shared_lock())
Closing a MERGE child before the parent would be fatal if the
other thread tries to abort the MERGE lock in between.
*/
@@ -7956,7 +7956,7 @@ void flush_tables()
rest of the server is broken.
*/
-bool notify_thread_having_shared_lock(THD *thd, THD *in_use)
+bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use)
{
bool signalled= FALSE;
if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
@@ -8501,7 +8501,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup)
/*
Note that we need to hold LOCK_open while changing the
open_tables list. Another thread may work on it.
- (See: notify_thread_having_shared_lock())
+ (See: mysql_notify_thread_having_shared_lock())
Closing a MERGE child before the parent would be fatal if the
other thread tries to abort the MERGE lock in between.
*/
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 9b30d8cec12..49d6cbaa447 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -247,7 +247,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
&name, (uint) namelen,
&alias, (uint) aliaslen,
&mdl_lock_data, sizeof(MDL_LOCK_DATA),
- &mdlkey, MAX_DBKEY_LENGTH,
+ &mdlkey, MAX_MDLKEY_LENGTH,
NullS)))
{
DBUG_PRINT("exit",("ERROR"));
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index c50d74412bf..a77ba6264a3 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -3084,7 +3084,7 @@ uint get_table_open_method(TABLE_LIST *tables,
@param mdlkey Pointer to the buffer for key for the lock request
(should be at least strlen(db) + strlen(name) + 2
bytes, or, if the lengths are not known,
- MAX_DBNAME_LENGTH)
+ MAX_MDLKEY_LENGTH)
@param table Table list element for the table
@note This is an auxiliary function to be used in cases when we want to
@@ -3157,7 +3157,7 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table,
uint key_length;
char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1];
MDL_LOCK_DATA mdl_lock_data;
- char mdlkey[MAX_DBKEY_LENGTH];
+ char mdlkey[MAX_MDLKEY_LENGTH];
bzero((char*) &table_list, sizeof(TABLE_LIST));
bzero((char*) &tbl, sizeof(TABLE));