List:Commits« Previous MessageNext Message »
From:Jørgen Løland Date:June 23 2008 5:17pm
Subject:Re: bzr commit into mysql-6.0-backup-myisam branch (cbell:2618)
Bug#36749, Bug#36778, Bug#36782
View as plain text  
Patch approved. Test cases have not changed since last review and have 
already been approved.

Chuck Bell wrote:
> #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_
> 
> 


-- 
Jørgen Løland
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