List:Commits« Previous MessageNext Message »
From:Sergey Vojtovich Date:July 25 2007 4:56pm
Subject:bk commit into 5.1 tree (svoj:1.2559) BUG#29806
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of svoj. When svoj does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-07-25 19:56:17+05:00, svoj@stripped +5 -0
  BUG#29806 - binlog_innodb.test creates a server log
  
  Stopping mysql server could result in an entry in mysql error
  file: "InnoDB: Error: MySQL is freeing a thd".
  
  This happened because InnoDB assumes that the server will never
  call external_lock(F_UNLCK) in case external_lock(READ/WRITE)
  failed.
  
  Prior to this patch we haven't had strict definition whether
  external_lock(F_UNLCK) must be called in case external_lock(READ/WRITE)
  fails.
  
  This patch states that we never call external_lock(F_UNLCK) in case
  external_lock(READ/WRITE) fails.

  mysql-test/suite/binlog/t/disabled.def@stripped, 2007-07-25 19:56:13+05:00, svoj@stripped +0
-3
    Re-enabled binlog_innodb and binlog_killed tests.

  sql/ha_ndbcluster.cc@stripped, 2007-07-25 19:56:13+05:00, svoj@stripped +6 -0
    Restore handler state in case external_lock() failed.

  sql/ha_partition.cc@stripped, 2007-07-25 19:56:14+05:00, svoj@stripped +14 -1
    Do not call external_lock(F_UNLCK) in case external_lock(READ/WRITE) failed.

  sql/lock.cc@stripped, 2007-07-25 19:56:14+05:00, svoj@stripped +7 -1
    Do not call external_lock(F_UNLCK) in case external_lock(READ/WRITE) failed.

  storage/myisammrg/myrg_locking.c@stripped, 2007-07-25 19:56:14+05:00, svoj@stripped +8 -0
    Restore handler state in case external_lock() failed.

diff -Nrup a/mysql-test/suite/binlog/t/disabled.def
b/mysql-test/suite/binlog/t/disabled.def
--- a/mysql-test/suite/binlog/t/disabled.def	2007-07-17 12:24:58 +05:00
+++ b/mysql-test/suite/binlog/t/disabled.def	2007-07-25 19:56:13 +05:00
@@ -9,6 +9,3 @@
 #  Do not use any TAB characters for whitespace.
 #
 ##############################################################################
-
-binlog_innodb        : Bug#29806 2007-07-15 ingo master.err: InnoDB: Error: MySQL is
freeing a thd
-binlog_killed        : Bug#29806 2007-07-17 ingo master.err: InnoDB: Error: MySQL is
freeing a thd
diff -Nrup a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
--- a/sql/ha_ndbcluster.cc	2007-07-09 15:04:52 +05:00
+++ b/sql/ha_ndbcluster.cc	2007-07-25 19:56:13 +05:00
@@ -4383,7 +4383,10 @@ int ha_ndbcluster::external_lock(THD *th
 
         trans= ndb->startTransaction();
         if (trans == NULL)
+        {
+          thd_ndb->lock_count= 0;
           ERR_RETURN(ndb->getNdbError());
+        }
         thd_ndb->init_open_tables();
         thd_ndb->stmt= trans;
 	thd_ndb->query_state&= NDB_QUERY_NORMAL;
@@ -4409,7 +4412,10 @@ int ha_ndbcluster::external_lock(THD *th
           
           trans= ndb->startTransaction();
           if (trans == NULL)
+          {
+            thd_ndb->lock_count= 0;
             ERR_RETURN(ndb->getNdbError());
+          }
           thd_ndb->init_open_tables();
           thd_ndb->all= trans; 
 	  thd_ndb->query_state&= NDB_QUERY_NORMAL;
diff -Nrup a/sql/ha_partition.cc b/sql/ha_partition.cc
--- a/sql/ha_partition.cc	2007-07-05 00:55:21 +05:00
+++ b/sql/ha_partition.cc	2007-07-25 19:56:14 +05:00
@@ -1142,6 +1142,12 @@ int ha_partition::prepare_new_partition(
   create_flag= TRUE;
   if ((error= file->ha_open(table, part_name, m_mode, m_open_test_lock)))
     goto error;
+  /*
+    Note: if you plan to add another call that may return failure,
+    better to do it before external_lock() as cleanup_new_partition()
+    assumes that external_lock() is last call that may fail here.
+    Otherwise see description for cleanup_new_partition().
+  */
   if ((error= file->external_lock(current_thd, m_lock_type)))
     goto error;
 
@@ -1164,6 +1170,14 @@ error:
     NONE
 
   DESCRIPTION
+    This function is called immediately after prepare_new_partition() in
+    case the latter fails.
+
+    In prepare_new_partition() last call that may return failure is
+    external_lock(). That means if prepare_new_partition() fails,
+    partition does not have external lock. Thus no need to call
+    external_lock(F_UNLCK) here.
+
   TODO:
     We must ensure that in the case that we get an error during the process
     that we call external_lock with F_UNLCK, close the table and delete the
@@ -1182,7 +1196,6 @@ void ha_partition::cleanup_new_partition
     m_file= m_added_file;
     m_added_file= NULL;
 
-    external_lock(current_thd, F_UNLCK);
     /* delete_table also needed, a bit more complex */
     close();
 
diff -Nrup a/sql/lock.cc b/sql/lock.cc
--- a/sql/lock.cc	2007-06-19 01:13:18 +05:00
+++ b/sql/lock.cc	2007-07-25 19:56:14 +05:00
@@ -60,6 +60,11 @@
   - When calling UNLOCK TABLES we call mysql_unlock_tables() for all
     tables used in LOCK TABLES
 
+  If table_handler->external_lock(thd, locktype) fails, we call
+  table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
+  excluding one that caused failure. That means handler must cleanup itself
+  in case external_lock() fails.
+
 TODO:
   Change to use my_malloc() ONLY when using LOCK TABLES command or when
   we are forced to use mysql_lock_merge.
@@ -269,8 +274,9 @@ static int lock_external(THD *thd, TABLE
     if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
     {
       print_lock_error(error, (*tables)->file->table_type());
-      for (; i-- ; tables--)
+      while (--i)
       {
+        tables--;
 	(*tables)->file->ha_external_lock(thd, F_UNLCK);
 	(*tables)->current_lock=F_UNLCK;
       }
diff -Nrup a/storage/myisammrg/myrg_locking.c b/storage/myisammrg/myrg_locking.c
--- a/storage/myisammrg/myrg_locking.c	2006-12-31 04:06:41 +04:00
+++ b/storage/myisammrg/myrg_locking.c	2007-07-25 19:56:14 +05:00
@@ -37,7 +37,15 @@ int myrg_lock_database(MYRG_INFO *info, 
     (file->table)->owned_by_merge = TRUE;
 #endif
     if ((new_error=mi_lock_database(file->table,lock_type)))
+    {
       error=new_error;
+      if (lock_type != F_UNLCK)
+      {
+        while (--file >= info->open_tables)
+          mi_lock_database(file->table, F_UNLCK);
+        break;
+      }
+    }
   }
   return(error);
 }
Thread
bk commit into 5.1 tree (svoj:1.2559) BUG#29806Sergey Vojtovich25 Jul