List:Commits« Previous MessageNext Message »
From:Chuck Bell Date:June 20 2008 1:59pm
Subject:bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749,
Bug#36778, Bug#36782
View as plain text  
#At file:///D:/source/bzr/mysql-6.0-bug-36749/

 2618 Chuck Bell	2008-06-20
      BUG#36749 Data Loss after Restore, if Trigger fired on the table that is being Restored. 
      
      Backup kernel should lock all tables during restore but it was not doing so
      for native drivers. This caused the MyISAM storage engine to return incorrect 
      and loss of data when tables were being restored.
      
      Note: This patch also fixes BUG#36778 and BUG#36782.
added:
  mysql-test/r/backup_lock_myisam.result
  mysql-test/t/backup_lock_myisam.test
modified:
  sql/backup/data_backup.cc
  sql/backup/image_info.h
  sql/share/errmsg.txt
  sql/si_objects.cc
  sql/si_objects.h

per-file messages:
  mysql-test/r/backup_lock_myisam.result
    New result file.
  mysql-test/t/backup_lock_myisam.test
    New test for MyISAM locking problem.
  sql/backup/data_backup.cc
    Added code to obtain name locks on all tables prior to restore and release them after
    restore. Code includes method to gather tables from all snapshots.
  sql/backup/image_info.h
    Needed to expose Tables class for retrieving list of tables for lock.
  sql/share/errmsg.txt
    New error messages added.
  sql/si_objects.cc
    Added new class to manage name lock on a table list. Class was needed
    to preserve state between get_ and release_ of locks.
  sql/si_objects.h
    Added primitives for new name locking class.
