summaryrefslogtreecommitdiff
path: root/sql/lock.cc
diff options
context:
space:
mode:
authorigor@rurik.mysql.com <>2006-04-19 18:08:15 -0700
committerigor@rurik.mysql.com <>2006-04-19 18:08:15 -0700
commit27cc6f4bc3be40dc6d6dac3c676193d5c1de3cd5 (patch)
tree3475fbd06f0fb2c8376c6279c435592f58d6324f /sql/lock.cc
parent592dc88be75fcad1129e053820bd326aeb114cb4 (diff)
parent67458961cf5cf8d50ca9b2b694a84599809b46ec (diff)
downloadmariadb-git-27cc6f4bc3be40dc6d6dac3c676193d5c1de3cd5.tar.gz
Merge rurik.mysql.com:/home/igor/dev/mysql-4.1-2
into rurik.mysql.com:/home/igor/dev/mysql-5.0-0
Diffstat (limited to 'sql/lock.cc')
-rw-r--r--sql/lock.cc56
1 files changed, 54 insertions, 2 deletions
diff --git a/sql/lock.cc b/sql/lock.cc
index a584b063a0b..8ea13b2117c 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -78,6 +78,7 @@ extern HASH open_cache;
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
uint flags, TABLE **write_locked);
+static void reset_lock_data(MYSQL_LOCK *sql_lock);
static int lock_external(THD *thd, TABLE **table,uint count);
static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error, const char *);
@@ -135,12 +136,16 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
*/
if (wait_if_global_read_lock(thd, 1, 1))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
- }
+ }
if (thd->version != refresh_version)
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
goto retry;
}
@@ -149,6 +154,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
thd->proc_info="System lock";
if (lock_external(thd, tables, count))
{
+ /* Clear the lock type of all lock data to avoid reusage. */
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
break;
@@ -699,7 +706,10 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*write_lock_used=table;
if (table->db_stat & HA_READ_ONLY)
{
- my_error(ER_OPEN_AS_READONLY, MYF(0), table->alias);
+ my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
+ /* Clear the lock type of the lock data that are stored already. */
+ sql_lock->lock_count= locks - sql_lock->locks;
+ reset_lock_data(sql_lock);
my_free((gptr) sql_lock,MYF(0));
DBUG_RETURN(0);
}
@@ -724,6 +734,48 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
}
+/*
+ Reset lock type in lock data.
+
+ SYNOPSIS
+ reset_lock_data()
+ sql_lock The MySQL lock.
+
+ DESCRIPTION
+
+ After a locking error we want to quit the locking of the table(s).
+ The test case in the bug report for Bug #18544 has the following
+ cases: 1. Locking error in lock_external() due to InnoDB timeout.
+ 2. Locking error in get_lock_data() due to missing write permission.
+ 3. Locking error in wait_if_global_read_lock() due to lock conflict.
+
+ In all these cases we have already set the lock type into the lock
+ data of the open table(s). If the table(s) are in the open table
+ cache, they could be reused with the non-zero lock type set. This
+ could lead to ignoring a different lock type with the next lock.
+
+ Clear the lock type of all lock data. This ensures that the next
+ lock request will set its lock type properly.
+
+ RETURN
+ void
+*/
+
+static void reset_lock_data(MYSQL_LOCK *sql_lock)
+{
+ THR_LOCK_DATA **ldata;
+ THR_LOCK_DATA **ldata_end;
+
+ for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
+ ldata < ldata_end;
+ ldata++)
+ {
+ /* Reset lock type. */
+ (*ldata)->type= TL_UNLOCK;
+ }
+}
+
+
/*****************************************************************************
Lock table based on the name.
This is used when we need total access to a closed, not open table