List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:October 4 2007 8:38pm
Subject:bk commit into 5.1 tree (istruewing:1.2610) BUG#26379
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing 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-10-04 20:38:09+02:00, istruewing@stripped +3 -0
  Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
              corrupts a MERGE table
  
  Not to be pushed. For intermediate review only.
  
  This is a technology preview for removing wait_for_tables()
  from mysql_lock_tables(). Done during my Heidelberg stay.
  
  All calls to mysql_lock_tables() do now use the flag
  MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN. This means that
  wait_for_tables() is not called any more.
  
  The next step would be to remove the flag and the call
  to wait_for_tables() and the function itself alltogether.
  It is not used elsewhere.
  
  Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
  and added restart code where necessary.

  sql/sql_base.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +29 -5
    Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
                corrupts a MERGE table
    Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
    and added restart code where necessary.

  sql/sql_handler.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +14 -3
    Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
                corrupts a MERGE table
    Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
    and added restart code where necessary.

  sql/sql_insert.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +12 -4
    Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
                corrupts a MERGE table
    Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
    and added restart code where necessary.

diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2007-09-12 22:11:44 +02:00
+++ b/sql/sql_base.cc	2007-10-04 20:38:07 +02:00
@@ -3194,7 +3194,8 @@ bool reopen_tables(THD *thd,bool get_loc
     /* We should always get these locks */
     thd->some_tables_deleted=0;
     if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables),
-                                 0, &not_used)))
+                                 MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+                                 &not_used)))
     {
       thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
     }
@@ -4214,6 +4215,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
   thd->current_tablenr= 0;
   /* open_ltable can be used only for BASIC TABLEs */
   table_list->required_type= FRMTYPE_TABLE;
+ restart:
   while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0))
&&
          refresh)
     ;
@@ -4223,10 +4225,12 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
     if (table->child_l)
     {
       /* A MERGE table must not come here. */
+      /* purecov: begin tested */
       my_error(ER_WRONG_OBJECT, MYF(0), table->s->db.str,
                table->s->table_name.str, "BASE TABLE");
       table= 0;
       goto end;
+      /* purecov: end */
     }
 
     table_list->lock_type= lock_type;
@@ -4242,8 +4246,20 @@ TABLE *open_ltable(THD *thd, TABLE_LIST 
       DBUG_ASSERT(thd->lock == 0);	// You must lock everything at once
       if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
 	if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1,
-                                            lock_flags, &refresh)))
-	  table= 0;
+                                            lock_flags |
+                                            MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+                                            &refresh)))
+        {
+          if (refresh)
+          {
+            /* This thread should have opened this table only. */
+            DBUG_ASSERT(thd->open_tables == table);
+            close_thread_table(thd, &thd->open_tables);
+            goto restart;
+          }
+          else
+            table= 0;
+        }
     }
   }
 
@@ -8070,6 +8086,7 @@ open_system_tables_for_read(THD *thd, TA
 
   uint count= 0;
   bool not_used;
+ restart:
   for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
   {
     TABLE *table= open_table(thd, tables, thd->mem_root, &not_used,
@@ -8088,11 +8105,18 @@ open_system_tables_for_read(THD *thd, TA
   {
     TABLE **list= (TABLE**) thd->alloc(sizeof(TABLE*) * count);
     TABLE **ptr= list;
+    bool refresh;
+
     for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
       *(ptr++)= tables->table;
 
-    thd->lock= mysql_lock_tables(thd, list, count,
-                                 MYSQL_LOCK_IGNORE_FLUSH, &not_used);
+    thd->lock= mysql_lock_tables(thd, list, count, MYSQL_LOCK_IGNORE_FLUSH |
+                                 MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &refresh);
+    if (!thd->lock && refresh)
+    {
+      close_system_tables(thd, backup);
+      goto restart;
+    }
   }
   if (thd->lock)
     DBUG_RETURN(FALSE);
diff -Nrup a/sql/sql_handler.cc b/sql/sql_handler.cc
--- a/sql/sql_handler.cc	2007-08-30 21:23:53 +02:00
+++ b/sql/sql_handler.cc	2007-10-04 20:38:07 +02:00
@@ -361,7 +361,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST 
   uint          num_rows;
   uchar		*key;
   uint		key_len;
-  bool          not_used;
+  bool          refresh;
   DBUG_ENTER("mysql_ha_read");
   DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
                       tables->db, tables->table_name, tables->alias));
@@ -375,6 +375,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST 
   List_iterator<Item> it(list);
   it++;
 
+ restart:
   if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
                                               (uchar*) tables->alias,
                                               strlen(tables->alias) + 1)))
