From e3b3907c4f6f6dbfd650272e7c65880d04e5789e Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@sun.com>
Date: Wed, 2 Dec 2009 19:15:40 +0300
Subject: Backport of:
 ------------------------------------------------------------ revno: 2630.4.32
 committer: Dmitry Lenev <dlenev@mysql.com> branch nick: mysql-6.0-3726-w2
 timestamp: Thu 2008-06-19 16:39:58 +0400 message:   WL#3726 "DDL locking for
 all metadata objects".

  After-review fixes in progress.

  Ensure that metadata locking subsystem properly handles
  out-of-memory conditions. Clarified MDL interface by
  separating release of locks and removal of lock requests
  from the context.

sql/lock.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/mdl.cc:
  Ensured that metadata locking subsystem properly handles
  out-of-memory conditions.
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired
  and we have not associated request with object respesenting
  lock.

  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to
  emphasize that it also actually removes lock requests
  from the context.

  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/mdl.h:
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired
  and we have not associated request with object respesenting
  lock.

  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to
  emphasize that it also actually removes lock requests
  from the context.

  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/sql_base.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Also adjusted open_table() to ensure that it
  releases/removes metadata locks in case of error
  after adding/acquiring them (unless keeping these
  lock requests is required for recovering action).
sql/sql_delete.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_handler.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_show.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_table.cc:
  Renamed mdl_release_all_locks_for_name() to emphasize
  that it also actually removes lock requests from the context.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
---
 sql/sql_delete.cc | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'sql/sql_delete.cc')

diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 630cf73076c..4827d48e1c5 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -1170,7 +1170,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
     mdl_set_lock_type(mdl_lock_data, MDL_EXCLUSIVE);
     mdl_add_lock(&thd->mdl_context, mdl_lock_data);
     if (mdl_acquire_exclusive_locks(&thd->mdl_context))
+    {
+      mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
       DBUG_RETURN(TRUE);
+    }
     pthread_mutex_lock(&LOCK_open);
     tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db,
                      table_list->table_name);
@@ -1200,12 +1203,18 @@ end:
       my_ok(thd);		// This should return record count
     }
     if (mdl_lock_data)
+    {
       mdl_release_lock(&thd->mdl_context, mdl_lock_data);
+      mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
+    }
   }
   else if (error)
   {
     if (mdl_lock_data)
+    {
       mdl_release_lock(&thd->mdl_context, mdl_lock_data);
+      mdl_remove_lock(&thd->mdl_context, mdl_lock_data);
+    }
   }
   DBUG_RETURN(error);
 
-- 
cgit v1.2.1