=== added file 'mysql-test/r/backup_lock_myisam.result'
--- a/mysql-test/r/backup_lock_myisam.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_lock_myisam.result	2008-06-20 13:59:11 +0000
@@ -0,0 +1,188 @@
+SET DEBUG_SYNC= 'RESET';
+From con1:
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+DROP DATABASE IF EXISTS db3;
+Create database 1 and a table then populate it
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT) ENGINE=MYISAM;
+INSERT INTO db1.t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(0);
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+CREATE TABLE db1.t2 (a int) ENGINE=MEMORY;
+INSERT INTO db1.t2 VALUES (1),(2),(3),(4),(5);
+CREATE TABLE db1.t3 (a int) ENGINE=INNODB;
+INSERT INTO db1.t3 VALUES (11),(12),(13);
+Show initial count of table
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+327680
+SELECT COUNT(*) FROM db1.t2;
+COUNT(*)
+5
+SELECT COUNT(*) FROM db1.t3;
+COUNT(*)
+3
+From con2:
+Create database 2 and a table then populate it and add a trigger
+that updates the table in database 1
+CREATE DATABASE db2;
+CREATE TABLE db2.t2 (A INT);
+CREATE TRIGGER db2.trg AFTER INSERT ON db2.t2 FOR EACH ROW
+BEGIN
+INSERT INTO db1.t1 VALUES ('99');
+END|
+From con1:
+Now do the backup 
+BACKUP DATABASE db1 TO 'db1.bak';
+backup_id
+#
+DROP DATABASE db1;
+now start the restore and while the restore is running, fire the trigger
+activate synchronization points for restore.
+SET DEBUG_SYNC= 'restore_in_progress SIGNAL wait_for_restore WAIT_FOR finish';
+RESTORE FROM 'db1.bak';
+From breakpoints:
+Wait for restore to reach its synchronization point.
+SET DEBUG_SYNC= 'now WAIT_FOR wait_for_restore';
+breakpoints: Show process list.
+SELECT id, command, state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "RESTORE%";
+From con2:
+Now do the insert while restore is running.
+INSERT INTO db2.t2 VALUES (0);
+From breakpoints:
+breakpoints: Sending finish signal to wake restore.
+SET DEBUG_SYNC= 'now SIGNAL finish';
+Reattach to connection 2 and finish.
+Reattach to connection 1 and finish.
+backup_id
+#
+Show the count for t1. It should be 1 more than before restore.
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+327681
+SELECT * FROM db1.t2;
+a
+1
+2
+3
+4
+5
+SELECT * FROM db1.t3;
+a
+11
+12
+13
+SET DEBUG_SYNC= 'RESET';
+DELETE FROM db2.t2;
+now start the restore and while the restore is running, fire the trigger
+activate synchronization points for restore.
+SET DEBUG_SYNC= 'restore_in_progress SIGNAL wait_for_restore WAIT_FOR finish';
+RESTORE FROM 'db1.bak';
+From breakpoints:
+Wait for restore to reach its synchronization point.
+SET DEBUG_SYNC= 'now WAIT_FOR wait_for_restore';
+breakpoints: Show process list.
+SELECT id, command, state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "RESTORE%";
+From con2:
+Now do the select while restore is running.
+SELECT * FROM db1.t1 limit 10;
+From breakpoints:
+breakpoints: Sending finish signal to wake restore.
+SET DEBUG_SYNC= 'now SIGNAL finish';
+Reattach to connection 2 and finish.
+a
+1
+2
+3
+4
+5
+6
+7
+8
+9
+0
+Reattach to connection 1 and finish.
+backup_id
+#
+Show the count for t1. It should be the same as before restore.
+SELECT COUNT(*) FROM db1.t1;
+COUNT(*)
+327680
+SELECT * FROM db1.t2;
+a
+1
+2
+3
+4
+5
+SELECT * FROM db1.t3;
+a
+11
+12
+13
+SET DEBUG_SYNC= 'RESET';
+Create a database with a table and a view using the MyISAM engine.
+CREATE DATABASE db3;
+CREATE TABLE db3.t1(name CHAR(10)) ENGINE=MYISAM;
+INSERT INTO db3.t1 VALUES('A'),('B'),('C'),('D');
+CREATE VIEW db3.v1 AS SELECT * FROM db3.t1;
+Show the data before backup
+SELECT * FROM db3.t1;
+name
+A
+B
+C
+D
+SELECT * FROM db3.v1;
+name
+A
+B
+C
+D
+Backup the database.
+BACKUP DATABASE db3 TO 'db3.bak';
+backup_id
+#
+Now drop then restore the database.
+DROP DATABASE db3;
+RESTORE FROM 'db3.bak';
+backup_id
+#
+Show the table and view.
+SHOW FULL TABLES FROM db3;
+Tables_in_db3	Table_type
+t1	BASE TABLE
+v1	VIEW
+Show the data after restore.
+SELECT * FROM db3.v1;
+name
+A
+B
+C
+D
+SELECT * FROM db3.t1;
+name
+A
+B
+C
+D
+cleanup
+DROP DATABASE db1;
+DROP DATABASE db2;
+DROP DATABASE db3;

