Commit 3d19fdad authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

------------------------------------------------------------
revno: 2630.4.14
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Wed 2008-05-28 12:16:03 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress. Removed unused code and
  adjusted names of functions/methods to better reflect
  their current function.
parent af4ee743
...@@ -1238,9 +1238,9 @@ bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last, ...@@ -1238,9 +1238,9 @@ bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
bool reopen_table(TABLE *table); bool reopen_table(TABLE *table);
bool reopen_tables(THD *thd, bool get_locks); bool reopen_tables(THD *thd, bool get_locks);
thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table); thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table);
void close_data_files_and_morph_locks(THD *thd, const char *db, void close_data_files_and_leave_as_placeholders(THD *thd, const char *db,
const char *table_name); const char *table_name);
void close_handle_and_leave_table_as_lock(TABLE *table); void close_handle_and_leave_table_as_placeholder(TABLE *table);
void unlock_locked_tables(THD *thd); void unlock_locked_tables(THD *thd);
void execute_init_command(THD *thd, sys_var_str *init_command_var, void execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex); rw_lock_t *var_mutex);
......
...@@ -726,25 +726,23 @@ static void reference_table_share(TABLE_SHARE *share) ...@@ -726,25 +726,23 @@ static void reference_table_share(TABLE_SHARE *share)
} }
/* /**
Close file handle, but leave the table in the table cache Close file handle, but leave the table in THD::open_tables list
to allow its future reopening.
SYNOPSIS @param table Table handler
close_handle_and_leave_table_as_lock()
table Table handler
NOTES @note THD::killed will be set if we run out of memory
By leaving the table in the table cache, it disallows any other thread
to open the table
thd->killed will be set if we run out of memory @note If closing a MERGE child, the calling function has to
take care for closing the parent too, if necessary.
If closing a MERGE child, the calling function has to take care for @todo Get rid of this function once we refactor LOCK TABLES
closing the parent too, if necessary. to keep around TABLE_LIST elements used for opening
of tables until UNLOCK TABLES.
*/ */
void close_handle_and_leave_table_as_placeholder(TABLE *table)
void close_handle_and_leave_table_as_lock(TABLE *table)
{ {
TABLE_SHARE *share, *old_share= table->s; TABLE_SHARE *share, *old_share= table->s;
char *key_buff; char *key_buff;
...@@ -1048,8 +1046,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, ...@@ -1048,8 +1046,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
char dbname[NAME_LEN+1]; char dbname[NAME_LEN+1];
char tname[NAME_LEN+1]; char tname[NAME_LEN+1];
/* /*
Since close_data_files_and_morph_locks() frees share's memroot Since close_data_files_and_leave_as_placeholders() frees share's
we need to make copies of database and table names. memroot we need to make copies of database and table names.
*/ */
strmov(dbname, tab->s->db.str); strmov(dbname, tab->s->db.str);
strmov(tname, tab->s->table_name.str); strmov(tname, tab->s->table_name.str);
...@@ -1059,7 +1057,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, ...@@ -1059,7 +1057,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
goto err_with_reopen; goto err_with_reopen;
} }
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
close_data_files_and_morph_locks(thd, dbname, tname); close_data_files_and_leave_as_placeholders(thd, dbname, tname);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
} }
} }
...@@ -1082,7 +1080,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, ...@@ -1082,7 +1080,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
goto err_with_reopen; goto err_with_reopen;
} }
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
close_data_files_and_morph_locks(thd, table->db, table->table_name); close_data_files_and_leave_as_placeholders(thd, table->db,
table->table_name);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
} }
} }
...@@ -1529,7 +1528,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) ...@@ -1529,7 +1528,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
detach_merge_children(table, TRUE); detach_merge_children(table, TRUE);
table->mdl_lock= 0; table->mdl_lock= 0;
if (table->needs_reopen_or_name_lock() || if (table->needs_reopen() ||
thd->version != refresh_version || !table->db_stat) thd->version != refresh_version || !table->db_stat)
{ {
free_cache_entry(table); free_cache_entry(table);
...@@ -1537,12 +1536,6 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) ...@@ -1537,12 +1536,6 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
} }
else else
{ {
/*
Open placeholders have TABLE::db_stat set to 0, so they should be
handled by the first alternative.
*/
DBUG_ASSERT(!table->open_placeholder);
/* Assert that MERGE children are not attached in unused_tables. */ /* Assert that MERGE children are not attached in unused_tables. */
DBUG_ASSERT(!table->is_children_attached()); DBUG_ASSERT(!table->is_children_attached());
...@@ -3244,7 +3237,7 @@ bool reopen_table(TABLE *table) ...@@ -3244,7 +3237,7 @@ bool reopen_table(TABLE *table)
/** /**
Close all instances of a table open by this thread and replace Close all instances of a table open by this thread and replace
them with exclusive name-locks. them with placeholder in THD::open_tables list for future reopening.
@param thd Thread context @param thd Thread context
@param db Database name for the table to be closed @param db Database name for the table to be closed
...@@ -3259,11 +3252,11 @@ bool reopen_table(TABLE *table) ...@@ -3259,11 +3252,11 @@ bool reopen_table(TABLE *table)
the strings are used in a loop even after the share may be freed. the strings are used in a loop even after the share may be freed.
*/ */
void close_data_files_and_morph_locks(THD *thd, const char *db, void close_data_files_and_leave_as_placeholders(THD *thd, const char *db,
const char *table_name) const char *table_name)
{ {
TABLE *table; TABLE *table;
DBUG_ENTER("close_data_files_and_morph_locks"); DBUG_ENTER("close_data_files_and_leave_as_placeholders");
safe_mutex_assert_owner(&LOCK_open); safe_mutex_assert_owner(&LOCK_open);
...@@ -3277,11 +3270,6 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, ...@@ -3277,11 +3270,6 @@ void close_data_files_and_morph_locks(THD *thd, const char *db,
thd->lock= 0; thd->lock= 0;
} }
/*
Note that open table list may contain a name-lock placeholder
for target table name if we process ALTER TABLE ... RENAME.
So loop below makes sense even if we are not under LOCK TABLES.
*/
for (table=thd->open_tables; table ; table=table->next) for (table=thd->open_tables; table ; table=table->next)
{ {
if (!strcmp(table->s->table_name.str, table_name) && if (!strcmp(table->s->table_name.str, table_name) &&
...@@ -3298,15 +3286,13 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, ...@@ -3298,15 +3286,13 @@ void close_data_files_and_morph_locks(THD *thd, const char *db,
won't have multiple children with the same db.table_name. won't have multiple children with the same db.table_name.
*/ */
mysql_lock_remove(thd, thd->locked_tables, table->parent, TRUE); mysql_lock_remove(thd, thd->locked_tables, table->parent, TRUE);
table->parent->open_placeholder= 1; close_handle_and_leave_table_as_placeholder(table->parent);
close_handle_and_leave_table_as_lock(table->parent);
} }
else else
mysql_lock_remove(thd, thd->locked_tables, table, TRUE); mysql_lock_remove(thd, thd->locked_tables, table, TRUE);
} }
table->open_placeholder= 1;
table->s->version= 0; table->s->version= 0;
close_handle_and_leave_table_as_lock(table); close_handle_and_leave_table_as_placeholder(table);
} }
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
......
...@@ -801,7 +801,7 @@ void mysql_ha_flush(THD *thd) ...@@ -801,7 +801,7 @@ void mysql_ha_flush(THD *thd)
if (hash_tables->table && if (hash_tables->table &&
(hash_tables->table->mdl_lock && (hash_tables->table->mdl_lock &&
mdl_has_pending_conflicting_lock(hash_tables->table->mdl_lock) || mdl_has_pending_conflicting_lock(hash_tables->table->mdl_lock) ||
hash_tables->table->needs_reopen_or_name_lock())) hash_tables->table->needs_reopen()))
mysql_ha_close_table(thd, hash_tables); mysql_ha_close_table(thd, hash_tables);
} }
......
...@@ -2638,7 +2638,7 @@ bool Delayed_insert::handle_inserts(void) ...@@ -2638,7 +2638,7 @@ bool Delayed_insert::handle_inserts(void)
thd_proc_info(&thd, "insert"); thd_proc_info(&thd, "insert");
max_rows= delayed_insert_limit; max_rows= delayed_insert_limit;
if (thd.killed || table->needs_reopen_or_name_lock()) if (thd.killed || table->needs_reopen())
{ {
thd.killed= THD::KILL_CONNECTION; thd.killed= THD::KILL_CONNECTION;
max_rows= ULONG_MAX; // Do as much as possible max_rows= ULONG_MAX; // Do as much as possible
......
...@@ -6262,7 +6262,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt) ...@@ -6262,7 +6262,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
and we set db_stat to zero to ensure we don't close twice. and we set db_stat to zero to ensure we don't close twice.
*/ */
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
close_data_files_and_morph_locks(thd, db, table_name); close_data_files_and_leave_as_placeholders(thd, db, table_name);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
......
...@@ -7415,7 +7415,7 @@ view_err: ...@@ -7415,7 +7415,7 @@ view_err:
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
close_data_files_and_morph_locks(thd, db, table_name); close_data_files_and_leave_as_placeholders(thd, db, table_name);
error=0; error=0;
save_old_db_type= old_db_type; save_old_db_type= old_db_type;
...@@ -7507,8 +7507,7 @@ view_err: ...@@ -7507,8 +7507,7 @@ view_err:
object to make it suitable for reopening. object to make it suitable for reopening.
*/ */
DBUG_ASSERT(t_table == table); DBUG_ASSERT(t_table == table);
table->open_placeholder= 1; close_handle_and_leave_table_as_placeholder(table);
close_handle_and_leave_table_as_lock(table);
} }
else else
{ {
......
...@@ -487,7 +487,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -487,7 +487,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (!result && thd->locked_tables) if (!result && thd->locked_tables)
{ {
/* Make table suitable for reopening */ /* Make table suitable for reopening */
close_data_files_and_morph_locks(thd, tables->db, tables->table_name); close_data_files_and_leave_as_placeholders(thd, tables->db,
tables->table_name);
thd->in_lock_tables= 1; thd->in_lock_tables= 1;
if (reopen_tables(thd, 1)) if (reopen_tables(thd, 1))
{ {
......
...@@ -793,24 +793,6 @@ public: ...@@ -793,24 +793,6 @@ public:
*/ */
my_bool key_read; my_bool key_read;
my_bool no_keyread; my_bool no_keyread;
/*
Placeholder for an open table which prevents other connections
from taking name-locks on this table. Typically used with
TABLE_SHARE::version member to take an exclusive name-lock on
this table name -- a name lock that not only prevents other
threads from opening the table, but also blocks other name
locks. This is achieved by:
- setting open_placeholder to 1 - this will block other name
locks, as wait_for_locked_table_name will be forced to wait,
see table_is_used for details.
- setting version to 0 - this will force other threads to close
the instance of this table and wait (this is the same approach
as used for usual name locks).
An exclusively name-locked table currently can have no handler
object associated with it (db_stat is always 0), but please do
not rely on that.
*/
my_bool open_placeholder;
my_bool locked_by_logger; my_bool locked_by_logger;
my_bool no_replicate; my_bool no_replicate;
my_bool locked_by_name; my_bool locked_by_name;
...@@ -874,12 +856,10 @@ public: ...@@ -874,12 +856,10 @@ public:
read_set= &def_read_set; read_set= &def_read_set;
write_set= &def_write_set; write_set= &def_write_set;
} }
/* Is table open or should be treated as such by name-locking? */
inline bool is_name_opened() { return db_stat || open_placeholder; }
/* /*
Is this instance of the table should be reopen or represents a name-lock? Is this instance of the table should be reopen?
*/ */
inline bool needs_reopen_or_name_lock() inline bool needs_reopen()
{ return s->version != refresh_version; } { return s->version != refresh_version; }
bool is_children_attached(void); bool is_children_attached(void);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment