diff options
author | monty@narttu.mysql.fi <> | 2003-03-03 20:42:49 +0200 |
---|---|---|
committer | monty@narttu.mysql.fi <> | 2003-03-03 20:42:49 +0200 |
commit | 8c51eb2c126c1782e2598763d516f92eec29c924 (patch) | |
tree | bb5b30b61dc86c58f8550645b5e1dd2dd91770ed /sql/lock.cc | |
parent | ddb13eef8aefe1059d70a3ad68d9c4e9dfd63c5d (diff) | |
download | mariadb-git-8c51eb2c126c1782e2598763d516f92eec29c924.tar.gz |
Fixed a deadlock problem when using LOCK TABLE in one thread and DROP TABLE in another
Diffstat (limited to 'sql/lock.cc')
-rw-r--r-- | sql/lock.cc | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/sql/lock.cc b/sql/lock.cc index 84d10d61366..e46e2aac7bc 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -416,10 +416,11 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) { TABLE *table; char key[MAX_DBKEY_LENGTH]; + char *db= table_list->db ? table_list->db : (thd->db ? thd->db : (char*) ""); uint key_length; DBUG_ENTER("lock_table_name"); - key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->real_name) + key_length=(uint) (strmov(strmov(key,db)+1,table_list->real_name) -key)+ 1; /* Only insert the table if we haven't insert it already */ @@ -447,7 +448,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) my_free((gptr) table,MYF(0)); DBUG_RETURN(-1); } - if (remove_table_from_cache(thd, table_list->db, table_list->real_name)) + if (remove_table_from_cache(thd, db, table_list->real_name)) DBUG_RETURN(1); // Table is in use DBUG_RETURN(0); } @@ -490,6 +491,77 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(result); } + +/* + Lock all tables in list with a name lock + + SYNOPSIS + lock_table_names() + thd Thread handle + table_list Names of tables to lock + + NOTES + One must have a lock on LOCK_open when calling this + + RETURN + 0 ok + 1 Fatal error (end of memory ?) +*/ + +bool lock_table_names(THD *thd, TABLE_LIST *table_list) +{ + bool got_all_locks=1; + TABLE_LIST *lock_table; + + for (lock_table=table_list ; lock_table ; lock_table=lock_table->next) + { + int got_lock; + if ((got_lock=lock_table_name(thd,lock_table)) < 0) + goto end; // Fatal error + if (got_lock) + got_all_locks=0; // Someone is using table + } + + /* If some table was in use, wait until we got the lock */ + if (!got_all_locks && wait_for_locked_table_names(thd, table_list)) + goto end; + return 0; + +end: + unlock_table_names(thd, table_list, lock_table); + return 1; +} + + +/* + Unlock all tables in list with a name lock + + SYNOPSIS + unlock_table_names() + thd Thread handle + table_list Names of tables to unlock + last_table Don't unlock any tables after this one. + (default 0, which will unlock all tables) + + NOTES + One must have a lock on LOCK_open when calling this + This function will send a COND_refresh signal to inform other threads + that the name locks are removed + + RETURN + 0 ok + 1 Fatal error (end of memory ?) +*/ + +void unlock_table_names(THD *thd, TABLE_LIST *table_list, + TABLE_LIST *last_table) +{ + for (TABLE_LIST *table=table_list ; table != last_table ; table=table->next) + unlock_table_name(thd,table); + pthread_cond_broadcast(&COND_refresh); +} + + static void print_lock_error(int error) { int textno; |