=== added file 'mysql-test/t/backup_lock_myisam.test'
--- a/mysql-test/t/backup_lock_myisam.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_lock_myisam.test	2008-06-20 13:59:11 +0000
@@ -0,0 +1,229 @@
+#
+# This test was created to ensure appropriate locks are obtained on the myisam
+# tables during a myisam native driver restore. See BUG#36749.
+#
+# The test uses two connections and debug synchronization to ensure the restore
+# in the middle of processing when a trigger attempts to insert data.
+#
+
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+SET DEBUG_SYNC= 'RESET';
+
+connect(con1, localhost, root,,);
+connect(con2, localhost, root,,);
+connect(breakpoints, localhost, root,,);
+
+--echo From con1:
+--connection con1
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+DROP DATABASE IF EXISTS db2;
+DROP DATABASE IF EXISTS db3;
+--enable_warnings
+
+--error 0, 1
+--remove_file $MYSQLTEST_VARDIR/master-data/db1.bak
+
+--error 0, 1
+--remove_file $MYSQLTEST_VARDIR/master-data/db3.bak
+
+--echo Create database 1 and a table then populate it
+CREATE DATABASE db1;
+CREATE TABLE db1.t1 (a INT) ENGINE=MYISAM;
+
+INSERT INTO db1.t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(0);
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+INSERT INTO db1.t1 SELECT * FROM db1.t1;
+
+CREATE TABLE db1.t2 (a int) ENGINE=MEMORY;
+
+INSERT INTO db1.t2 VALUES (1),(2),(3),(4),(5);
+
+CREATE TABLE db1.t3 (a int) ENGINE=INNODB;
+
+INSERT INTO db1.t3 VALUES (11),(12),(13);
+
+--echo Show initial count of table
+SELECT COUNT(*) FROM db1.t1;
+
+SELECT COUNT(*) FROM db1.t2;
+
+SELECT COUNT(*) FROM db1.t3;
+
+--echo From con2:
+--connection con2
+
+--echo Create database 2 and a table then populate it and add a trigger
+--echo that updates the table in database 1
+
+CREATE DATABASE db2;
+CREATE TABLE db2.t2 (A INT);
+
+DELIMITER |;
+
+CREATE TRIGGER db2.trg AFTER INSERT ON db2.t2 FOR EACH ROW
+BEGIN
+  INSERT INTO db1.t1 VALUES ('99');
+END|
+
+delimiter ;|
+
+--echo From con1:
+--connection con1
+
+--echo Now do the backup 
+--replace_column 1 #
+BACKUP DATABASE db1 TO 'db1.bak';
+
+DROP DATABASE db1;
+
+--echo now start the restore and while the restore is running, fire the trigger
+--echo activate synchronization points for restore.
+SET DEBUG_SYNC= 'restore_in_progress SIGNAL wait_for_restore WAIT_FOR finish';
+--send RESTORE FROM 'db1.bak'
+
+--echo From breakpoints:
+--connection breakpoints
+--echo Wait for restore to reach its synchronization point.
+SET DEBUG_SYNC= 'now WAIT_FOR wait_for_restore';
+
+--echo breakpoints: Show process list.
+--replace_column 1 #
+query_vertical SELECT id, command, state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "RESTORE%";
+
+--echo From con2:
+--connection con2
+--echo Now do the insert while restore is running.
+send INSERT INTO db2.t2 VALUES (0);
+
+--echo From breakpoints:
+--connection breakpoints
+--echo breakpoints: Sending finish signal to wake restore.
+SET DEBUG_SYNC= 'now SIGNAL finish';
+
+--echo Reattach to connection 2 and finish.
+--connection con2
+--reap
+
+--echo Reattach to connection 1 and finish.
+--connection con1
+--replace_column 1 #
+--reap
+
+--echo Show the count for t1. It should be 1 more than before restore.
+SELECT COUNT(*) FROM db1.t1;
+
+SELECT * FROM db1.t2;
+
+SELECT * FROM db1.t3;
+
+SET DEBUG_SYNC= 'RESET';
+
+#
+# BUG#36778 - Data loss during select at time of restore.
+#
+
+DELETE FROM db2.t2;
+
+--echo now start the restore and while the restore is running, fire the trigger
+--echo activate synchronization points for restore.
+SET DEBUG_SYNC= 'restore_in_progress SIGNAL wait_for_restore WAIT_FOR finish';
+--send RESTORE FROM 'db1.bak'
+
+--echo From breakpoints:
+--connection breakpoints
+--echo Wait for restore to reach its synchronization point.
+SET DEBUG_SYNC= 'now WAIT_FOR wait_for_restore';
+
+--echo breakpoints: Show process list.
+--replace_column 1 #
+query_vertical SELECT id, command, state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "RESTORE%";
+
+--echo From con2:
+--connection con2
+--echo Now do the select while restore is running.
+send SELECT * FROM db1.t1 limit 10;
+
+--echo From breakpoints:
+--connection breakpoints
+--echo breakpoints: Sending finish signal to wake restore.
+SET DEBUG_SYNC= 'now SIGNAL finish';
+
+--echo Reattach to connection 2 and finish.
+--connection con2
+--reap
+
+--echo Reattach to connection 1 and finish.
+--connection con1
+--replace_column 1 #
+--reap
+
+--echo Show the count for t1. It should be the same as before restore.
+SELECT COUNT(*) FROM db1.t1;
+
+SELECT * FROM db1.t2;
+
+SELECT * FROM db1.t3;
+
+SET DEBUG_SYNC= 'RESET';
+
+#
+# BUG#36782 - Data loss with restore of view.
+#
+
+--echo Create a database with a table and a view using the MyISAM engine.
+CREATE DATABASE db3;
+CREATE TABLE db3.t1(name CHAR(10)) ENGINE=MYISAM;
+INSERT INTO db3.t1 VALUES('A'),('B'),('C'),('D');
+CREATE VIEW db3.v1 AS SELECT * FROM db3.t1;
+
+--echo Show the data before backup
+SELECT * FROM db3.t1;
+SELECT * FROM db3.v1;
+
+--echo Backup the database.
+--replace_column 1 #
+BACKUP DATABASE db3 TO 'db3.bak';
+
+--echo Now drop then restore the database.
+DROP DATABASE db3;
+--replace_column 1 #
+RESTORE FROM 'db3.bak';
+
+--echo Show the table and view.
+SHOW FULL TABLES FROM db3;
+
+--echo Show the data after restore.
+SELECT * FROM db3.v1;
+SELECT * FROM db3.t1;
+
+--echo cleanup
+DROP DATABASE db1;
+DROP DATABASE db2;
+DROP DATABASE db3;
+
+--error 0, 1
+--remove_file $MYSQLTEST_VARDIR/master-data/db1.bak
+
+--error 0, 1
+--remove_file $MYSQLTEST_VARDIR/master-data/db3.bak