@@ -429,11 +430,21 @@ bool mysql_ha_read(THD *thd, TABLE_LIST 
   tables->table=table;
 
   HANDLER_TABLES_HACK(thd);
-  lock= mysql_lock_tables(thd, &tables->table, 1, 0, &not_used);
+  lock= mysql_lock_tables(thd, &tables->table, 1,
+                          MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &refresh);
   HANDLER_TABLES_HACK(thd);
 
   if (!lock)
-    goto err0; // mysql_lock_tables() printed error message already
+  {
+    if (refresh)
+    {
+      mysql_ha_close_table(thd, hash_tables);
+      hash_tables->table= NULL;
+      goto restart;
+    }
+    else
+      goto err0; // mysql_lock_tables() printed error message already
+  }
 
   // Always read all columns
   tables->table->read_set= &tables->table->s->all_set;
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc	2007-09-12 22:11:45 +02:00
+++ b/sql/sql_insert.cc	2007-10-04 20:38:07 +02:00
@@ -1676,6 +1676,7 @@ public:
   pthread_cond_t cond,cond_client;
   volatile uint tables_in_use,stacked_inserts;
   volatile bool status,dead;
+  bool refresh;
   COPY_INFO info;
   I_List<delayed_row> rows;
   ulong group_count;
@@ -1844,6 +1845,7 @@ bool delayed_get_table(THD *thd, TABLE_L
   /* Must be set in the parser */
   DBUG_ASSERT(table_list->db);
 
+ restart:
   /* Find the thread which handles this table. */
   if (!(di= find_handler(thd, table_list)))
   {
@@ -1945,6 +1947,9 @@ bool delayed_get_table(THD *thd, TABLE_L
   }
   /* Unlock the delayed insert object after its last access. */
   di->unlock();
+  /* If mysql_lock_tables() failed, table needs refresh. */
+  if (!table_list->table && di->refresh)
+    goto restart;
   DBUG_RETURN((table_list->table == NULL));
 
 end_create:
@@ -2368,7 +2373,6 @@ pthread_handler_t handle_delayed_insert(
 
     if (di->tables_in_use && ! thd->lock)
     {
-      bool not_used;
       /*
         Request for new delayed insert.
         Lock the table, but avoid to be blocked by a global read lock.
@@ -2380,8 +2384,9 @@ pthread_handler_t handle_delayed_insert(
         inserts are done.
       */
       if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1,
-                                          MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
-                                          &not_used)))
+                                          MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
+                                          MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+                                          &di->refresh)))
       {
 	/* Fatal error */
 	di->dead= 1;
@@ -3446,8 +3451,11 @@ static TABLE *create_table_from_items(TH
   {
     table->reginfo.lock_type= TL_WRITE;
     hooks->prelock(&table, 1);                    // Call prelock hooks
+    /* Locking should not fail with "need reopen". Name lock exists. */
     if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
-                                      MYSQL_LOCK_IGNORE_FLUSH, &not_used)) ||
+                                      MYSQL_LOCK_IGNORE_FLUSH |
+                                      MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+                                      &not_used)) ||
         hooks->postlock(&table, 1))
     {
       if (*lock)
Thread
bk commit into 5.1 tree (istruewing:1.2610) BUG#26379Ingo Struewing4 Oct