summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorKonstantin Osipov <kostja@sun.com>2009-12-02 19:31:57 +0300
committerKonstantin Osipov <kostja@sun.com>2009-12-02 19:31:57 +0300
commit124cda8a0a783180b280935fd4b62a2b7d6dc6c4 (patch)
treec7cd519ccaa3357e48161f2c078f2e22c00d2e56 /sql
parente3b3907c4f6f6dbfd650272e7c65880d04e5789e (diff)
downloadmariadb-git-124cda8a0a783180b280935fd4b62a2b7d6dc6c4.tar.gz
Backport of:
------------------------------------------------------------ revno: 2630.4.33 committer: Dmitry Lenev <dlenev@mysql.com> branch nick: mysql-6.0-3726-w2 timestamp: Fri 2008-06-20 17:11:20 +0400 message: WL#3726 "DDL locking for all metadata objects". After-review fixes in progress. Minimized dependency of mdl.cc on other modules (particularly made it independant of mysql_priv.h) in order to be able write unit tests for metadata locking subsystem. sql/ha_ndbcluster_binlog.cc: Use newly introduced MAX_MDLKEY_LENGTH constant for allocating buffer for object key for metadata locking subsystem. sql/log_event.cc: Use newly introduced MAX_MDLKEY_LENGTH constant for allocating buffer for object key for metadata locking subsystem. sql/mdl.cc: Removed dependency on THD class (and thus on mysql_priv.h) by using direct access to members of st_my_thread_var instead of accessing THD::killed/enter_cond()/exit_cond(). sql/mdl.h: Added MAX_MDLKEY_LENGTH constant to be used for allocating buffers for key for metadata locking subsystem. Added declarations of server kernel functions used by metadata locking subsystem to mdl.h in order to decrease dependency of mdl.cc on other files. sql/mysql_priv.h: Moved declaration of notify_thread_having_shared_lock() to the mdl.h (also renamed it to make clear in metadata locking code that it is a callback to SQL-layer). sql/sql_base.cc: Renamed notify_thread_having_shared_lock() to make it clear in metadata locking subsystem code that it is a callback to SQL layer. sql/sql_handler.cc: Use newly introduced MAX_MDLKEY_LENGTH constant for allocating buffer for object key for metadata locking subsystem. sql/sql_show.cc: Use newly introduced MAX_MDLKEY_LENGTH constant for allocating buffer for object key for metadata locking subsystem.
Diffstat (limited to 'sql')
-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));