List:Commits« Previous MessageNext Message »
From:dlenev Date:October 17 2007 12:28pm
Subject:bk commit into 5.1 tree (dlenev:1.2579)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of dlenev. When dlenev 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-17 14:28:38+04:00, dlenev@stripped +5 -0
  Next stage of work on new meta-data locking subsystem/table cache/table
  definition cache (which is needed to simplify fixes for such bugs as
  #25144 "replication / binlog with view breaks"  and #989 "If DROP TABLE
  while there's an active transaction, wrong binlog order").
  
  Implemented infrastracture and API calls to allow caching pointers to the
  objects associated with locks in MDL subsystem. Exploited them to speed
  up table open process.
  
  Also improved performance of MDL operations by keeping pointer to the
  MDL_LOCK in lock request object and avoiding extra lookups in mdl_locks
  hash in some cases.

  sql/meta_lock.cc@stripped, 2007-10-17 14:28:35+04:00, dlenev@stripped +115 -7
    Implemented infrastracture and API calls to allow caching pointers to the
    objects associated with locks in MDL subsystem.
    Added assertion which prohibits taking/releasing meta-data locks while
    holding LOCK_open as now this might lead to deadlock.
    Improved performance of MDL operations by keeping pointer to the MDL_LOCK
    in lock request object and avoiding extra look-ups in mdl_locks hash
    in some cases (most notable case is when we releaser meta-data lock).

  sql/meta_lock.h@stripped, 2007-10-17 14:28:35+04:00, dlenev@stripped +12 -2
    Implemented infrastracture and API calls to allow caching pointers to the
    objects associated with locks in MDL subsystem.
    Improved performance of MDL operations by keeping pointer to the MDL_LOCK
    in lock request object and avoiding extra look-ups in mdl_locks hash
    in some cases (most notable case is when we releaser meta-data lock).

  sql/sql_base.cc@stripped, 2007-10-17 14:28:35+04:00, dlenev@stripped +98 -36
    Use ability of MDL subysystem to cache pointers to objects associated with
    meta-data lock to speed up table open process (currently we save one hash
    look-up by doing this but in future we may also save on synchronization).

  sql/sql_handler.cc@stripped, 2007-10-17 14:28:35+04:00, dlenev@stripped +17 -22
    Adjusted mysql_ha_flush() and mysql_ha_flush_table() functions to
    satisfy newly introduced assertion in meta-data locking subsystem
    which prohibits holding LOCK_open while trying to obtain or release
    meta-data lock. This is actually temporary solution which will be
    reworked once we get rid of usage of mysql_ha_flush() in
    wait_for_tables().

  sql/sql_table.cc@stripped, 2007-10-17 14:28:35+04:00, dlenev@stripped +4 -3
    Fixed code to satisfy newly introduced assertion in meta-data locking
    subsystem. We should not hold LOCK_open while trying to obtain/release
    meta-data lock since this might lead to deadlock.

diff -Nrup a/sql/meta_lock.cc b/sql/meta_lock.cc
--- a/sql/meta_lock.cc	2007-09-04 13:31:58 +04:00
+++ b/sql/meta_lock.cc	2007-10-17 14:28:35 +04:00
@@ -34,6 +34,8 @@ struct MDL_LOCK
   MDL_EL *active_writers;
   MDL_EL *waiting_writers;
   uint   users;
+  void   *cached_object;
+  mdl_cached_object_release_hook cached_object_release_hook;
   MDL_EL *get_key_owner()
   {
      return active_readers ? active_readers : (active_readers_waiting_upgrade ?
@@ -126,6 +128,7 @@ void mdl_init_lock(MDL_EL *mdl, char *ke
   mdl->key= key;
 #ifndef DBUG_OFF
   mdl->ctx= 0;
+  mdl->lock= 0;
 #endif
 }
 
@@ -234,6 +237,8 @@ bool mdl_acquire_lock(MDL_EL *l)
 
   DBUG_ASSERT(l->type == SHARED_PENDING);
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
 
   if (!(lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key,
l->key_length)))
@@ -244,6 +249,7 @@ bool mdl_acquire_lock(MDL_EL *l)
     lock->users= 1;
     my_hash_insert(&mdl_locks, (uchar*)lock);
     l->type= SHARED;
+    l->lock= lock;
   }
   else
   {
@@ -262,6 +268,7 @@ bool mdl_acquire_lock(MDL_EL *l)
       lock->active_readers= l;
       lock->users++;
       l->type= SHARED;
+      l->lock= lock;
     }
     else
       result= TRUE;
@@ -327,6 +334,8 @@ void mdl_acquire_exclusive_locks(MDL_CON
   MDL_LOCK *lock;
   bool signalled= FALSE;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= context->locks; l; l= l->next_context)
   {
@@ -338,12 +347,14 @@ void mdl_acquire_exclusive_locks(MDL_CON
       l->next_lock= 0;
       lock->users= 1;
       my_hash_insert(&mdl_locks, (uchar*)lock);
+      l->lock= lock;
     }
     else
     {
       l->next_lock= lock->waiting_writers;
       lock->waiting_writers= l;
       lock->users++;
+      l->lock= lock;
     }
   }
 
@@ -351,7 +362,7 @@ void mdl_acquire_exclusive_locks(MDL_CON
   {
     for (l= context->locks; l; l= l->next_context)
     {
-      lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+      lock= l->lock;
 
       if ((lh= lock->active_readers))
       {
@@ -388,7 +399,7 @@ void mdl_acquire_exclusive_locks(MDL_CON
   }
   for (l= context->locks; l; l= l->next_context)
   {
-    lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+    lock= l->lock;
     /* remove lock from waiters list */
     lp= &(lock->waiting_writers);
     while (*lp != l)
@@ -398,6 +409,9 @@ void mdl_acquire_exclusive_locks(MDL_CON
     l->next_lock= lock->active_writers;
     lock->active_writers= l;
     l->type= EXCLUSIVE;
+    if (lock->cached_object)
+      (*lock->cached_object_release_hook)(l->lock->cached_object);
+    lock->cached_object= NULL;
   }
   pthread_mutex_unlock(&LOCK_mdl);
 }
@@ -427,6 +441,8 @@ void mdl_upgrade_shared_lock_to_exclusiv
   int4store(key, type);
   key_length= (uint) (strmov(strmov(key+4, db)+1, name)-key)+1;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= context->locks; l; l= l->next_context)
     if (l->key_length == key_length && !memcmp(l->key, key, key_length)
&&
@@ -434,7 +450,7 @@ void mdl_upgrade_shared_lock_to_exclusiv
     {
       DBUG_PRINT("info", ("found shared lock for upgrade"));
       l->type= SHARED_PENDING_UPGRADE;
-      lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+      lock= l->lock;
       /* exclude lock from readers list */
       lp= &(lock->active_readers);
       while (*lp != l)
@@ -455,7 +471,7 @@ void mdl_upgrade_shared_lock_to_exclusiv
     {
       if (l->type == SHARED_PENDING_UPGRADE)
       {
-        lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key,
l->key_length);
+        lock= l->lock;
 
         if ((lh= lock->active_readers))
         {
@@ -493,7 +509,7 @@ void mdl_upgrade_shared_lock_to_exclusiv
   for (l= context->locks; l; l= l->next_context)
     if (l->type == SHARED_PENDING_UPGRADE)
     {
-      lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+      lock= l->lock;
       /* remove lock from waiters list */
       lp= &(lock->active_readers_waiting_upgrade);
       while (*lp != l)
@@ -503,6 +519,9 @@ void mdl_upgrade_shared_lock_to_exclusiv
       l->next_lock= lock->active_writers;
       lock->active_writers= l;
       l->type= EXCLUSIVE;
+      if (lock->cached_object)
+        (*lock->cached_object_release_hook)(l->lock->cached_object);
+      lock->cached_object= 0;
     }
 
   pthread_mutex_unlock(&LOCK_mdl);
@@ -524,10 +543,14 @@ static void release_lock(MDL_EL *l)
   DBUG_PRINT("enter", ("db=%s name=%s", l->key + 4,
                         l->key + 4 + strlen(l->key + 4) + 1));
 
-  lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+  lock= l->lock;
   if (lock->has_no_other_users())
   {
     hash_delete(&mdl_locks, (uchar *)lock);
+    DBUG_PRINT("info", ("releasing cached_object cached_object=%p",
+                        lock->cached_object));
+    if (lock->cached_object)
+      (*lock->cached_object_release_hook)(l->lock->cached_object);
     release_lock_object(lock);
   }
   else
@@ -568,6 +591,9 @@ void mdl_release_locks(MDL_CONTEXT *cont
 {
   MDL_EL *l;
   DBUG_ENTER("mdl_release_locks");
+
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= context->locks; l; l= l->next_context)
   {
@@ -580,6 +606,9 @@ void mdl_release_locks(MDL_CONTEXT *cont
     {
       release_lock(l);
       l->type= SHARED_PENDING;
+#ifndef DBUG_OFF
+      l->lock= 0;
+#endif
     }
   }
   /* Inefficient but will do for a while */
@@ -601,6 +630,8 @@ void mdl_wait_for_locks(MDL_CONTEXT *con
   MDL_EL *l;
   MDL_LOCK *lock;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   while (1)
   {
@@ -695,6 +726,8 @@ bool mdl_try_acquire_exclusive_lock(MDL_
 
   DBUG_ASSERT(l->type == EXCLUSIVE_PENDING);
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   if (!(lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key,
l->key_length)))
   {
@@ -704,10 +737,25 @@ bool mdl_try_acquire_exclusive_lock(MDL_
     my_hash_insert(&mdl_locks, (uchar*)lock);
     l->type= EXCLUSIVE;
     l->next_lock= 0;
+    l->lock= lock;
     lock= 0;
   }
   pthread_mutex_unlock(&LOCK_mdl);
 
+  /*
+    FIXME: We can't leave EXCLUSIVE_PENDING locks in the list since for such
+           locks we assume that they have MDL_EL::lock properly set.
+           Long term we should clearly define relation between lock types,
+           presence in the context lists and MDL_EL::lock values.
+  */
+  if (lock)
+  {
+    MDL_EL **lp;
+    for (lp= &context->locks; *lp != l; lp= &((*lp)->next_context))
+      continue;
+    *lp= l->next_context;
+  }
+
   return lock;
 }
 
@@ -724,6 +772,8 @@ void mdl_release_exclusive_locks(MDL_CON
 {
   MDL_EL **l;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= &context->locks; *l; )
   {
@@ -732,6 +782,7 @@ void mdl_release_exclusive_locks(MDL_CON
       release_lock(*l);
 #ifndef DBUG_OFF
       (*l)->ctx= 0;
+      (*l)->lock= 0;
 #endif
       *l= (*l)->next_context;
     }
@@ -754,11 +805,13 @@ void mdl_downgrade_exclusive_locks(MDL_C
   MDL_EL *l, **lp;
   MDL_LOCK *lock;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= context->locks; l; l= l->next_context)
     if (l->type == EXCLUSIVE)
     {
-      lock= (MDL_LOCK *)hash_search(&mdl_locks, (uchar*)l->key, l->key_length);
+      lock= l->lock;
       lp= &(lock->active_writers);
       while (*lp != l)
         lp= &((*lp)->next_lock);
@@ -783,12 +836,15 @@ void mdl_release_lock(MDL_CONTEXT *conte
 {
   MDL_EL **l;
 
+  safe_mutex_assert_not_owner(&LOCK_open);
+
   pthread_mutex_lock(&LOCK_mdl);
   for (l= &context->locks; *l != lr; l= &((*l)->next_context))
     continue;
   release_lock(*l);
 #ifndef DBUG_OFF
   (*l)->ctx= 0;
+  (*l)->lock= 0;
 #endif
   *l= (*l)->next_context;
   pthread_cond_broadcast(&COND_mdl);
@@ -821,4 +877,56 @@ bool mdl_is_exclusive_lock_owner(MDL_CON
        l= l->next_context)
     continue;
   return (l && l->type == EXCLUSIVE);
+}
+
+
+/**
+   @brief Get pointer to opaque object associated with lock.
+
+   @param  l Lock request for the lock with which object is associated.
+
+   @return Pointer to opaque object associated with lock.
+*/
+
+void* mdl_get_cached_object(MDL_EL *l)
+{
+  DBUG_ASSERT(l->type == SHARED || l->type == EXCLUSIVE ||
+              l->type == SHARED_PENDING_UPGRADE);
+  return l->lock->cached_object;
+}
+
+
+/**
+   @brief Associate pointer to opaque object with lock.
+
+   @param l             Lock request for the lock with which object should
+                        be associated.
+   @param cached_object Pointer to the object
+   @param release_hook  Cleanup function to be called when MDL subsystem
+                        decides to remove lock or associate another object.
+*/
+
+void mdl_set_cached_object(MDL_EL *l, void *cached_object,
+                           mdl_cached_object_release_hook release_hook)
+{
+  DBUG_ENTER("mdl_set_cached_object");
+  DBUG_PRINT("enter", ("db=%s name=%s cached_object=%p", l->key + 4,
+                       l->key + 4 + strlen(l->key + 4) + 1,
+                       cached_object));
+
+  DBUG_ASSERT(l->type == SHARED || l->type == EXCLUSIVE ||
+              l->type == SHARED_PENDING_UPGRADE);
+
+  /*
+    TODO: This assumption works now since we do mdl_get_cached_object()
+          and mdl_set_cached_object() in the same critical section. Once
+          this becomes false we will have to call release_hook here and
+          use additional mutex protecting 'cached_object' member.
+  */
+  DBUG_ASSERT(!l->lock->cached_object);
+
+  l->lock->cached_object= cached_object;
+  l->lock->cached_object_release_hook= release_hook;
+
+  DBUG_VOID_RETURN;
 }
diff -Nrup a/sql/meta_lock.h b/sql/meta_lock.h
--- a/sql/meta_lock.h	2007-08-22 00:43:29 +04:00
+++ b/sql/meta_lock.h	2007-10-17 14:28:35 +04:00
@@ -16,6 +16,7 @@
 /* TODO: Header guards! */
 
 struct MDL_EL;
+struct MDL_LOCK;
 
 
 /* Class representing owner/requestor of meta-data lock. */
@@ -40,8 +41,6 @@ enum enum_mdl_type {SHARED_PENDING=0, SH
 
   TODO: By using double linked lists instead of single linked lists
         we can make MDL code more simple and efficient.
-  TODO: Also it might be a nice idea to have a pointer to MDL_LOCK
-        object in MDL_EL class.
 */
 
 struct MDL_EL
@@ -53,6 +52,12 @@ struct MDL_EL
   MDL_EL      *next_context;
   /* Next element in the list of satisfied/pending requests for the lock. */
   MDL_EL      *next_lock;
+  /*
+    Pointer to the lock object for this lock request. Valid only if this lock
+    request is satisified or is present in the list of pending lock requests
+    for particular lock.
+  */
+  MDL_LOCK    *lock;
   MDL_CONTEXT *ctx;
   /* FIXME Belongs to MDL_CONTEXT */
   THD         *thd;
@@ -83,3 +88,8 @@ void mdl_release_lock(MDL_CONTEXT *conte
 void mdl_downgrade_exclusive_locks(MDL_CONTEXT *context);
 bool mdl_is_exclusive_lock_owner(MDL_CONTEXT *context, int type, const char *db,
                                  const char *name);
+
+typedef void (* mdl_cached_object_release_hook)(void *);
+void* mdl_get_cached_object(MDL_EL *l);
+void mdl_set_cached_object(MDL_EL *l, void *cached_object,
+                           mdl_cached_object_release_hook release_hook);
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2007-09-04 13:31:58 +04:00
+++ b/sql/sql_base.cc	2007-10-17 14:28:35 +04:00
@@ -675,6 +675,22 @@ TABLE_SHARE *get_cached_table_share(cons
 }  
 
 
+/**
+   @brief Mark table share as having one more user (increase its reference
+          count).
+
+   @param share Table share for which reference count should be increased.
+*/
+
+static void reference_table_share(TABLE_SHARE *share)
+{
+  DBUG_ASSERT(share->ref_count);
+  pthread_mutex_lock(&share->mutex);
+  share->ref_count++;
+  pthread_mutex_unlock(&share->mutex);
+}
+
+
 /*
   Close file handle, but leave the table in the table cache
 
@@ -995,7 +1011,9 @@ bool close_cached_tables(THD *thd, bool 
     /* Set version for table */
     for (TABLE *table=thd->open_tables; table ; table= table->next)
       table->s->version= refresh_version;
+    VOID(pthread_mutex_unlock(&LOCK_open));
     mdl_downgrade_exclusive_locks(&thd->mdl_context);
+    VOID(pthread_mutex_lock(&LOCK_open));
   }
   if (!have_lock)
     VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2137,6 +2155,20 @@ bool check_if_table_exists(THD *thd, TAB
 }
 
 
+/**
+   @brief Helper function used by MDL subsystem for releasing TABLE_SHARE
+          objects in cases when it no longer wants to cache reference to it.
+*/
+
+void table_share_release_hook(void *share)
+{
+  VOID(pthread_mutex_lock(&LOCK_open));
+  release_table_share((TABLE_SHARE*)share, RELEASE_NORMAL);
+  broadcast_refresh();
+  VOID(pthread_mutex_unlock(&LOCK_open));
+}
+
+
 /*
   Open a table.
 
@@ -2390,6 +2422,16 @@ TABLE *open_table(THD *thd, TABLE_LIST *
     }
   }
 
+  /*
+    Close HANDLER tables which are marked for flush.
+    TODO: What happens if we have pending DDL-lock for one of those tables?
+          Probably we should close them as well. Also since we no-longer do
+          waiting for name-lock/old-version to go away in the same critical
+          section we might need to do special tricks/checks before waiting.
+  */
+  if (thd->handler_tables)
+    mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, FALSE);
+
   VOID(pthread_mutex_lock(&LOCK_open));
 
   /*
@@ -2412,10 +2454,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *
     DBUG_RETURN(0);
   }
 
-  /* close handler tables which are marked for flush */
-  if (thd->handler_tables)
-    mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
-
   if (table_list->open_table_type == TABLE_LIST::OPEN_OR_CREATE)
   {
     bool exists;
@@ -2436,41 +2474,59 @@ TABLE *open_table(THD *thd, TABLE_LIST *
     DBUG_RETURN(0);
   }
 
-  /* QQ: Does it makes sense to move code below to separate function? */
-  if (!(share= get_table_share_with_create(thd, table_list, key,
-                                           key_length, OPEN_VIEW,
-                                           &error)))
-    goto err_unlock2;
-
-  if (share->is_view)
-  {
-    /* Open view */
-    if (open_new_frm(thd, share, alias,
-                     (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
-                             HA_GET_INDEX | HA_TRY_READ_ONLY),
-                     READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |
-                     (flags & OPEN_VIEW_NO_PARSE), thd->open_options,
-                     0, table_list, mem_root))
-      goto err_unlock;
-
-    /* TODO: Don't free this */
-    release_table_share(share, RELEASE_NORMAL);
+  if (!(share= (TABLE_SHARE *)mdl_get_cached_object(mdl)))
+  {
+    /* QQ: Does it makes sense to move code below to separate function? */
+    if (!(share= get_table_share_with_create(thd, table_list, key,
+                                             key_length, OPEN_VIEW,
+                                             &error)))
+      goto err_unlock2;
 
-    if (flags & OPEN_VIEW_NO_PARSE)
+    if (share->is_view)
     {
-      /*
-        VIEW not really opened, only frm were read.
-        Set 1 as a flag here
-      */
-      table_list->view= (st_lex*)1;
-    }
-    else
-    {
-      DBUG_ASSERT(table_list->view);
+      /* Open view */
+      if (open_new_frm(thd, share, alias,
+                       (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
+                               HA_GET_INDEX | HA_TRY_READ_ONLY),
+                       READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD |
+                       (flags & OPEN_VIEW_NO_PARSE), thd->open_options,
+                       0, table_list, mem_root))
+        goto err_unlock;
+
+      /* TODO: Don't free this */
+      release_table_share(share, RELEASE_NORMAL);
+
+      if (flags & OPEN_VIEW_NO_PARSE)
+      {
+        /*
+          VIEW not really opened, only frm were read.
+          Set 1 as a flag here
+        */
+        table_list->view= (st_lex*)1;
+      }
+      else
+      {
+        DBUG_ASSERT(table_list->view);
+      }
+
+      VOID(pthread_mutex_unlock(&LOCK_open));
+      DBUG_RETURN(0);
     }
 
-    VOID(pthread_mutex_unlock(&LOCK_open));
-    DBUG_RETURN(0);
+    /*
+      We are going to to store extra reference to the share in MDL-subsystem
+      so we need to increase reference counter;
+    */
+    reference_table_share(share);
+    mdl_set_cached_object(mdl, share, table_share_release_hook);
+  }
+  else
+  {
+    /*
+      We are going to use this share for construction of new TABLE object
+      so reference counter should be increased.
+    */
+    reference_table_share(share);
   }
 
   if (share->version != refresh_version)
@@ -2970,7 +3026,13 @@ bool table_is_used(TABLE *table, bool wa
 }
 
 
-/* Wait until all used tables are refreshed */
+/*
+  Wait until all used tables are refreshed.
+
+  FIXME We should remove this function since for several functions which
+        are invoked by it new scenarios of usage are introduced, while
+        this function implements optimization useful only in rare cases.
+*/
 
 bool wait_for_tables(THD *thd)
 {
diff -Nrup a/sql/sql_handler.cc b/sql/sql_handler.cc
--- a/sql/sql_handler.cc	2007-08-22 00:43:30 +04:00
+++ b/sql/sql_handler.cc	2007-10-17 14:28:35 +04:00
@@ -74,7 +74,8 @@ static enum enum_ha_read_modes rkey_to_r
   thd->handler_mdl_context= t2; \
   }
 
-static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags);
+static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags,
+                                bool is_locked);
 
 
 /*
@@ -656,7 +657,6 @@ int mysql_ha_flush(THD *thd, TABLE_LIST 
 {
   TABLE_LIST    *tmp_tables;
   TABLE         **table_ptr;
-  bool          did_lock= FALSE;
   DBUG_ENTER("mysql_ha_flush");
   DBUG_PRINT("enter", ("tables: 0x%lx  mode_flags: 0x%02x",
                        (long) tables, mode_flags));
@@ -684,13 +684,7 @@ int mysql_ha_flush(THD *thd, TABLE_LIST 
                              (*table_ptr)->s->db.str,
                              (*table_ptr)->s->table_name.str,
                              (*table_ptr)->alias));
-          /* The first time it is required, lock for close_thread_table(). */
-          if (! did_lock && ! is_locked)
-          {
-            VOID(pthread_mutex_lock(&LOCK_open));
-            did_lock= TRUE;
-          }
-          mysql_ha_flush_table(thd, table_ptr, mode_flags);
+          mysql_ha_flush_table(thd, table_ptr, mode_flags, is_locked);
           continue;
         }
         table_ptr= &(*table_ptr)->next;
@@ -708,23 +702,13 @@ int mysql_ha_flush(THD *thd, TABLE_LIST 
       if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
           (*table_ptr)->needs_reopen_or_name_lock())
       {
-        /* The first time it is required, lock for close_thread_table(). */
-        if (! did_lock && ! is_locked)
-        {
-          VOID(pthread_mutex_lock(&LOCK_open));
-          did_lock= TRUE;
-        }
-        mysql_ha_flush_table(thd, table_ptr, mode_flags);
+        mysql_ha_flush_table(thd, table_ptr, mode_flags, is_locked);
         continue;
       }
       table_ptr= &(*table_ptr)->next;
     }
   }
 
-  /* Release the lock if it was taken by this function. */
-  if (did_lock)
-    VOID(pthread_mutex_unlock(&LOCK_open));
-
   DBUG_RETURN(0);
 }
 
@@ -737,16 +721,24 @@ int mysql_ha_flush(THD *thd, TABLE_LIST 
     table                       The table to close.
     mode_flags                  MYSQL_HA_CLOSE_FINAL finally close the table.
                                 MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
+    is_locked                   TRUE if we already had LOCK_open locked.
 
   DESCRIPTION
     Broadcasts refresh if it closed the table.
     The caller must lock LOCK_open.
 
+  FIXME
+    is_locked parameter is temporary hack which should go away in the final
+    patch since cases when we have LOCK_open locked when calling this
+    function actually contradict assertion in MDL subsystem. See also
+    comment for wait_for_tables().
+
   RETURN
     0  ok
 */
 
-static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
+static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags,
+                                bool is_locked)
 {
   TABLE_LIST    *hash_tables;
   TABLE         *table= *table_ptr;
@@ -760,14 +752,17 @@ static int mysql_ha_flush_table(THD *thd
                                          (uchar*) table->alias,
                                          strlen(table->alias) + 1);
 
+  if (!is_locked)
+    pthread_mutex_lock(&LOCK_open);
   safe_mutex_assert_owner(&LOCK_open);
   (*table_ptr)->file->ha_index_or_rnd_end();
-  safe_mutex_assert_owner(&LOCK_open);
   if (close_thread_table(thd, table_ptr))
   {
     /* Tell threads waiting for refresh that something has happened */
     broadcast_refresh();
   }
+  if (!is_locked)
+    pthread_mutex_unlock(&LOCK_open);
   mdl_release_lock(&thd->handler_mdl_context, mdl);
 
   if (hash_tables)
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc	2007-08-29 23:30:00 +04:00
+++ b/sql/sql_table.cc	2007-10-17 14:28:35 +04:00
@@ -5788,13 +5788,14 @@ bool mysql_alter_table(THD *thd,char *ne
 
     if (wait_if_global_read_lock(thd,0,1))
       DBUG_RETURN(TRUE);
-    VOID(pthread_mutex_lock(&LOCK_open));
     if (lock_table_names(thd, table_list))
     {
       error= 1;
       goto view_err;
     }
-    
+
+    VOID(pthread_mutex_lock(&LOCK_open));
+
     if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
     {
       if (mysql_bin_log.is_open())
@@ -5805,11 +5806,11 @@ bool mysql_alter_table(THD *thd,char *ne
       }
       send_ok(thd);
     }
+    pthread_mutex_unlock(&LOCK_open);
 
     unlock_table_names(thd);
 
 view_err:
-    pthread_mutex_unlock(&LOCK_open);
     start_waiting_global_read_lock(thd);
     DBUG_RETURN(error);
   }
Thread
bk commit into 5.1 tree (dlenev:1.2579)dlenev17 Oct