=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc	2008-05-05 15:03:24 +0000
+++ b/sql/backup/data_backup.cc	2008-06-20 13:59:11 +0000
@@ -1364,7 +1364,7 @@ namespace backup {
 /**
   Read backup image data from a backup stream and forward it to restore drivers.
  */
-int restore_table_data(THD*, Restore_info &info, Input_stream &s)
+int restore_table_data(THD *thd, Restore_info &info, Input_stream &s)
 {
   DBUG_ENTER("restore::restore_table_data");
 
@@ -1377,6 +1377,8 @@ int restore_table_data(THD*, Restore_inf
 
   TABLE_LIST *table_list= 0;
   TABLE_LIST *table_list_last= 0;
+  List<obs::Obj> tables_to_lock;
+  obs::Name_locker *table_name_locker= new obs::Name_locker(thd);
 
   if (info.snap_count() > 256)
   {
@@ -1412,6 +1414,15 @@ int restore_table_data(THD*, Restore_inf
         (snap->type() == Snapshot_info::CS_SNAPSHOT))
       get_default_snapshot_tables(NULL, (default_backup::Restore *)drv[n],
                                   &table_list, &table_list_last);
+    /*
+      Collect tables from all drivers for name locking.
+    */
+    Image_info::Tables *snap_table_list= snap->get_table_list();
+    for (uint i= 0; i < snap_table_list->count(); i++)
+    {
+      Image_info::Table *tbl= snap_table_list->get_table(i);
+      tables_to_lock.push_front(tbl->m_obj_ptr);
+    }
   }
 
   /*
@@ -1430,6 +1441,15 @@ int restore_table_data(THD*, Restore_inf
       table_list_last->next_global= NULL; // break lists
   }
 
+  /*
+    Apply name locks to all tables used.
+  */
+  if (table_name_locker->get_name_locks(&tables_to_lock, TL_WRITE))
+  {
+    info.m_ctx.fatal_error(ER_BACKUP_OBTAIN_NAME_LOCK_FAILED);
+    goto error;
+  }
+
   // Initialize the drivers.
   for (uint n=0; n < info.snap_count(); ++n)
   {
@@ -1441,6 +1461,7 @@ int restore_table_data(THD*, Restore_inf
     }
   }
 
+  DEBUG_SYNC(thd, "restore_in_progress");
   {
     Buffer  buf;
     uint    snap_num=0;
@@ -1592,6 +1613,13 @@ int restore_table_data(THD*, Restore_inf
   }
 
   /*
+    Release name locks on driver tables.
+  */
+  if (table_name_locker->release_name_locks())
+    info.m_ctx.fatal_error(ER_BACKUP_RELEASE_NAME_LOCK_FAILED);
+  delete table_name_locker;
+
+  /*
     Close all tables if default or snapshot driver used.
   */
   if (table_list)
@@ -1602,6 +1630,9 @@ int restore_table_data(THD*, Restore_inf
  error:
 
   DBUG_PRINT("restore",("Cancelling restore process"));
+
+  if (table_name_locker)
+    delete table_name_locker;
 
   for (uint n=0; n < info.snap_count(); ++n)
   {

=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h	2008-05-05 15:06:40 +0000
+++ b/sql/backup/image_info.h	2008-06-20 13:59:11 +0000
@@ -132,9 +132,10 @@ public: // public interface
   Image_info();
   uint m_table_count;
 
+  class Tables; ///< Implementation of Table_list interface. 
+
  private:
 
-  class Tables; ///< Implementation of Table_list interface. 
 
   // storage
 
@@ -260,6 +261,8 @@ class Snapshot_info
   virtual result_t get_restore_driver(Restore_driver*&) =0;
 
   virtual ~Snapshot_info();
+
+  Image_info::Tables *get_table_list() { return &m_tables; }
 
  protected:
  

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-05-05 19:38:05 +0000
+++ b/sql/share/errmsg.txt	2008-06-20 13:59:11 +0000
@@ -6357,3 +6357,8 @@ ER_DEBUG_SYNC_HIT_LIMIT
   eng "debug sync point hit limit reached"
   ger "Debug Sync Point Hit Limit erreicht"
 
+ER_BACKUP_OBTAIN_NAME_LOCK_FAILED
+  eng "Restore failed to obtain the name locks on the tables."
+ER_BACKUP_RELEASE_NAME_LOCK_FAILED
+  eng "Restore failed to release the name locks on the tables."
+

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2008-05-05 20:19:03 +0000
+++ b/sql/si_objects.cc	2008-06-20 13:59:11 +0000
@@ -3071,6 +3071,96 @@ void ddl_blocker_exception_off(THD *thd)
   DBUG_VOID_RETURN;
 }
 
+/**
+  Build a table list from a list of tables as class Obj.
+
+  This method creates a TABLE_LIST from a List<> of type Obj.
+
+  param[IN]  tables    The list of tables
+  param[IN]  lock      The desired lock type
+
+  @returns TABLE_LIST *
+
+  @note Caller must free memory.
+*/
+TABLE_LIST *Name_locker::build_table_list(List<Obj> *tables,
+                                          thr_lock_type lock)
+{
+  TABLE_LIST *tl= NULL;
+  Obj *tbl= NULL;
+  DBUG_ENTER("Name_locker::build_table_list()");
+  
+  List_iterator<Obj> it(*tables);
+  while (tbl= it++)
+  {
+    TABLE_LIST *ptr= (TABLE_LIST*)my_malloc(sizeof(TABLE_LIST), MYF(MY_WME));
+    DBUG_ASSERT(ptr);  // FIXME: report error instead
+    bzero(ptr, sizeof(TABLE_LIST));
+
+    ptr->alias= ptr->table_name= const_cast<char*>(tbl->get_name()->ptr());
+    ptr->db= const_cast<char*>(tbl->get_db_name()->ptr());
+    ptr->lock_type= lock;
+
+    // and add it to the list
+
+    ptr->next_global= ptr->next_local=
+      ptr->next_name_resolution_table= tl;
+    tl= ptr;
+    tl->table= ptr->table;
+  }
+
+  DBUG_RETURN(tl);
+}
+
+/**
+  Gets name locks on table list.
+
+  This method attempts to take an exclusive name lock on each table in the
+  list. It does nothing if the table list is empty.
+
+  @param[IN] tables  The list of tables to lock.
+  @param[IN] lock    The type of lock to take.
+
+  @returns 0 if success, 1 if error
+*/
+int Name_locker::get_name_locks(List<Obj> *tables, thr_lock_type lock)
+{
+  int ret= 0;
+  DBUG_ENTER("Name_locker::get_name_locks()");
+  /*
+    Convert List<Obj> to TABLE_LIST *
+  */
+  m_table_list= build_table_list(tables, lock);
+  if (m_table_list)
+  {
+    pthread_mutex_lock(&LOCK_open);
+    if (lock_table_names_exclusively(m_thd, m_table_list))
+      ret= 1;
+    pthread_mutex_unlock(&LOCK_open);
+  }
+  DBUG_RETURN(ret);
+}
+
+/*
+  Releases name locks on table list.
+
+  This method releases the name locks on the table list. It does nothing if
+  the table list is empty.
+
+  @returns 0 if success, 1 if error
+*/
+int Name_locker::release_name_locks()
+{
+  DBUG_ENTER("Name_locker::release_name_locks()");
+  if (m_table_list)
+  {
+    pthread_mutex_lock(&LOCK_open);
+    unlock_table_names(m_thd, m_table_list, (TABLE_LIST*) 0);
+    pthread_mutex_unlock(&LOCK_open);
+ }
+  DBUG_RETURN(0);
+}
+
 } // obs namespace
 
 ///////////////////////////////////////////////////////////////////////////

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2008-05-05 15:03:24 +0000
+++ b/sql/si_objects.h	2008-06-20 13:59:11 +0000
@@ -604,6 +604,38 @@ COND *create_db_select_condition(THD *th
                                  TABLE *t,
                                  List<LEX_STRING> *db_list);
 
+/*
+  The following class is used to manage name locks on a list of tables.
+
+  This class uses a list of type List<Obj> to establish the table list 
+  that will be used to manage locks on the tables.
+*/
+class Name_locker
+{
+public:
+  Name_locker(THD *thd) { m_thd= thd; }
+  ~Name_locker() { my_free(m_table_list, MYF(0)); }
+
+  /*
+    Gets name locks on table list.
+  */
+  int get_name_locks(List<Obj> *tables, thr_lock_type lock);
+
+  /*
+    Releases name locks on table list.
+  */
+  int release_name_locks();
+
+private:
+  TABLE_LIST *m_table_list; ///< The list of tables to obtain locks on.
+  THD *m_thd;               ///< Thread context.
+
+  /*
+    Builds a table list from the list of objects passed to constructor.
+  */
+  TABLE_LIST *build_table_list(List<Obj> *tables, thr_lock_type lock);
+};
+
 } // obs namespace
 
 #endif // SI_OBJECTS_H_

Thread
bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749,Bug#36778, Bug#36782Chuck Bell20 Jun
  • Re: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749,Bug#36778, Bug#36782Rafal Somla23 Jun
    • RE: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749, Bug#36778, Bug#36782Chuck Bell23 Jun
    • RE: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749, Bug#36778, Bug#36782Chuck Bell23 Jun
      • Re: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618) Bug#36749,Bug#36778, Bug#36782Rafal Somla24 Jun
  • Re: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618)Bug#36749, Bug#36778, Bug#36782Jørgen Løland23 Jun