mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge mysql.com:/Users/davi/mysql/bugs/32395-5.1
into mysql.com:/Users/davi/mysql/mysql-5.1-runtime
This commit is contained in:
@ -130,7 +130,7 @@ void table_cache_free(void)
|
||||
DBUG_ENTER("table_cache_free");
|
||||
if (table_def_inited)
|
||||
{
|
||||
close_cached_tables((THD*) 0,0,(TABLE_LIST*) 0);
|
||||
close_cached_tables(NULL, NULL, FALSE, FALSE, FALSE);
|
||||
if (!open_cache.records) // Safety first
|
||||
hash_free(&open_cache);
|
||||
}
|
||||
@ -908,16 +908,24 @@ void free_io_cache(TABLE *table)
|
||||
/*
|
||||
Close all tables which aren't in use by any thread
|
||||
|
||||
THD can be NULL, but then if_wait_for_refresh must be FALSE
|
||||
and tables must be NULL.
|
||||
@param thd Thread context
|
||||
@param tables List of tables to remove from the cache
|
||||
@param have_lock If LOCK_open is locked
|
||||
@param wait_for_refresh Wait for a impending flush
|
||||
@param wait_for_placeholders Wait for tables being reopened so that the GRL
|
||||
won't proceed while write-locked tables are being reopened by other
|
||||
threads.
|
||||
|
||||
@remark THD can be NULL, but then wait_for_refresh must be FALSE
|
||||
and tables must be NULL.
|
||||
*/
|
||||
|
||||
bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
TABLE_LIST *tables, bool have_lock)
|
||||
bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
|
||||
bool wait_for_refresh, bool wait_for_placeholders)
|
||||
{
|
||||
bool result=0;
|
||||
DBUG_ENTER("close_cached_tables");
|
||||
DBUG_ASSERT(thd || (!if_wait_for_refresh && !tables));
|
||||
DBUG_ASSERT(thd || (!wait_for_refresh && !tables));
|
||||
|
||||
if (!have_lock)
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
@ -941,7 +949,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
}
|
||||
DBUG_PRINT("tcache", ("incremented global refresh_version to: %lu",
|
||||
refresh_version));
|
||||
if (if_wait_for_refresh)
|
||||
if (wait_for_refresh)
|
||||
{
|
||||
/*
|
||||
Other threads could wait in a loop in open_and_lock_tables(),
|
||||
@ -998,13 +1006,13 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
found=1;
|
||||
}
|
||||
if (!found)
|
||||
if_wait_for_refresh=0; // Nothing to wait for
|
||||
wait_for_refresh=0; // Nothing to wait for
|
||||
}
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (!tables)
|
||||
kill_delayed_threads();
|
||||
#endif
|
||||
if (if_wait_for_refresh)
|
||||
if (wait_for_refresh)
|
||||
{
|
||||
/*
|
||||
If there is any table that has a lower refresh_version, wait until
|
||||
@ -1027,6 +1035,9 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
for (uint idx=0 ; idx < open_cache.records ; idx++)
|
||||
{
|
||||
TABLE *table=(TABLE*) hash_element(&open_cache,idx);
|
||||
/* Avoid a self-deadlock. */
|
||||
if (table->in_use == thd)
|
||||
continue;
|
||||
/*
|
||||
Note that we wait here only for tables which are actually open, and
|
||||
not for placeholders with TABLE::open_placeholder set. Waiting for
|
||||
@ -1041,7 +1052,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
are employed by CREATE TABLE as in this case table simply does not
|
||||
exist yet.
|
||||
*/
|
||||
if (table->needs_reopen_or_name_lock() && table->db_stat)
|
||||
if (table->needs_reopen_or_name_lock() && (table->db_stat ||
|
||||
(table->open_placeholder && wait_for_placeholders)))
|
||||
{
|
||||
found=1;
|
||||
DBUG_PRINT("signal", ("Waiting for COND_refresh"));
|
||||
@ -1060,11 +1072,18 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||
thd->in_lock_tables=0;
|
||||
/* Set version for table */
|
||||
for (TABLE *table=thd->open_tables; table ; table= table->next)
|
||||
table->s->version= refresh_version;
|
||||
{
|
||||
/*
|
||||
Preserve the version (0) of write locked tables so that a impending
|
||||
global read lock won't sneak in.
|
||||
*/
|
||||
if (table->reginfo.lock_type < TL_WRITE_ALLOW_WRITE)
|
||||
table->s->version= refresh_version;
|
||||
}
|
||||
}
|
||||
if (!have_lock)
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
if (if_wait_for_refresh)
|
||||
if (wait_for_refresh)
|
||||
{
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
thd->mysys_var->current_mutex= 0;
|
||||
@ -1091,10 +1110,10 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh,
|
||||
DBUG_ASSERT(thd);
|
||||
|
||||
bzero(&tmp, sizeof(TABLE_LIST));
|
||||
|
||||
|
||||
if (!have_lock)
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
|
||||
|
||||
for (idx= 0; idx < table_def_cache.records; idx++)
|
||||
{
|
||||
TABLE_SHARE *share= (TABLE_SHARE *) hash_element(&table_def_cache, idx);
|
||||
@ -1123,11 +1142,11 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh,
|
||||
}
|
||||
|
||||
if (tables)
|
||||
result= close_cached_tables(thd, FALSE, tables, TRUE);
|
||||
|
||||
result= close_cached_tables(thd, tables, TRUE, FALSE, FALSE);
|
||||
|
||||
if (!have_lock)
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
|
||||
|
||||
if (if_wait_for_refresh)
|
||||
{
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
@ -2227,7 +2246,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond)
|
||||
current thread.
|
||||
|
||||
@param thd current thread context
|
||||
@param tables able list containing one table to open.
|
||||
@param tables table list containing one table to open.
|
||||
|
||||
@return FALSE on success, TRUE otherwise.
|
||||
*/
|
||||
@ -3295,8 +3314,8 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p)
|
||||
|
||||
@param thd Thread context
|
||||
@param get_locks Should we get locks after reopening tables ?
|
||||
@param in_refresh Are we in FLUSH TABLES ? TODO: It seems that
|
||||
we can remove this parameter.
|
||||
@param mark_share_as_old Mark share as old to protect from a impending
|
||||
global read lock.
|
||||
|
||||
@note Since this function can't properly handle prelocking and
|
||||
create placeholders it should be used in very special
|
||||
@ -3310,13 +3329,17 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p)
|
||||
@return FALSE in case of success, TRUE - otherwise.
|
||||
*/
|
||||
|
||||
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
|
||||
bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
|
||||
{
|
||||
TABLE *table,*next,**prev;
|
||||
TABLE **tables,**tables_ptr; // For locks
|
||||
TABLE *err_tables= NULL;
|
||||
bool error=0, not_used;
|
||||
bool merge_table_found= FALSE;
|
||||
const uint flags= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN |
|
||||
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
|
||||
MYSQL_LOCK_IGNORE_FLUSH;
|
||||
|
||||
DBUG_ENTER("reopen_tables");
|
||||
|
||||
if (!thd->open_tables)
|
||||
@ -3377,7 +3400,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
|
||||
/* Do not handle locks of MERGE children. */
|
||||
if (get_locks && !db_stat && !table->parent)
|
||||
*tables_ptr++= table; // need new lock on this
|
||||
if (in_refresh)
|
||||
if (mark_share_as_old)
|
||||
{
|
||||
table->s->version=0;
|
||||
table->open_placeholder= 0;
|
||||
@ -3410,7 +3433,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
|
||||
*/
|
||||
thd->some_tables_deleted=0;
|
||||
if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables),
|
||||
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, ¬_used)))
|
||||
flags, ¬_used)))
|
||||
{
|
||||
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
|
||||
}
|
||||
|
Reference in New Issue
Block a user