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

Merge work:/my/mysql-4.0 into narttu.mysql.fi:/my/mysql-4.0

parents 61f280a9 2a7dfa17
...@@ -2477,6 +2477,7 @@ int main(int argc, char** argv) ...@@ -2477,6 +2477,7 @@ int main(int argc, char** argv)
} }
case Q_COMMENT: /* Ignore row */ case Q_COMMENT: /* Ignore row */
case Q_COMMENT_WITH_COMMAND: case Q_COMMENT_WITH_COMMAND:
break;
case Q_PING: case Q_PING:
(void) mysql_ping(&cur_con->mysql); (void) mysql_ping(&cur_con->mysql);
break; break;
......
...@@ -107,6 +107,7 @@ void thr_unlock(THR_LOCK_DATA *data); ...@@ -107,6 +107,7 @@ void thr_unlock(THR_LOCK_DATA *data);
int thr_multi_lock(THR_LOCK_DATA **data,uint count); int thr_multi_lock(THR_LOCK_DATA **data,uint count);
void thr_multi_unlock(THR_LOCK_DATA **data,uint count); void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
void thr_abort_locks(THR_LOCK *lock); void thr_abort_locks(THR_LOCK *lock);
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
void thr_print_locks(void); /* For debugging */ void thr_print_locks(void); /* For debugging */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data); my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data);
......
...@@ -349,7 +349,8 @@ while test $# -gt 0; do ...@@ -349,7 +349,8 @@ while test $# -gt 0; do
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace" --debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/master.trace"
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \ EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT \
--debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace" --debug=d:t:i:A,$MYSQL_TEST_DIR/var/log/slave.trace"
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug" EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqltest.trace"
;; ;;
--fast) --fast)
FAST_START=1 FAST_START=1
......
drop table if exists t1; drop table if exists t1,t2;
create table t1(n int); create table t1(n int);
insert into t1 values (1); insert into t1 values (1);
lock tables t1 write; lock tables t1 write;
...@@ -17,3 +17,10 @@ unlock tables; ...@@ -17,3 +17,10 @@ unlock tables;
n n
1 1
drop table t1; drop table t1;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
insert t1 select * from t2;
drop table t2;
Table 'test.t2' doesn't exist
drop table t1;
...@@ -6,8 +6,9 @@ ...@@ -6,8 +6,9 @@
# #
-- source include/not_embedded.inc -- source include/not_embedded.inc
drop table if exists t1; drop table if exists t1,t2;
#test to see if select will get the lock ahead of low priority update
# test to see if select will get the lock ahead of low priority update
connect (locker,localhost,root,,); connect (locker,localhost,root,,);
connect (reader,localhost,root,,); connect (reader,localhost,root,,);
...@@ -48,3 +49,22 @@ reap; ...@@ -48,3 +49,22 @@ reap;
connection reader; connection reader;
reap; reap;
drop table t1; drop table t1;
#
# Test problem when using locks on many tables and droping a table that
# is to-be-locked by another thread
#
connection locker;
create table t1 (a int);
create table t2 (a int);
lock table t1 write, t2 write;
connection reader;
send insert t1 select * from t2;
connection locker;
drop table t2;
connection reader;
--error 1146
reap;
connection locker;
drop table t1;
...@@ -945,6 +945,54 @@ void thr_abort_locks(THR_LOCK *lock) ...@@ -945,6 +945,54 @@ void thr_abort_locks(THR_LOCK *lock)
} }
/*
Abort all locks for specific table/thread combination
This is used to abort all locks for a specific thread
*/
void thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
{
THR_LOCK_DATA *data;
DBUG_ENTER("thr_abort_locks_for_thread");
pthread_mutex_lock(&lock->mutex);
for (data= lock->read_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */
pthread_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->read_wait.last= data->prev;
}
}
for (data= lock->write_wait.data; data ; data= data->next)
{
if (pthread_equal(thread, data->thread))
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
pthread_cond_signal(data->cond);
data->cond= 0;
if (((*data->prev)= data->next))
data->next->prev= data->prev;
else
lock->write_wait.last= data->prev;
}
}
pthread_mutex_unlock(&lock->mutex);
DBUG_VOID_RETURN;
}
/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */
my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
......
...@@ -503,7 +503,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) ...@@ -503,7 +503,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
int error; int error;
DBUG_ENTER("handler::open"); DBUG_ENTER("handler::open");
DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d", DBUG_PRINT("enter",("name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
name, table->db_type, table->db_stat, mode, test_if_locked)); name, table->db_type, table->db_stat, mode,
test_if_locked));
if ((error=open(name,mode,test_if_locked))) if ((error=open(name,mode,test_if_locked)))
{ {
......
...@@ -313,6 +313,25 @@ void mysql_lock_abort(THD *thd, TABLE *table) ...@@ -313,6 +313,25 @@ void mysql_lock_abort(THD *thd, TABLE *table)
} }
/* Abort one thread / table combination */
void mysql_lock_abort_for_thread(THD *thd, TABLE *table)
{
MYSQL_LOCK *locked;
TABLE *write_lock_used;
DBUG_ENTER("mysql_lock_abort_for_thread");
if ((locked = get_lock_data(thd,&table,1,1,&write_lock_used)))
{
for (uint i=0; i < locked->lock_count; i++)
thr_abort_locks_for_thread(locked->locks[i]->lock,
table->in_use->real_id);
my_free((gptr) locked,MYF(0));
}
DBUG_VOID_RETURN;
}
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b) MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
{ {
MYSQL_LOCK *sql_lock; MYSQL_LOCK *sql_lock;
......
...@@ -711,6 +711,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); ...@@ -711,6 +711,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table);
void mysql_lock_abort(THD *thd, TABLE *table); void mysql_lock_abort(THD *thd, TABLE *table);
void mysql_lock_abort_for_thread(THD *thd, TABLE *table);
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b); MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b);
bool lock_global_read_lock(THD *thd); bool lock_global_read_lock(THD *thd);
void unlock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd);
......
...@@ -4416,8 +4416,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -4416,8 +4416,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case (int) OPT_SAFE: case (int) OPT_SAFE:
opt_specialflag|= SPECIAL_SAFE_MODE; opt_specialflag|= SPECIAL_SAFE_MODE;
delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE;
myisam_recover_options= HA_RECOVER_NONE; // To be changed myisam_recover_options= HA_RECOVER_DEFAULT;
ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE); ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
break; break;
case (int) OPT_SKIP_PRIOR: case (int) OPT_SKIP_PRIOR:
opt_specialflag|= SPECIAL_NO_PRIOR; opt_specialflag|= SPECIAL_NO_PRIOR;
......
...@@ -1244,25 +1244,44 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name) ...@@ -1244,25 +1244,44 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name)
} }
/* lock table to force abort of any threads trying to use table */ /*
If we have the table open, which only happens when a LOCK TABLE has been
done on the table, change the lock type to a lock that will abort all
other threads trying to get the lock.
*/
void abort_locked_tables(THD *thd,const char *db, const char *table_name) void abort_locked_tables(THD *thd,const char *db, const char *table_name)
{ {
TABLE *table; TABLE *table;
for (table=thd->open_tables; table ; table=table->next) for (table= thd->open_tables; table ; table= table->next)
{ {
if (!strcmp(table->real_name,table_name) && if (!strcmp(table->real_name,table_name) &&
!strcmp(table->table_cache_key,db)) !strcmp(table->table_cache_key,db))
{
mysql_lock_abort(thd,table); mysql_lock_abort(thd,table);
break;
}
} }
} }
/****************************************************************************
** open_unireg_entry /*
** Purpose : Load a table definition from file and open unireg table Load a table definition from file and open unireg table
** Args : entry with DB and table given
** Returns : 0 if ok SYNOPSIS
** Note that the extra argument for open is taken from thd->open_options open_unireg_entry()
thd Thread handle
entry Store open table definition here
db Database name
name Table name
alias Alias name
NOTES
Extra argument for open is taken from thd->open_options
RETURN
0 ok
# Error
*/ */
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
...@@ -2277,6 +2296,17 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, ...@@ -2277,6 +2296,17 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
} }
pthread_mutex_unlock(&in_use->mysys_var->mutex); pthread_mutex_unlock(&in_use->mysys_var->mutex);
} }
/*
Now we must abort all tables locks used by this thread
as the thread may be waiting to get a lock for another table
*/
for (TABLE *thd_table= in_use->open_tables;
thd_table ;
thd_table= thd_table->next)
{
if (thd_table->db_stat) // If table is open
mysql_lock_abort_for_thread(thd, thd_table);
}
} }
else else
result= result || return_if_owned_by_thd; result= result || return_if_owned_by_thd;
......
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