Commit c0a68902 authored by monty@narttu.mysql.fi's avatar monty@narttu.mysql.fi

Added some missing mutex_locks() when manipulating the table cache.

This should fix some possible table cache corruptions when doing
OPTIMIZE or REPAIR table when other threads are opening new tables.
parent 6899a4e3
...@@ -25,3 +25,4 @@ zak@balfor.local ...@@ -25,3 +25,4 @@ zak@balfor.local
monty@narttu. monty@narttu.
monty@mashka.mysql.fi monty@mashka.mysql.fi
bar@bar.udmsearch.izhnet.ru bar@bar.udmsearch.izhnet.ru
monty@narttu.mysql.fi
...@@ -279,6 +279,16 @@ void intern_close_table(TABLE *table) ...@@ -279,6 +279,16 @@ void intern_close_table(TABLE *table)
VOID(closefrm(table)); // close file VOID(closefrm(table)); // close file
} }
/*
Remove table from the open table cache
SYNOPSIS
free_cache_entry()
table Table to remove
NOTE
We need to have a lock on LOCK_open when calling this
*/
static void free_cache_entry(TABLE *table) static void free_cache_entry(TABLE *table)
{ {
...@@ -833,7 +843,10 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ...@@ -833,7 +843,10 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* make a new table */ /* make a new table */
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
{
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
}
if (open_unireg_entry(thd, table,db,table_name,alias,1) || if (open_unireg_entry(thd, table,db,table_name,alias,1) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key, !(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length))) key_length)))
...@@ -1181,7 +1194,6 @@ bool wait_for_tables(THD *thd) ...@@ -1181,7 +1194,6 @@ bool wait_for_tables(THD *thd)
/* Now we can open all tables without any interference */ /* Now we can open all tables without any interference */
thd->proc_info="Reopen tables"; thd->proc_info="Reopen tables";
result=reopen_tables(thd,0,0); result=reopen_tables(thd,0,0);
} }
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
thd->proc_info=0; thd->proc_info=0;
...@@ -1372,9 +1384,9 @@ int open_tables(THD *thd,TABLE_LIST *start) ...@@ -1372,9 +1384,9 @@ int open_tables(THD *thd,TABLE_LIST *start)
} }
} }
*prev_table=0; *prev_table=0;
pthread_mutex_unlock(&LOCK_open);
if (found) if (found)
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open);
goto restart; goto restart;
} }
result= -1; // Fatal error result= -1; // Fatal error
......
...@@ -1419,6 +1419,11 @@ bool select_create::send_eof() ...@@ -1419,6 +1419,11 @@ bool select_create::send_eof()
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
VOID(pthread_mutex_lock(&LOCK_open)); VOID(pthread_mutex_lock(&LOCK_open));
mysql_unlock_tables(thd, lock); mysql_unlock_tables(thd, lock);
/*
TODO:
Check if we can remove the following two rows.
We should be able to just keep the table in the table cache.
*/
if (!table->tmp_table) if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table); hash_delete(&open_cache,(byte*) table);
lock=0; table=0; lock=0; table=0;
......
...@@ -117,6 +117,7 @@ int mysqld_show_open_tables(THD *thd,const char *db,const char *wild) ...@@ -117,6 +117,7 @@ int mysqld_show_open_tables(THD *thd,const char *db,const char *wild)
if (list_open_tables(thd,&tables,db,wild)) if (list_open_tables(thd,&tables,db,wild))
DBUG_RETURN(-1); DBUG_RETURN(-1);
pthread_mutex_lock(&LOCK_open);
List_iterator<char> it(tables); List_iterator<char> it(tables);
while ((table_name=it++)) while ((table_name=it++))
{ {
...@@ -124,13 +125,17 @@ int mysqld_show_open_tables(THD *thd,const char *db,const char *wild) ...@@ -124,13 +125,17 @@ int mysqld_show_open_tables(THD *thd,const char *db,const char *wild)
net_store_data(&thd->packet,table_name); net_store_data(&thd->packet,table_name);
net_store_data(&thd->packet,query_table_status(thd,db,table_name)); net_store_data(&thd->packet,query_table_status(thd,db,table_name));
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length())) if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
{
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
} }
pthread_mutex_unlock(&LOCK_open);
send_eof(&thd->net); send_eof(&thd->net);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*************************************************************************** /***************************************************************************
** List all tables in a database (fast version) ** List all tables in a database (fast version)
** A table is a .frm file in the current databasedir ** A table is a .frm file in the current databasedir
......
...@@ -147,8 +147,8 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -147,8 +147,8 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
error = 0; error = 0;
err: err:
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
pthread_mutex_lock(&thd->mysys_var->mutex); pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0; thd->mysys_var->current_mutex= 0;
...@@ -160,7 +160,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) ...@@ -160,7 +160,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists)
my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr()); my_error(ER_BAD_TABLE_ERROR,MYF(0),wrong_tables.c_ptr());
error=1; error=1;
} }
if(error) if (error)
DBUG_RETURN(-1); DBUG_RETURN(-1);
send_ok(&thd->net); send_ok(&thd->net);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -711,7 +711,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, ...@@ -711,7 +711,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
table->reginfo.lock_type=TL_WRITE; table->reginfo.lock_type=TL_WRITE;
if (!((*lock)=mysql_lock_tables(thd,&table,1))) if (!((*lock)=mysql_lock_tables(thd,&table,1)))
{ {
VOID(pthread_mutex_lock(&LOCK_open));
hash_delete(&open_cache,(byte*) table); hash_delete(&open_cache,(byte*) table);
VOID(pthread_mutex_unlock(&LOCK_open));
quick_rm_table(create_info->db_type,db,name); quick_rm_table(create_info->db_type,db,name);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -859,7 +861,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -859,7 +861,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
reg_ext, 4), reg_ext, 4),
MYF(MY_WME))) MYF(MY_WME)))
{ {
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table); unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed copying .frm file")); "Failed copying .frm file"));
} }
...@@ -870,7 +874,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table) ...@@ -870,7 +874,9 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table)
if (generate_table(thd, table, 0)) if (generate_table(thd, table, 0))
{ {
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table); unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
thd->net.no_send_ok = save_no_send_ok; thd->net.no_send_ok = save_no_send_ok;
DBUG_RETURN(send_check_errmsg(thd, table, "restore", DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed generating table from .frm file")); "Failed generating table from .frm file"));
...@@ -930,9 +936,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -930,9 +936,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
// now we should be able to open the partially restored table // now we should be able to open the partially restored table
// to finish the restore in the handler later on // to finish the restore in the handler later on
if (!(table->table = reopen_name_locked_table(thd, table))) if (!(table->table = reopen_name_locked_table(thd, table)))
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table); unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
}
} }
if (!table->table) if (!table->table)
{ {
const char *err_msg; const char *err_msg;
...@@ -1031,8 +1040,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -1031,8 +1040,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (fatal_error) if (fatal_error)
table->table->version=0; // Force close of table table->table->version=0; // Force close of table
else if (open_for_modify) else if (open_for_modify)
{
pthread_mutex_lock(&LOCK_open);
remove_table_from_cache(thd, table->table->table_cache_key, remove_table_from_cache(thd, table->table->table_cache_key,
table->table->real_name); table->table->real_name);
pthread_mutex_unlock(&LOCK_open);
}
close_thread_tables(thd); close_thread_tables(thd);
if (my_net_write(&thd->net, (char*) packet->ptr(), if (my_net_write(&thd->net, (char*) packet->ptr(),
packet->length())) packet->length()))
...@@ -1648,8 +1661,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1648,8 +1661,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=1; error=1;
if (error) if (error)
{ {
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
VOID(pthread_cond_broadcast(&COND_refresh));
goto err; goto err;
} }
#ifdef HAVE_BERKELEY_DB #ifdef HAVE_BERKELEY_DB
......
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