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,
bool reopen_table(TABLE *table);
bool reopen_tables(THD *thd, bool get_locks);
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);
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 execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex);
......
......@@ -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
close_handle_and_leave_table_as_lock()
table Table handler
@param table Table handler
NOTES
By leaving the table in the table cache, it disallows any other thread
to open the table
@note THD::killed will be set if we run out of memory
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
closing the parent too, if necessary.
@todo Get rid of this function once we refactor LOCK TABLES
to keep around TABLE_LIST elements used for opening
of tables until UNLOCK TABLES.
*/
void close_handle_and_leave_table_as_lock(TABLE *table)
void close_handle_and_leave_table_as_placeholder(TABLE *table)
{
TABLE_SHARE *share, *old_share= table->s;
char *key_buff;
......@@ -1048,8 +1046,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
char dbname[NAME_LEN+1];
char tname[NAME_LEN+1];
/*
Since close_data_files_and_morph_locks() frees share's memroot
we need to make copies of database and table names.
Since close_data_files_and_leave_as_placeholders() frees share's
memroot we need to make copies of database and table names.
*/
strmov(dbname, tab->s->db.str);
strmov(tname, tab->s->table_name.str);
......@@ -1059,7 +1057,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
goto err_with_reopen;
}
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);
}
}
......@@ -1082,7 +1080,8 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
goto err_with_reopen;
}
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);
}
}
......@@ -1529,7 +1528,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
detach_merge_children(table, TRUE);
table->mdl_lock= 0;
if (table->needs_reopen_or_name_lock() ||
if (table->needs_reopen() ||
thd->version != refresh_version || !table->db_stat)
{
free_cache_entry(table);
......@@ -1537,12 +1536,6 @@ bool close_thread_table(THD *thd, TABLE **table_ptr)
}
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. */
DBUG_ASSERT(!table->is_children_attached());
......@@ -3244,7 +3237,7 @@ bool reopen_table(TABLE *table)
/**
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 db Database name for the table to be closed
......@@ -3259,11 +3252,11 @@ bool reopen_table(TABLE *table)
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)
{
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);
......@@ -3277,11 +3270,6 @@ void close_data_files_and_morph_locks(THD *thd, const char *db,
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)
{
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,
won't have multiple children with the same db.table_name.
*/
mysql_lock_remove(thd, thd->locked_tables, table->parent, TRUE);
table->parent->open_placeholder= 1;
close_handle_and_leave_table_as_lock(table->parent);
close_handle_and_leave_table_as_placeholder(table->parent);
}
else
mysql_lock_remove(thd, thd->locked_tables, table, TRUE);
}
table->open_placeholder= 1;
table->s->version= 0;
close_handle_and_leave_table_as_lock(table);
close_handle_and_leave_table_as_placeholder(table);
}
}
DBUG_VOID_RETURN;
......
......@@ -801,7 +801,7 @@ void mysql_ha_flush(THD *thd)
if (hash_tables->table &&
(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);
}
......
......@@ -2638,7 +2638,7 @@ bool Delayed_insert::handle_inserts(void)
thd_proc_info(&thd, "insert");
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;
max_rows= ULONG_MAX; // Do as much as possible
......
......@@ -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.
*/
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);
DBUG_RETURN(0);
}
......
......@@ -7415,7 +7415,7 @@ view_err:
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;
save_old_db_type= old_db_type;
......@@ -7507,8 +7507,7 @@ view_err:
object to make it suitable for reopening.
*/
DBUG_ASSERT(t_table == table);
table->open_placeholder= 1;
close_handle_and_leave_table_as_lock(table);
close_handle_and_leave_table_as_placeholder(table);
}
else
{
......
......@@ -487,7 +487,8 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (!result && thd->locked_tables)
{
/* 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;
if (reopen_tables(thd, 1))
{
......
......@@ -793,24 +793,6 @@ public:
*/
my_bool key_read;
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 no_replicate;
my_bool locked_by_name;
......@@ -874,12 +856,10 @@ public:
read_set= &def_read_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; }
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