@ -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 , FALS E ) ;
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 t able 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 , & not_used ) ) )
flags , & not_used ) ) )
{
thd - > locked_tables = mysql_lock_merge ( thd - > locked_tables , lock ) ;
}