List:Commits« Previous MessageNext Message »
From:Jorgen Loland Date:November 26 2009 9:52am
Subject:bzr commit into mysql-6.0-backup branch (jorgen.loland:2896) Bug#44568
View as plain text  
#At file:///localhome/jl208045/mysql/backup-brances/mysql-6.0-backup-44568/ based on revid:rafal.somla@stripped

 2896 Jorgen Loland	2009-11-26
      Bug#44568: Online backup 'waiting' while load executed 
            
      To make a transaction consistent backup image across all tables
      and storage engines, backup needs to block commits during the
      synchronization phase. Previously, this was achieved by using
      global read lock (GRL). However, GRL was not intended for this
      usage and has some serious disadvantages:
       - backup did not use it as it was meant to be used, and GRL
         will therefore starve backup even with few concurrent 
         transactions
       - backup only needs to block commits/be blocked by commits.
         Backup's usage of GRL blocked DMLs. 
      
      This patch contains a temporary solution to the problem. It 
      changes the backup metadata locking to a more generic backup
      shared/exclusive locking mechanism that is used for both
      BML and commit blocking. Compared to using GRL for commit 
      blocking, much fewer operations are blocked (only commits vs
      whole transactions starting from it's first DML statement).
      Further, the starvation of backup by concurrent transactions 
      is removed because the locking mechanism orders lock requests 
      FIFO.
      
      The patch is a temporary solution because the locking mechanism
      will most likely be replaced by MetaDataLocking later. There are
      plans for scoped locks in MDL, which will make backup block
      commits only in the tables being backed up.
     @ mysql-test/suite/backup/include/backup_vp_nontx.inc
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/include/bml_test.inc
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/r/backup_bml_block.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_bml_not_falcon.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_errors.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_errors_compression.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_snapshot.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_timeout.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_triggers_and_events.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_vp_nontx_memory.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_vp_nontx_myisam.result
        Recorded new test output.
     @ mysql-test/suite/backup/r/backup_vp_tx.result
        Recorded new test output.
     @ mysql-test/suite/backup/t/backup_bml.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_bml_block.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_errors.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_snapshot.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_timeout.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_triggers_and_events.test
        Change test and sync points to work with new commit blocker.
     @ mysql-test/suite/backup/t/backup_vp_tx.test
        Change test and sync points to work with new commit blocker.
     @ sql/backup/be_default.cc
        Incorrect optimization removed. Caused too early lock release
        because locking thread was killed.
     @ sql/backup/data_backup.cc
        Change backup to use new commit blocker instead of GRL
     @ sql/bml.cc
        Refactor BML to become more generic backup shared/exclusive
        locking mechanism. This will be used both for backup metadata
        locking and commit blocking.
     @ sql/bml.h
        Refactor BML to become more generic backup shared/exclusive
        locking mechanism. This will be used both for backup metadata
        locking and commit blocking.
     @ sql/handler.cc
        Acquire and release shared backup commit blocker lock when
        committing.
     @ sql/mysqld.cc
        Instanciate backup metadata locks and backup commit blocker
        locking instances.
     @ sql/si_objects.cc
        Add functions for setting and releasing backup commit blocker.
        Also removed BML_exception since Backup_sx_locks allows the 
        thread owning X lock to set S lock, thus making BML_exception
        redundant.
     @ sql/si_objects.h
        Add functions for setting and releasing backup commit blocker.
        Also removed BML_exception since Backup_sx_locks allows the 
        thread owning X lock to set S lock, thus making BML_exception
        redundant.
     @ sql/sql_class.cc
        Removed BML_exception flag since Backup_sx_locks allows the 
        thread owning X lock to set S lock, thus making BML_exception
        redundant.
     @ sql/sql_class.h
        Removed BML_exception flag since Backup_sx_locks allows the 
        thread owning X lock to set S lock, thus making BML_exception
        redundant.
     @ sql/sql_parse.cc
        BML_class changed name to Backup_sx_lock

    modified:
      mysql-test/suite/backup/include/backup_vp_nontx.inc
      mysql-test/suite/backup/include/bml_test.inc
      mysql-test/suite/backup/r/backup_bml_block.result
      mysql-test/suite/backup/r/backup_bml_not_falcon.result
      mysql-test/suite/backup/r/backup_errors.result
      mysql-test/suite/backup/r/backup_errors_compression.result
      mysql-test/suite/backup/r/backup_snapshot.result
      mysql-test/suite/backup/r/backup_timeout.result
      mysql-test/suite/backup/r/backup_triggers_and_events.result
      mysql-test/suite/backup/r/backup_vp_nontx_memory.result
      mysql-test/suite/backup/r/backup_vp_nontx_myisam.result
      mysql-test/suite/backup/r/backup_vp_tx.result
      mysql-test/suite/backup/t/backup_bml.test
      mysql-test/suite/backup/t/backup_bml_block.test
      mysql-test/suite/backup/t/backup_errors.test
      mysql-test/suite/backup/t/backup_snapshot.test
      mysql-test/suite/backup/t/backup_timeout.test
      mysql-test/suite/backup/t/backup_triggers_and_events.test
      mysql-test/suite/backup/t/backup_vp_tx.test
      sql/backup/be_default.cc
      sql/backup/data_backup.cc
      sql/bml.cc
      sql/bml.h
      sql/handler.cc
      sql/mysqld.cc
      sql/si_objects.cc
      sql/si_objects.h
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_parse.cc
=== modified file 'mysql-test/suite/backup/include/backup_vp_nontx.inc'
--- a/mysql-test/suite/backup/include/backup_vp_nontx.inc	2009-05-26 23:26:33 +0000
+++ b/mysql-test/suite/backup/include/backup_vp_nontx.inc	2009-11-26 09:52:48 +0000
@@ -119,6 +119,7 @@ SELECT * FROM bup_vp.t1 ORDER BY col_a;
 --echo # Connection con_bup
 --echo #
 connection con_bup;
+SET DEBUG_SYNC= 'now WAIT_FOR insert_started';
 
 # Backup will be blocked from setting CB by the ongoing insert in
 # con_ntx1. Backup will signal con_ntx1 that it has been blocked. The
@@ -131,8 +132,16 @@ connection con_bup;
 # complete.
 
 --echo # con_bup: Activate synchronization points for BACKUP.
---echo # Signal when backup is blocked by ongoing insert in con_ntx1
-SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL sync_complete_insert';
+
+--echo # Backup should not reach after_backup_validated because
+--echo # this happens after getting the table lock (blocked by the insert)
+--echo # There's no way to use DEBUG_SYNC to check if BACKUP is waiting for 
+--echo # the table lock since BACKUP tries to get this lock in a separate
+--echo # thread. Here, we signal from a sync point BACKUP should not be able
+--echo # to reach due to the lock set by the insert above. Further down, 
+--echo # we listen for this signal and expect to timeout.
+
+SET DEBUG_SYNC= 'after_backup_validated SIGNAL backup_got_too_far';
 
 --echo # ntx1 insert is completed, so backup can set CB. Just before reaching
 --echo # VP, signal ntx2 should try to insert. Wait until ntx2 signals it has
@@ -152,8 +161,11 @@ send BACKUP DATABASE bup_vp TO "bup_vp.b
 --echo # Connection sync
 --echo #
 connection con_sync;
-SET DEBUG_SYNC= 'now WAIT_FOR sync_complete_insert';
---echo # Backup has been blocked by ongoing insert
+--echo # Here we listen for the signal that BACKUP *should not send*! 
+--echo # If this does not timeout and produce a warning, BACKUP got the 
+--echo # table lock it shouldn't have gotten!
+--replace_regex /[0-9]{4}/#/
+SET DEBUG_SYNC= 'now WAIT_FOR backup_got_too_far TIMEOUT 4';
 
 --echo # cannot test with select that insert has not completed ntx1 has X-lock
 SET DEBUG_SYNC= 'now SIGNAL complete_insert';
@@ -182,7 +194,7 @@ SET DEBUG_SYNC= 'now SIGNAL complete_ins
     # Wait for backup to set CB
     SET DEBUG_SYNC= 'now WAIT_FOR try_insert';
     # Signal to backup that the insert is blocked
-    SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL sync_insert_blocked';
+    SET DEBUG_SYNC= 'wait_for_lock SIGNAL sync_insert_blocked';
     send INSERT INTO bup_vp.t1 VALUES ("ntx2: Should NOT be in backup");
 
     # INSERT is blocked until CB has been released
@@ -193,9 +205,14 @@ SET DEBUG_SYNC= 'now SIGNAL complete_ins
 connection con_sync;
 SET DEBUG_SYNC= 'now WAIT_FOR sync_insert_blocked';
 
---echo # Insert in ntx2 is blocked and should not be in t1; Should be 0 records
-SELECT * FROM bup_vp.t1 WHERE col_a like 'ntx2%';
---echo 
+if (`SELECT '$engine'='MyISAM'`)
+{   
+  # With MEMORY engine, this select is blocked by the INSERT 
+  # waiting for the lock.
+  --echo # Insert in ntx2 is blocked and should not be in t1; Should be 0 records
+  SELECT * FROM bup_vp.t1 WHERE col_a like 'ntx2%';
+  --echo 
+}
 
 SET DEBUG_SYNC= 'now SIGNAL insert_blocked';
 
@@ -207,8 +224,20 @@ SET DEBUG_SYNC= 'now SIGNAL insert_block
   --echo # Scenario(d): Backup has now released CB. Perform insert
   # Double-check that backup has reached sync point after CB release
   SET DEBUG_SYNC= 'now WAIT_FOR commit_unblocked';
-  INSERT INTO bup_vp.t1 VALUES ("ntx1: Should NOT be in backup");
-  SET DEBUG_SYNC= 'now SIGNAL finish_bup';
+
+  if (`SELECT '$engine'='MyISAM'`)
+  {   
+    # MyISAM tables have been unlocked, so INSERT passes just fine
+    INSERT INTO bup_vp.t1 VALUES ("ntx1: Should NOT be in backup");
+    SET DEBUG_SYNC= 'now SIGNAL finish_bup';
+  }
+  if (`SELECT '$engine'='MEMORY'`)
+  {
+    # Memory tables have not yet been unlocked
+    SET DEBUG_SYNC= 'wait_for_lock SIGNAL finish_bup';
+    send INSERT INTO bup_vp.t1 VALUES ("ntx1: Should NOT be in backup");
+  }
+
 
 --echo # 
 --echo # Connection con_ntx2

=== modified file 'mysql-test/suite/backup/include/bml_test.inc'
--- a/mysql-test/suite/backup/include/bml_test.inc	2009-11-24 16:47:23 +0000
+++ b/mysql-test/suite/backup/include/bml_test.inc	2009-11-26 09:52:48 +0000
@@ -150,7 +150,7 @@ CALL test.check_results();
          # statements. Make it send 'bup_waiting' signal just before it checks
          # for registered statements inside BML. 
          #
-         SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+         SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
          #
          # Whether BACKUP/RESTORE is blocked or not make it stop after it 
          # completes preparations, including activating the BML.
@@ -245,7 +245,7 @@ CALL test.check_results();
      --echo # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
      --echo #       (will not be in backup) make it send signal when
      --echo #       blocked on BML.
-     SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+     SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
      --send
      eval $DDL3;
 
@@ -255,7 +255,7 @@ CALL test.check_results();
        --echo # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
        --echo #       (will not be in backup) make it send signal when
        --echo #       blocked on BML.
-       SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+       SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
        --send
        eval $DDL4;
 

=== modified file 'mysql-test/suite/backup/r/backup_bml_block.result'
--- a/mysql-test/suite/backup/r/backup_bml_block.result	2009-08-29 22:06:21 +0000
+++ b/mysql-test/suite/backup/r/backup_bml_block.result	2009-11-26 09:52:48 +0000
@@ -15,7 +15,7 @@ PURGE BACKUP LOGS;
 CREATE TABLE test.testcombinations(
 test_no int auto_increment primary key,
 command VARCHAR(10), 
-syncpoint VARCHAR (20));
+syncpoint VARCHAR (30));
 #
 # Create connections
 #
@@ -29,11 +29,11 @@ syncpoint VARCHAR (20));
 # Add test combinations
 #
 INSERT INTO test.testcombinations(command, syncpoint) VALUES 
-("BACKUP", "bml_get_check2"),
-("RESTORE", "bml_get_check2");
+("BACKUP", "wait_backup_exclusive_lock"),
+("RESTORE", "wait_backup_exclusive_lock");
 #
 # Test 1, iteration 1:
-#    syncpoint: bml_get_check2
+#    syncpoint: wait_backup_exclusive_lock
 #    command:   BACKUP
 #
 
@@ -46,7 +46,7 @@ CREATE TABLE t2(a CHAR(20));
 
 SET DEBUG_SYNC= 'now WAIT_FOR ddl_started';
 # Starting BACKUP/RESTORE (will be blocked by ongoing DDL)
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 BACKUP DATABASE bml_interrupt TO 'bml_interrupt.bak';
 
 SET DEBUG_SYNC= 'now WAIT_FOR bup_waiting';
@@ -68,7 +68,7 @@ DELETE FROM test.testcombinations WHERE 
 SET DEBUG_SYNC= 'reset';
 #
 # Test 1, iteration 2:
-#    syncpoint: bml_get_check2
+#    syncpoint: wait_backup_exclusive_lock
 #    command:   RESTORE
 #
 
@@ -81,7 +81,7 @@ CREATE TABLE t2(a CHAR(20));
 
 SET DEBUG_SYNC= 'now WAIT_FOR ddl_started';
 # Starting BACKUP/RESTORE (will be blocked by ongoing DDL)
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 RESTORE FROM 'bml_interrupt.bak' OVERWRITE;
 
 SET DEBUG_SYNC= 'now WAIT_FOR bup_waiting';
@@ -128,7 +128,7 @@ SET DEBUG_SYNC= 'before_backup_meta SIGN
 BACKUP DATABASE bml_interrupt TO 'bml_interrupt.bak';
 
 SET DEBUG_SYNC= 'now WAIT_FOR bup_running';
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl_waiting';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl_waiting';
 # Starting DDL statement (will be blocked by BACKUP/RESTORE)
 CREATE TABLE t2(a CHAR(20));
 
@@ -163,7 +163,7 @@ SET DEBUG_SYNC= 'start_do_restore SIGNAL
 RESTORE FROM 'bml_interrupt.bak' OVERWRITE;
 
 SET DEBUG_SYNC= 'now WAIT_FOR bup_running';
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl_waiting';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl_waiting';
 # Starting DDL statement (will be blocked by BACKUP/RESTORE)
 CREATE TABLE t2(a CHAR(20));
 

=== modified file 'mysql-test/suite/backup/r/backup_bml_not_falcon.result'
--- a/mysql-test/suite/backup/r/backup_bml_not_falcon.result	2009-11-24 16:47:23 +0000
+++ b/mysql-test/suite/backup/r/backup_bml_not_falcon.result	2009-11-26 09:52:48 +0000
@@ -153,7 +153,7 @@ DROP FUNCTION f1;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -230,14 +230,14 @@ t2	CREATE TABLE `t2` (
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 DROP DATABASE bml_test_db1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 CREATE TABLE t1(a int);
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -368,7 +368,7 @@ DROP TABLE t1;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -445,14 +445,14 @@ t2	CREATE TABLE `t2` (
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 DROP VIEW v1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 CREATE FUNCTION f1() RETURNS int RETURN 1;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -585,7 +585,7 @@ DROP INDEX i1 ON t2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -660,14 +660,14 @@ t2	CREATE TABLE `t2` (
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 DROP PROCEDURE p1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 CREATE EVENT e1 ON SCHEDULE EVERY 1 YEAR DISABLE DO SET @foo=1;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -795,7 +795,7 @@ DROP EVENT e1;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -870,14 +870,14 @@ t2	CREATE TABLE `t2` (
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 DROP TRIGGER r1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 CREATE INDEX i1 ON t2(b);
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -1048,7 +1048,7 @@ ALTER TABLE t1 ADD INDEX `i` (a);
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -1130,14 +1130,14 @@ e1
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 ALTER VIEW v1 AS SELECT 1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 ALTER FUNCTION f1 COMMENT 'testing alter';
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -1280,7 +1280,7 @@ ALTER FUNCTION f1 COMMENT 'testing alter
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -1362,14 +1362,14 @@ e1
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 ALTER PROCEDURE p1 COMMENT 'testing alter';
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 ALTER EVENT e1 RENAME TO e2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -1512,7 +1512,7 @@ ALTER EVENT e1 RENAME TO e2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -1594,14 +1594,14 @@ e2
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 ALTER DATABASE bml_test_db1 CHARACTER SET = utf8;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 ALTER TABLE t1 ADD INDEX `i` (a);
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -1744,7 +1744,7 @@ ALTER TABLE t1 ADD INDEX `i` (a);
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -1826,14 +1826,14 @@ e1
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 ALTER VIEW v1 AS SELECT 1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 ALTER FUNCTION f1 COMMENT 'testing alter';
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -2004,7 +2004,7 @@ DROP USER bml_u1;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -2074,14 +2074,14 @@ tablespace_name	file_name
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 RENAME USER bml_u2 TO bml_u2_renamed;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 DROP USER bml_u4;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -2198,7 +2198,7 @@ GRANT ALL ON bml_test.* TO bml_u3;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -2266,14 +2266,14 @@ tablespace_name	file_name
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 RENAME TABLE t1_renamed TO t1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 GRANT ALL ON bml_test.* TO bml_u2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -2394,7 +2394,7 @@ REVOKE ALL ON bml_test.* FROM bml_u2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -2463,14 +2463,14 @@ tablespace_name	file_name
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 DROP USER bml_u2;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 REVOKE ALL ON bml_test.* FROM bml_u3;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -2608,7 +2608,7 @@ REPAIR TABLE t2 USE_FRM;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -2682,14 +2682,14 @@ bml_test.t2	1578680517
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 TRUNCATE TABLE t1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 TRUNCATE TABLE t2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -2810,7 +2810,7 @@ TRUNCATE t2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -2879,14 +2879,14 @@ bml_test.t2	0
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 REPAIR TABLE t1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 OPTIMIZE TABLE t2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -3013,7 +3013,7 @@ ANALYZE TABLE t2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -3086,14 +3086,14 @@ bml_test.t2	1578680517
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 TRUNCATE TABLE t1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 TRUNCATE TABLE t2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';
@@ -3214,7 +3214,7 @@ TRUNCATE t2;
 SET DEBUG_SYNC= 'now WAIT_FOR ddl2_started TIMEOUT 15';
 SET DEBUG_SYNC='before_execute_sql_command CLEAR';
 # con5: Activate synchronization points for BACKUP/RESTORE.
-SET DEBUG_SYNC= 'bml_get_check2 SIGNAL bup_waiting';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL bup_waiting';
 SET DEBUG_SYNC= 'after_backup_start_backup  WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'after_backup_start_restore WAIT_FOR continue_bup';
 SET DEBUG_SYNC= 'before_backup_meta SIGNAL bup_running WAIT_FOR finish_bup';
@@ -3283,14 +3283,14 @@ bml_test.t2	0
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl3_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl3_blocked';
 CHECK TABLE t1;
 # Wait for DDL3 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl3_blocked TIMEOUT 15';
 # con3: Send DDL3 but it is blocked by BACKUP/RESTORE 
 #       (will not be in backup) make it send signal when
 #       blocked on BML.
-SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl4_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl4_blocked';
 ANALYZE TABLE t2;
 # Wait for DDL4 to send its signal.
 SET DEBUG_SYNC= 'now WAIT_FOR ddl4_blocked TIMEOUT 15';

=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result	2009-11-17 20:18:50 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result	2009-11-26 09:52:48 +0000
@@ -421,13 +421,13 @@ Inserted before
 #
 # Test error handling by backup code when injecting commit blocker error.
 #
-SET SESSION DEBUG='+d,backup_grl_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 BACKUP DATABASE db1 TO 'overwrite1.bak' ;
 ERROR HY000: Backup failed to synchronize table images.
 SET SESSION DEBUG='-d';
 
 PURGE BACKUP LOGS;
-SET SESSION DEBUG='+d,backup_grl_block_commit_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 BACKUP DATABASE db1 TO 'overwrite1.bak' ;
 ERROR HY000: Backup failed to synchronize table images.
 SET SESSION DEBUG='-d';
@@ -439,6 +439,7 @@ SELECT notes FROM mysql.backup_progress;
 notes
 starting
 running
+validity point
 Backup failed to synchronize table images.
 error
 #

=== modified file 'mysql-test/suite/backup/r/backup_errors_compression.result'
--- a/mysql-test/suite/backup/r/backup_errors_compression.result	2009-11-17 20:18:50 +0000
+++ b/mysql-test/suite/backup/r/backup_errors_compression.result	2009-11-26 09:52:48 +0000
@@ -421,13 +421,13 @@ Inserted before
 #
 # Test error handling by backup code when injecting commit blocker error.
 #
-SET SESSION DEBUG='+d,backup_grl_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 BACKUP DATABASE db1 TO 'overwrite1.bak' WITH COMPRESSION;
 ERROR HY000: Backup failed to synchronize table images.
 SET SESSION DEBUG='-d';
 
 PURGE BACKUP LOGS;
-SET SESSION DEBUG='+d,backup_grl_block_commit_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 BACKUP DATABASE db1 TO 'overwrite1.bak' WITH COMPRESSION;
 ERROR HY000: Backup failed to synchronize table images.
 SET SESSION DEBUG='-d';
@@ -439,6 +439,7 @@ SELECT notes FROM mysql.backup_progress;
 notes
 starting
 running
+validity point
 Backup failed to synchronize table images.
 error
 #

=== modified file 'mysql-test/suite/backup/r/backup_snapshot.result'
--- a/mysql-test/suite/backup/r/backup_snapshot.result	2008-11-17 09:57:51 +0000
+++ b/mysql-test/suite/backup/r/backup_snapshot.result	2009-11-26 09:52:48 +0000
@@ -37,7 +37,7 @@ con2: Wait for backup to have locked the
 SET DEBUG_SYNC= 'now WAIT_FOR locked';
 con2: Start an insert now that CS has a transaction 
 con2: Activate sync points for the insert statement.
-SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL inserting';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL inserting';
 INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
 con2: insert additional rows.
 INSERT INTO bup_snapshot.t1 VALUES("- Yes");

=== modified file 'mysql-test/suite/backup/r/backup_timeout.result'
--- a/mysql-test/suite/backup/r/backup_timeout.result	2009-02-13 13:25:43 +0000
+++ b/mysql-test/suite/backup/r/backup_timeout.result	2009-11-26 09:52:48 +0000
@@ -12,7 +12,7 @@ Variable_name	Value
 backup_wait_timeout	50
 Part A
 con1: Activate synchronization points for backup.
-SET DEBUG_SYNC= 'after_bml_activated SIGNAL bup_blocked WAIT_FOR timeout_done';
+SET DEBUG_SYNC= 'after_backup_exclusivelock_set SIGNAL bup_blocked WAIT_FOR timeout_done';
 con1: Get a backup going and stop after BML is activated.
 BACKUP DATABASE bup_bml TO "bup_bml.bak";
 SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';
@@ -31,7 +31,7 @@ backup_id
 #
 Part B
 con1: Activate synchronization points for backup.
-SET DEBUG_SYNC= 'after_bml_activated SIGNAL bup_blocked WAIT_FOR timeout_done';
+SET DEBUG_SYNC= 'after_backup_exclusivelock_set SIGNAL bup_blocked WAIT_FOR timeout_done';
 con1: Get a backup going and stop after the DDL blocker is fired.
 BACKUP DATABASE bup_bml TO "bup_bml.bak";
 SET DEBUG_SYNC= 'now WAIT_FOR bup_blocked';

=== modified file 'mysql-test/suite/backup/r/backup_triggers_and_events.result'
--- a/mysql-test/suite/backup/r/backup_triggers_and_events.result	2009-11-24 16:47:23 +0000
+++ b/mysql-test/suite/backup/r/backup_triggers_and_events.result	2009-11-26 09:52:48 +0000
@@ -229,23 +229,23 @@ CREATE DATABASE bup_trigevt_indept;
 # Tables with triggers influencing other table in same database.
 #
 CREATE TABLE bup_trigevt_backup.t1_same
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t1_same
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 #
 # Tables with triggers influencing other table in other database.
 #
 CREATE TABLE bup_trigevt_backup.t2_othr
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t2_othr
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 #
 # "Victim" tables to be influenced by other table's triggers.
 #
 CREATE TABLE bup_trigevt_backup.t3_vict
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t3_vict
-(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+(c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 #
 # Changing delimiter to ||.
 #
@@ -436,36 +436,32 @@ SET DEBUG_SYNC='now SIGNAL go WAIT_FOR a
 # all DML blocks at the validity point.
 #
 # connection con2, UPDATE trigger.
-SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con2_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con1';
-SET DEBUG_SYNC='after_update SIGNAL con2';
+SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con2_wait';
+SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con1';
 UPDATE bup_trigevt_backup.t1_same
 SET   c2='UPDATE bup_trigevt_backup.t1_same'
                WHERE c2='INSERT bup_trigevt_backup.t1_same';
 #
 # connection con3, UPDATE trigger.
 SET DEBUG_SYNC='now WAIT_FOR con2_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con3_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con2';
-SET DEBUG_SYNC='after_update SIGNAL con3';
+SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con3_wait';
+SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con2';
 UPDATE bup_trigevt_backup.t2_othr
 SET   c2='UPDATE bup_trigevt_backup.t2_othr'
                    WHERE c2='INSERT bup_trigevt_backup.t2_othr';
 #
 # connection con4, UPDATE trigger.
 SET DEBUG_SYNC='now WAIT_FOR con3_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con4_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con3';
-SET DEBUG_SYNC='after_update SIGNAL con4';
+SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con4_wait';
+SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con3';
 UPDATE bup_trigevt_indept.t1_same
 SET   c2='UPDATE bup_trigevt_indept.t1_same'
                        WHERE c2='INSERT bup_trigevt_indept.t1_same';
 #
 # connection con5, UPDATE trigger.
 SET DEBUG_SYNC='now WAIT_FOR con4_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con5_wait';
-SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con4';
-SET DEBUG_SYNC='after_update SIGNAL con5';
+SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con5_wait';
+SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con4';
 UPDATE bup_trigevt_indept.t2_othr
 SET   c2='UPDATE bup_trigevt_indept.t2_othr'
                            WHERE c2='INSERT bup_trigevt_indept.t2_othr';
@@ -476,12 +472,16 @@ SET DEBUG_SYNC='now SIGNAL go WAIT_FOR a
 SET DEBUG_SYNC='now SIGNAL con1';
 #
 # connection con2, receive UPDATE result.
+SET DEBUG_SYNC='now SIGNAL con2';
 #
 # connection con3, receive UPDATE result.
+SET DEBUG_SYNC='now SIGNAL con3';
 #
 # connection con4, receive UPDATE result.
+SET DEBUG_SYNC='now SIGNAL con4';
 #
 # connection con5, receive UPDATE result.
+SET DEBUG_SYNC='now SIGNAL con5';
 #
 # connection con1, examine results.
 SELECT * FROM bup_trigevt_backup.t1_same ORDER BY c1;
@@ -638,10 +638,10 @@ c1	c2
 2	bup_trigevt_backup_t1_same_ai
 3	bup_trigevt_indept_t2_othr_bi
 4	bup_trigevt_indept_t2_othr_ai
-5	bup_trigevt_backup_t1_same_bi
-6	bup_trigevt_backup_t1_same_ai
-7	bup_trigevt_indept_t2_othr_bi
-8	bup_trigevt_indept_t2_othr_ai
+13	bup_trigevt_backup_t1_same_bi
+14	bup_trigevt_backup_t1_same_ai
+15	bup_trigevt_indept_t2_othr_bi
+16	bup_trigevt_indept_t2_othr_ai
 SELECT * FROM bup_trigevt_indept.t1_same ORDER BY c1;
 c1	c2
 2	INSERT bup_trigevt_indept.t1_same RESTORE
@@ -697,14 +697,14 @@ c1	c2
 2	bup_trigevt_backup_t1_same_ai
 3	bup_trigevt_indept_t2_othr_bi
 4	bup_trigevt_indept_t2_othr_ai
-5	bup_trigevt_backup_t1_same_bi
-6	bup_trigevt_backup_t1_same_ai
-7	bup_trigevt_indept_t2_othr_bi
-8	bup_trigevt_indept_t2_othr_ai
-9	bup_trigevt_backup_t1_same_bu
-10	bup_trigevt_backup_t1_same_au
-11	bup_trigevt_indept_t2_othr_bu
-12	bup_trigevt_indept_t2_othr_au
+13	bup_trigevt_backup_t1_same_bi
+14	bup_trigevt_backup_t1_same_ai
+15	bup_trigevt_indept_t2_othr_bi
+16	bup_trigevt_indept_t2_othr_ai
+17	bup_trigevt_backup_t1_same_bu
+18	bup_trigevt_backup_t1_same_au
+19	bup_trigevt_indept_t2_othr_bu
+20	bup_trigevt_indept_t2_othr_au
 SELECT * FROM bup_trigevt_indept.t1_same ORDER BY c1;
 c1	c2
 2	UPDATE bup_trigevt_indept.t1_same RESTORE
@@ -758,18 +758,18 @@ c1	c2
 2	bup_trigevt_backup_t1_same_ai
 3	bup_trigevt_indept_t2_othr_bi
 4	bup_trigevt_indept_t2_othr_ai
-5	bup_trigevt_backup_t1_same_bi
-6	bup_trigevt_backup_t1_same_ai
-7	bup_trigevt_indept_t2_othr_bi
-8	bup_trigevt_indept_t2_othr_ai
-9	bup_trigevt_backup_t1_same_bu
-10	bup_trigevt_backup_t1_same_au
-11	bup_trigevt_indept_t2_othr_bu
-12	bup_trigevt_indept_t2_othr_au
-13	bup_trigevt_backup_t1_same_bd
-14	bup_trigevt_backup_t1_same_ad
-15	bup_trigevt_indept_t2_othr_bd
-16	bup_trigevt_indept_t2_othr_ad
+13	bup_trigevt_backup_t1_same_bi
+14	bup_trigevt_backup_t1_same_ai
+15	bup_trigevt_indept_t2_othr_bi
+16	bup_trigevt_indept_t2_othr_ai
+17	bup_trigevt_backup_t1_same_bu
+18	bup_trigevt_backup_t1_same_au
+19	bup_trigevt_indept_t2_othr_bu
+20	bup_trigevt_indept_t2_othr_au
+21	bup_trigevt_backup_t1_same_bd
+22	bup_trigevt_backup_t1_same_ad
+23	bup_trigevt_indept_t2_othr_bd
+24	bup_trigevt_indept_t2_othr_ad
 SELECT * FROM bup_trigevt_indept.t1_same ORDER BY c1;
 c1	c2
 SELECT * FROM bup_trigevt_indept.t2_othr ORDER BY c1;

=== modified file 'mysql-test/suite/backup/r/backup_vp_nontx_memory.result'
--- a/mysql-test/suite/backup/r/backup_vp_nontx_memory.result	2009-05-26 23:26:33 +0000
+++ b/mysql-test/suite/backup/r/backup_vp_nontx_memory.result	2009-11-26 09:52:48 +0000
@@ -34,9 +34,16 @@ INSERT INTO bup_vp.t1 VALUES ("ntx1: 06 
 #
 # Connection con_bup
 #
+SET DEBUG_SYNC= 'now WAIT_FOR insert_started';
 # con_bup: Activate synchronization points for BACKUP.
-# Signal when backup is blocked by ongoing insert in con_ntx1
-SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL sync_complete_insert';
+# Backup should not reach after_backup_validated because
+# this happens after getting the table lock (blocked by the insert)
+# There's no way to use DEBUG_SYNC to check if BACKUP is waiting for 
+# the table lock since BACKUP tries to get this lock in a separate
+# thread. Here, we signal from a sync point BACKUP should not be able
+# to reach due to the lock set by the insert above. Further down, 
+# we listen for this signal and expect to timeout.
+SET DEBUG_SYNC= 'after_backup_validated SIGNAL backup_got_too_far';
 # ntx1 insert is completed, so backup can set CB. Just before reaching
 # VP, signal ntx2 should try to insert. Wait until ntx2 signals it has
 # been blocked
@@ -51,8 +58,12 @@ BACKUP DATABASE bup_vp TO "bup_vp.bak";
 #
 # Connection sync
 #
-SET DEBUG_SYNC= 'now WAIT_FOR sync_complete_insert';
-# Backup has been blocked by ongoing insert
+# Here we listen for the signal that BACKUP *should not send*! 
+# If this does not timeout and produce a warning, BACKUP got the 
+# table lock it shouldn't have gotten!
+SET DEBUG_SYNC= 'now WAIT_FOR backup_got_too_far TIMEOUT 4';
+Warnings:
+Warning	#	debug sync point wait timed out
 # cannot test with select that insert has not completed ntx1 has X-lock
 SET DEBUG_SYNC= 'now SIGNAL complete_insert';
 #
@@ -69,24 +80,20 @@ ntx1: 06 Some data to test
 #
 # Scenario(c): Wait until backup has set CB, then try to insert
 SET DEBUG_SYNC= 'now WAIT_FOR try_insert';
-SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL sync_insert_blocked';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL sync_insert_blocked';
 INSERT INTO bup_vp.t1 VALUES ("ntx2: Should NOT be in backup");
 #
 # Connection con_sync
 #
 SET DEBUG_SYNC= 'now WAIT_FOR sync_insert_blocked';
-# Insert in ntx2 is blocked and should not be in t1; Should be 0 records
-SELECT * FROM bup_vp.t1 WHERE col_a like 'ntx2%';
-col_a
-
 SET DEBUG_SYNC= 'now SIGNAL insert_blocked';
 #
 # Connection con_ntx1
 #
 # Scenario(d): Backup has now released CB. Perform insert
 SET DEBUG_SYNC= 'now WAIT_FOR commit_unblocked';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL finish_bup';
 INSERT INTO bup_vp.t1 VALUES ("ntx1: Should NOT be in backup");
-SET DEBUG_SYNC= 'now SIGNAL finish_bup';
 # 
 # Connection con_ntx2
 #

=== modified file 'mysql-test/suite/backup/r/backup_vp_nontx_myisam.result'
--- a/mysql-test/suite/backup/r/backup_vp_nontx_myisam.result	2009-05-26 23:26:33 +0000
+++ b/mysql-test/suite/backup/r/backup_vp_nontx_myisam.result	2009-11-26 09:52:48 +0000
@@ -34,9 +34,16 @@ INSERT INTO bup_vp.t1 VALUES ("ntx1: 06 
 #
 # Connection con_bup
 #
+SET DEBUG_SYNC= 'now WAIT_FOR insert_started';
 # con_bup: Activate synchronization points for BACKUP.
-# Signal when backup is blocked by ongoing insert in con_ntx1
-SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL sync_complete_insert';
+# Backup should not reach after_backup_validated because
+# this happens after getting the table lock (blocked by the insert)
+# There's no way to use DEBUG_SYNC to check if BACKUP is waiting for 
+# the table lock since BACKUP tries to get this lock in a separate
+# thread. Here, we signal from a sync point BACKUP should not be able
+# to reach due to the lock set by the insert above. Further down, 
+# we listen for this signal and expect to timeout.
+SET DEBUG_SYNC= 'after_backup_validated SIGNAL backup_got_too_far';
 # ntx1 insert is completed, so backup can set CB. Just before reaching
 # VP, signal ntx2 should try to insert. Wait until ntx2 signals it has
 # been blocked
@@ -51,8 +58,12 @@ BACKUP DATABASE bup_vp TO "bup_vp.bak";
 #
 # Connection sync
 #
-SET DEBUG_SYNC= 'now WAIT_FOR sync_complete_insert';
-# Backup has been blocked by ongoing insert
+# Here we listen for the signal that BACKUP *should not send*! 
+# If this does not timeout and produce a warning, BACKUP got the 
+# table lock it shouldn't have gotten!
+SET DEBUG_SYNC= 'now WAIT_FOR backup_got_too_far TIMEOUT 4';
+Warnings:
+Warning	#	debug sync point wait timed out
 # cannot test with select that insert has not completed ntx1 has X-lock
 SET DEBUG_SYNC= 'now SIGNAL complete_insert';
 #
@@ -69,7 +80,7 @@ ntx1: 06 Some data to test
 #
 # Scenario(c): Wait until backup has set CB, then try to insert
 SET DEBUG_SYNC= 'now WAIT_FOR try_insert';
-SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL sync_insert_blocked';
+SET DEBUG_SYNC= 'wait_for_lock SIGNAL sync_insert_blocked';
 INSERT INTO bup_vp.t1 VALUES ("ntx2: Should NOT be in backup");
 #
 # Connection con_sync

=== modified file 'mysql-test/suite/backup/r/backup_vp_tx.result'
--- a/mysql-test/suite/backup/r/backup_vp_tx.result	2009-01-29 10:19:15 +0000
+++ b/mysql-test/suite/backup/r/backup_vp_tx.result	2009-11-26 09:52:48 +0000
@@ -72,7 +72,7 @@ BEGIN;
 INSERT INTO bup_vp.t2 VALUES ("tx2: 06 Should NOT be in backup");
 
 con_bup: Activate synchronization points for BACKUP.
-SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL sync_complete_commit';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL sync_complete_commit';
 SET DEBUG_SYNC= 'before_backup_data_lock SIGNAL try_commit 
                  WAIT_FOR commit_blocked';
 SET DEBUG_SYNC= 'after_backup_binlog SIGNAL commit_unblocked
@@ -97,7 +97,7 @@ tx1: 06 Some data to test
 
 con_tx2: Commit request will be blocked by CB
 SET DEBUG_SYNC= 'now WAIT_FOR try_commit';
-SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL sync_commit_blocked';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL sync_commit_blocked';
 COMMIT;
 
 SET DEBUG_SYNC= 'now WAIT_FOR sync_commit_blocked';

=== modified file 'mysql-test/suite/backup/t/backup_bml.test'
--- a/mysql-test/suite/backup/t/backup_bml.test	2009-06-30 07:51:04 +0000
+++ b/mysql-test/suite/backup/t/backup_bml.test	2009-11-26 09:52:48 +0000
@@ -36,6 +36,11 @@
 ##       main, a copy of this test with a modified part 3 has been
 ##       created as backup_bml_not_falcon.test. Once Falcon is back in
 ##       main, that test file should be removed.
+## NOTE: The result file of backup_bml_not_falcon has since changed.
+##       Without Falcon, the result file for this test can't be
+##       recorded. When reenabling this test, please check the diff
+##       between the result file of this test and
+##       backup_bml_not_falcon.result
 
 --source include/not_embedded.inc
 --source include/have_innodb.inc

=== modified file 'mysql-test/suite/backup/t/backup_bml_block.test'
--- a/mysql-test/suite/backup/t/backup_bml_block.test	2009-08-29 22:06:21 +0000
+++ b/mysql-test/suite/backup/t/backup_bml_block.test	2009-11-26 09:52:48 +0000
@@ -31,7 +31,7 @@ PURGE BACKUP LOGS;
 CREATE TABLE test.testcombinations(
        test_no int auto_increment primary key,
        command VARCHAR(10), 
-       syncpoint VARCHAR (20));
+       syncpoint VARCHAR (30));
 
 --echo #
 --echo # Create connections
@@ -54,8 +54,8 @@ connect (backup,localhost,root,,);
 --echo #
 
 INSERT INTO test.testcombinations(command, syncpoint) VALUES 
-       ("BACKUP", "bml_get_check2"),
-       ("RESTORE", "bml_get_check2");
+       ("BACKUP", "wait_backup_exclusive_lock"),
+       ("RESTORE", "wait_backup_exclusive_lock");
 
 let $it=1;
 while (`SELECT count(*) > 0 FROM test.testcombinations`) {
@@ -192,7 +192,7 @@ while (`SELECT count(*) > 0 FROM test.te
   --connection ddl
   let $id=`select connection_id()`;
   SET DEBUG_SYNC= 'now WAIT_FOR bup_running';
-  SET DEBUG_SYNC= 'bml_enter_check SIGNAL ddl_waiting';
+  SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL ddl_waiting';
   --echo # Starting DDL statement (will be blocked by BACKUP/RESTORE)
   send CREATE TABLE t2(a CHAR(20));
 

=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test	2009-11-17 20:18:50 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test	2009-11-26 09:52:48 +0000
@@ -485,18 +485,19 @@ RESTORE FROM 'overwrite.bak';
 SELECT * FROM table1;
 --remove_file $MYSQLD_DATADIR/overwrite.bak
 
+## New CB can't fail
 --echo #
 --echo # Test error handling by backup code when injecting commit blocker error.
 --echo #
 
-SET SESSION DEBUG='+d,backup_grl_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 --error ER_BACKUP_SYNCHRONIZE
 eval BACKUP DATABASE db1 TO 'overwrite1.bak' $compression;
 SET SESSION DEBUG='-d';
 
 --echo
 PURGE BACKUP LOGS;
-SET SESSION DEBUG='+d,backup_grl_block_commit_fail';
+SET SESSION DEBUG='+d,backup_block_commits_fail';
 --error ER_BACKUP_SYNCHRONIZE
 eval BACKUP DATABASE db1 TO 'overwrite1.bak' $compression;
 SET SESSION DEBUG='-d';

=== modified file 'mysql-test/suite/backup/t/backup_snapshot.test'
--- a/mysql-test/suite/backup/t/backup_snapshot.test	2009-02-24 20:57:21 +0000
+++ b/mysql-test/suite/backup/t/backup_snapshot.test	2009-11-26 09:52:48 +0000
@@ -90,9 +90,10 @@ SET DEBUG_SYNC= 'now WAIT_FOR locked';
 # the backup is released.
 
 --echo con2: Activate sync points for the insert statement.
-SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL inserting';
+SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL inserting';
 
-# Insert will wait in wait_if_global_read_lock() until backup is done.
+# Autocommit of this insert will wait in wait_if_backup_exclusive_locked() 
+# until backup is done.
 INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
 
 --echo con2: insert additional rows.
@@ -151,7 +152,8 @@ SET DEBUG_SYNC= 'now WAIT_FOR reading';
 --echo con2: Activate sync points for the insert statement.
 SET DEBUG_SYNC= 'after_insert_locked_tables SIGNAL inserting';
 
-# Insert will wait in wait_if_global_read_lock() until backup is done.
+# Commit of this insert will wait in wait_if_backup_exclusive_locked() 
+# until backup is done.
 INSERT INTO bup_snapshot.t1 VALUES("- Dave Mathews");
 
 --echo con2: insert additional rows.

=== modified file 'mysql-test/suite/backup/t/backup_timeout.test'
--- a/mysql-test/suite/backup/t/backup_timeout.test	2009-02-24 20:57:21 +0000
+++ b/mysql-test/suite/backup/t/backup_timeout.test	2009-11-26 09:52:48 +0000
@@ -63,7 +63,7 @@ SHOW VARIABLES LIKE 'backup_wait%';
 connection con1;
 
 --echo con1: Activate synchronization points for backup.
-SET DEBUG_SYNC= 'after_bml_activated SIGNAL bup_blocked WAIT_FOR timeout_done';
+SET DEBUG_SYNC= 'after_backup_exclusivelock_set SIGNAL bup_blocked WAIT_FOR timeout_done';
 
 --echo con1: Get a backup going and stop after BML is activated.
 send BACKUP DATABASE bup_bml TO "bup_bml.bak";
@@ -103,7 +103,7 @@ reap;
 connection con1;
 
 --echo con1: Activate synchronization points for backup.
-SET DEBUG_SYNC= 'after_bml_activated SIGNAL bup_blocked WAIT_FOR timeout_done';
+SET DEBUG_SYNC= 'after_backup_exclusivelock_set SIGNAL bup_blocked WAIT_FOR timeout_done';
 
 --echo con1: Get a backup going and stop after the DDL blocker is fired.
 send BACKUP DATABASE bup_bml TO "bup_bml.bak";

=== modified file 'mysql-test/suite/backup/t/backup_triggers_and_events.test'
--- a/mysql-test/suite/backup/t/backup_triggers_and_events.test	2009-11-24 16:47:23 +0000
+++ b/mysql-test/suite/backup/t/backup_triggers_and_events.test	2009-11-26 09:52:48 +0000
@@ -10,6 +10,7 @@
 #                                      and events during backup/restore)
 #
 
+--source include/have_innodb.inc
 --source include/have_debug_sync.inc
 --source include/not_embedded.inc
 
@@ -266,23 +267,23 @@ CREATE DATABASE bup_trigevt_indept;
 --echo # Tables with triggers influencing other table in same database.
 --echo #
 CREATE TABLE bup_trigevt_backup.t1_same
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t1_same
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 --echo #
 --echo # Tables with triggers influencing other table in other database.
 --echo #
 CREATE TABLE bup_trigevt_backup.t2_othr
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t2_othr
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+   (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 --echo #
 --echo # "Victim" tables to be influenced by other table's triggers.
 --echo #
 CREATE TABLE bup_trigevt_backup.t3_vict
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+   (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 CREATE TABLE bup_trigevt_indept.t3_vict
-  (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64));
+        (c1 INT AUTO_INCREMENT PRIMARY KEY, c2 CHAR(64)) engine=innodb;
 --echo #
 --echo # Changing delimiter to ||.
 --echo #
@@ -419,6 +420,7 @@ CREATE TRIGGER bup_trigevt_indept.bup_tr
     INSERT INTO bup_trigevt_backup.t3_vict
       VALUES(NULL, 'bup_trigevt_indept_t2_othr_ad');
 ||
+
 --echo #
 --echo # Changing delimiter to ;.
 --echo #
@@ -462,23 +464,22 @@ send BACKUP DATABASE bup_trigevt_backup 
     --echo #
 #
 # The cascade of synchronization signals is required to:
-# 1. Prove that all UPDATEs run into wait_if_global_read_lock(),
-#    which is done with the con*_wait signals.
-#    This cascade ends in con1 at WAIT_FOR con5_wait.
-#    At this point all UPDATES are in wait_if_global_read_lock().
+# 1. Prove that all UPDATEs auto-commits run into Commit Blocker 
+#    (Backup_sx_lock->get_shared_lock()), which is done with the con*_wait 
+#    signals. This cascade ends in con1 at WAIT_FOR con5_wait.
+#    At this point all UPDATES are in get_shared_lock().
 # 2. Force an order of execution for the UPDATEs so that the triggers
 #    insert into the "victim" tables in a fixed order,
 #    which is done with the con* signals.
 #    This cascade starts when BACKUP leaves the validation point
-#    and releases the global read lock.
+#    and releases the commit blocker (Backup_sx_lock->release_exclusive_lock())
 #
         --echo # connection con2, UPDATE trigger.
         --connect (con2,localhost,root,,)
-        # Cascade #1: Synchronize before global read lock
-        SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con2_wait';
-        # Cascade #2: Synchronize after global read lock
-        SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con1';
-        SET DEBUG_SYNC='after_update SIGNAL con2';
+        # Cascade #1: Synchronize before setting commit blocker
+        SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con2_wait';
+        # Cascade #2: Synchronize after blocking commits
+        SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con1';
         send UPDATE bup_trigevt_backup.t1_same
                SET   c2='UPDATE bup_trigevt_backup.t1_same'
                WHERE c2='INSERT bup_trigevt_backup.t1_same';
@@ -486,12 +487,11 @@ send BACKUP DATABASE bup_trigevt_backup 
             --echo #
             --echo # connection con3, UPDATE trigger.
             --connect (con3,localhost,root,,)
-            # Cascade #1: Synchronize before global read lock
+            # Cascade #1: Synchronize before commit blocker
             SET DEBUG_SYNC='now WAIT_FOR con2_wait';
-            SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con3_wait';
-            # Cascade #2: Synchronize after global read lock
-            SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con2';
-            SET DEBUG_SYNC='after_update SIGNAL con3';
+            SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con3_wait';
+            # Cascade #2: Synchronize after commits have been blocked
+            SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con2';
             send UPDATE bup_trigevt_backup.t2_othr
                    SET   c2='UPDATE bup_trigevt_backup.t2_othr'
                    WHERE c2='INSERT bup_trigevt_backup.t2_othr';
@@ -499,12 +499,11 @@ send BACKUP DATABASE bup_trigevt_backup 
                 --echo #
                 --echo # connection con4, UPDATE trigger.
                 --connect (con4,localhost,root,,)
-                # Cascade #1: Synchronize before global read lock
+                # Cascade #1: Synchronize before commit blocker
                 SET DEBUG_SYNC='now WAIT_FOR con3_wait';
-                SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con4_wait';
-                # Cascade #2: Synchronize after global read lock
-                SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con3';
-                SET DEBUG_SYNC='after_update SIGNAL con4';
+                SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con4_wait';
+                # Cascade #2: Synchronize after commits have been blocked
+                SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con3';
                 send UPDATE bup_trigevt_indept.t1_same
                        SET   c2='UPDATE bup_trigevt_indept.t1_same'
                        WHERE c2='INSERT bup_trigevt_indept.t1_same';
@@ -512,15 +511,15 @@ send BACKUP DATABASE bup_trigevt_backup 
                     --echo #
                     --echo # connection con5, UPDATE trigger.
                     --connect (con5,localhost,root,,)
-                    # Cascade #1: Synchronize before global read lock
+                    # Cascade #1: Synchronize before commit blocker
                     SET DEBUG_SYNC='now WAIT_FOR con4_wait';
-                    SET DEBUG_SYNC='wait_if_global_read_lock SIGNAL con5_wait';
-                    # Cascade #2: Synchronize after global read lock
-                    SET DEBUG_SYNC='wait_if_global_read_lock_end WAIT_FOR con4';
-                    SET DEBUG_SYNC='after_update SIGNAL con5';
+                    SET DEBUG_SYNC='wait_if_backup_exclusive_locked SIGNAL con5_wait';
+                    # Cascade #2: Synchronize after commits have been blocked
+                    SET DEBUG_SYNC='backup_got_shared_lock WAIT_FOR con4';
                     send UPDATE bup_trigevt_indept.t2_othr
                            SET   c2='UPDATE bup_trigevt_indept.t2_othr'
                            WHERE c2='INSERT bup_trigevt_indept.t2_othr';
+
 #
     --echo #
     --echo # connection con1, complete validity point.
@@ -536,21 +535,25 @@ send BACKUP DATABASE bup_trigevt_backup 
         --echo # connection con2, receive UPDATE result.
         --connection con2
         reap;
+        SET DEBUG_SYNC='now SIGNAL con2';
 #
             --echo #
             --echo # connection con3, receive UPDATE result.
             --connection con3
             reap;
+            SET DEBUG_SYNC='now SIGNAL con3';
 #
                 --echo #
                 --echo # connection con4, receive UPDATE result.
                 --connection con4
                 reap;
+                SET DEBUG_SYNC='now SIGNAL con4';
 #
                     --echo #
                     --echo # connection con5, receive UPDATE result.
                     --connection con5
                     reap;
+                    SET DEBUG_SYNC='now SIGNAL con5';
 #
     --echo #
     --echo # connection con1, examine results.
@@ -601,6 +604,7 @@ SELECT * FROM bup_trigevt_indept.t3_vict
 --echo #
 --echo # Start another RESTORE to see if triggers work.
 --echo #
+
 SET DEBUG_SYNC='before_restore_completed SIGNAL completed WAIT_FOR go';
 send RESTORE FROM 'bup_trigevt_backup.bak' OVERWRITE;
 #
@@ -609,6 +613,7 @@ send RESTORE FROM 'bup_trigevt_backup.ba
     --echo #
     --connection con1
     SET DEBUG_SYNC='now WAIT_FOR completed';
+
     INSERT INTO bup_trigevt_backup.t1_same
       VALUES(NULL, 'INSERT bup_trigevt_backup.t1_same RESTORE');
     INSERT INTO bup_trigevt_backup.t2_othr

=== modified file 'mysql-test/suite/backup/t/backup_vp_tx.test'
--- a/mysql-test/suite/backup/t/backup_vp_tx.test	2009-01-29 10:19:15 +0000
+++ b/mysql-test/suite/backup/t/backup_vp_tx.test	2009-11-26 09:52:48 +0000
@@ -181,7 +181,7 @@ connection con_bup;
 
 --echo con_bup: Activate synchronization points for BACKUP.
 # Signal when backup is blocked by ongoing commit in con_tx1
-SET DEBUG_SYNC= 'wait_lock_global_read_lock SIGNAL sync_complete_commit';
+SET DEBUG_SYNC= 'wait_backup_exclusive_lock SIGNAL sync_complete_commit';
 
 # tx1 commit is completed, so backup can set CB. Just before reaching
 # VP, signal tx2 should try to commit. Wait until tx2 signals it has
@@ -232,7 +232,7 @@ SET DEBUG_SYNC= 'now SIGNAL complete_com
     SET DEBUG_SYNC= 'now WAIT_FOR try_commit';
 
     # Signal to backup that the commit is blocked
-    SET DEBUG_SYNC= 'wait_if_global_read_lock SIGNAL sync_commit_blocked';
+    SET DEBUG_SYNC= 'wait_if_backup_exclusive_locked SIGNAL sync_commit_blocked';
 
     send COMMIT;
 

=== modified file 'sql/backup/be_default.cc'
--- a/sql/backup/be_default.cc	2009-11-26 09:02:58 +0000
+++ b/sql/backup/be_default.cc	2009-11-26 09:52:48 +0000
@@ -469,12 +469,6 @@ result_t Backup::get_data(Buffer &buf)
       buf.last= TRUE;
       mode= GET_NEXT_TABLE;
 
-      /*
-        Optimization: If this is the last table to read, close the tables and
-        kill the lock thread. This only applies iff we are using the thread.
-      */
-      if (locking_thd->tables_in_backup->next_global == NULL)
-        locking_thd->kill_locking_thread();
     }
     else if (last_read_res != 0)
     {

=== modified file 'sql/backup/data_backup.cc'
--- a/sql/backup/data_backup.cc	2009-10-21 13:32:24 +0000
+++ b/sql/backup/data_backup.cc	2009-11-26 09:52:48 +0000
@@ -395,43 +395,15 @@ int block_commits(THD *thd, TABLE_LIST *
 {
   DBUG_ENTER("block_commits()");
 
-  DBUG_EXECUTE_IF("backup_grl_fail",
-    /* Mimic behavior of a failing lock_global_read_lock. */
-    DBUG_RETURN(1););
-
-  // Step 1 - global read lock.
-  DEBUG_SYNC(thd, "before_commit_block");
-  if (lock_global_read_lock(thd))
-    DBUG_RETURN(1);
-
-  /*
-    Step 2 - close cached tables.
-
-    Notice to Online Backup developers.
+  DEBUG_SYNC(thd, "before_get_cb");
 
-    The method "close_cached_tables" as originally included in the commit
-    blocker algorithm (see above) was omitted because there are no non-
-    transactional tables that are not included in the existing default,
-    consistent snapshot, and myisam drivers. This is only needed for engines
-    that do not take lock tables. Thus, it should apply to write locked
-    tables only and only to non-transactional engines.
+  if (obs::bcb_get(thd) || thd->killed)
+    DBUG_RETURN(1);
 
-    result= close_cached_tables(thd, 0, tables);
-  */
+  DBUG_EXECUTE_IF("backup_block_commits_fail", DBUG_RETURN(1););
 
-  DBUG_EXECUTE_IF("backup_grl_block_commit_fail",
-    /* Mimic behavior of a failing make_global_read_lock_block_commit. */
-    unlock_global_read_lock(thd);
-    DBUG_RETURN(1);
-  );
+  DEBUG_SYNC(thd, "after_get_cb");
 
-  // Step 3 - make the global read lock to block commits.
-  if (make_global_read_lock_block_commit(thd))
-  {
-    /* Don't leave things in a half-locked state. */
-    unlock_global_read_lock(thd);
-    DBUG_RETURN(1);
-  }
   DBUG_RETURN(0);
 }
 
@@ -450,7 +422,7 @@ int block_commits(THD *thd, TABLE_LIST *
 void unblock_commits(THD *thd)
 {
   DBUG_ENTER("unblock_commits()");
-  unlock_global_read_lock(thd);
+  obs::bcb_release();                           // Never errors
   DBUG_VOID_RETURN;
 }
 
@@ -687,33 +659,6 @@ int write_table_data(THD* thd, Backup_in
     DBUG_PRINT("backup_data",("-- PREPARE PHASE --"));
     DEBUG_SYNC(thd, "before_backup_data_prepare");
 
-    /*
-      Note: block_commits is performed here because of the global read
-      lock/table lock deadlock reported in bug#39602. It should be
-      moved back to right before sch.lock() once a refined commit
-      blocker has been implemented. WL#4610 tracks the work on a
-      refined commit blocker
-    */
-
-    /*
-      Block commits.
-
-      TODO: Step 2 of the commit blocker has been skipped for this release.
-      When it is included, developer needs to build a list of all of the
-      non-transactional tables and pass that to block_commits().
-    */
-    int error= 0;
-
-    if (!(error= block_commits(thd, NULL)))
-      commits_blocked= TRUE;
-    if (log.report_killed())
-      goto error;
-    if (error)
-    {
-      log.report_error(ER_BACKUP_SYNCHRONIZE);
-      goto error;
-    }
-
     if (sch.prepare())    // Logs errors.
       goto error;
 
@@ -737,7 +682,15 @@ int write_table_data(THD* thd, Backup_in
     */
     DEBUG_SYNC(thd, "after_backup_validated");
 
-    // Refined commit blocker should be set here; see WL#4610.
+    int error= block_commits(thd, NULL);
+    commits_blocked= TRUE;
+    if (log.report_killed())
+      goto error;
+    if (error)
+    {
+      log.report_error(ER_BACKUP_SYNCHRONIZE);
+      goto error;
+    }
 
     DEBUG_SYNC(thd, "before_backup_data_lock");
     /*

=== modified file 'sql/bml.cc'
--- a/sql/bml.cc	2009-10-16 13:12:38 +0000
+++ b/sql/bml.cc	2009-11-26 09:52:48 +0000
@@ -17,13 +17,55 @@
 /**
    @file
 
-   @brief Contains methods to implement the Backup Metadata Lock (BML) service.
+   @brief Contains methods to implement the Backup Shared/Exclusive
+   Locks service.
 
-   This file contains methods that allow SQL statements to register with the
-   BML service. In case the lock is taken, these statements will be blocked.
-   It also contains methods for taking and releasing the lock.
-
-   The list of statements which should obey BML is as follows:
+   This file contains methods that allow getting and releasing Shared
+   and Exclusive locks. The service follows the standard lock
+   compatibility matrix for Shared/Exclusive locking:
+
+     | S  X
+   --+-----
+   S | Y  N
+   X | N  N
+
+   Where S=Shared lock and X=Exclusive lock
+
+   The following properties are enforced:
+
+   * A thread requesting an S lock gets the lock immediately unless 
+     - another thread already got the X lock, or 
+     - another thread has requested the X lock and is waiting for the release
+       of S locks to get it
+
+     In both these, the request is blocked until the X lock has been
+     released or a timeout occurs
+
+   * A thread requesting an X lock gets the lock immediately unless 
+     - one or more threads has S locks, in which case the request is
+       blocked until all existing S locks have been released, or
+     - another thread has (requested) the X lock. Since only one
+       BACKUP/RESTORE process can exist at any time, X lock requests
+       return with an error if the X lock has already been set.
+
+
+   The Backup Shared/Exclusive Lock service is used by BACKUP for two things:
+    - Backup Metadata Locking
+    - Backup Commit Blocker
+
+   Hence, two Backup_sx_lock objects are defined at MySQL server startup:
+
+   Backup_sx_lock *BML_instance
+   Backup_sx_lock *BCB_instance
+
+   BACKUP METADATA LOCKING
+   -----------------------
+   For the duration of BACKUP/RESTORE, most DDL statements are
+   disallowed. This is implemented by making BACKUP acquire an exclusive
+   lock for the duration that must be protected, and making DDL
+   statements aquire Shared locks.
+   
+   The list of statements that should obey BML is as follows:
 
     DROP   DATABASE/TABLE/VIEW/FUNCTION/PROCEDURE/EVENT/TRIGGER/INDEX
     DROP   USER/TABLESPACE
@@ -34,219 +76,246 @@
     TRUNCATE/OPTIMIZE/REPAIR TABLE
 
    The parser (mysql_execute_command() in sql_parse.cc) arranges for calls to
-   bml_enter() and bml_leave() for these statements.
-*/
+   get_shared_lock() and release_shared_lock() for these statements.
 
-#include "bml.h"
-#include "debug_sync.h"
+   BACKUP COMMIT BLOCKER
+   ---------------------
 
-BML_class *BML_class::m_instance= NULL;
+   To get a transaction consistent image of all tables in all
+   databases being backed up, BACKUP needs to disallow commits for a
+   short period of time to synchronize data from all storage
+   engines. This is implemented by making BACKUP acquire an exclusive lock
+   for the duration of the synchronization phase, and by making all
+   commits of transactions that have modified data acquire Shared locks.
 
-BML_class *BML_class::get_BML_class_instance()
-{
-  if (m_instance == NULL)
-    m_instance = new BML_class();
-  return m_instance;
-}
+   ha_commit_trans in handler.cc arranges for calls to get_shared_lock()
+   and release_shared_lock().
 
-void BML_class::destroy_BML_class_instance()
-{
-  delete m_instance;
-  m_instance= NULL;
-}
+*/
 
-BML_class::BML_class()
-{
-  pthread_mutex_init(&THR_LOCK_BML, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&THR_LOCK_BML_active, MY_MUTEX_INIT_FAST);
-  pthread_mutex_init(&THR_LOCK_BML_get, MY_MUTEX_INIT_FAST);
-  pthread_cond_init(&COND_BML, NULL);
-  pthread_cond_init(&COND_BML_registered, NULL);
-  pthread_cond_init(&COND_BML_release, NULL);
-  BML_active= FALSE;
-  BML_registered= 0;
-}
+#include "bml.h"
+#include "debug_sync.h"
 
-BML_class::~BML_class()
+Backup_sx_lock::Backup_sx_lock()
 {
-  pthread_mutex_destroy(&THR_LOCK_BML);
-  pthread_mutex_destroy(&THR_LOCK_BML_active);
-  pthread_mutex_destroy(&THR_LOCK_BML_get);
-  pthread_cond_destroy(&COND_BML);
-  pthread_cond_destroy(&COND_BML_registered);
-  pthread_cond_destroy(&COND_BML_release);
+  pthread_mutex_init(&LOCK_mutex, MY_MUTEX_INIT_FAST);
+  pthread_cond_init(&COND_no_slock, NULL);
+  pthread_cond_init(&COND_no_xlock, NULL);
+  xlock_set= NULL;
+  slock_count= 0;
 }
 
-/**
-   do_enter()
-
-   Registers operation which obeys BML by increasing BML_registered counter.
-*/
-void BML_class::do_enter()
+Backup_sx_lock::~Backup_sx_lock()
 {
-  DBUG_ENTER("BML_class::do_enter()");
-  pthread_mutex_lock(&THR_LOCK_BML);
-  BML_registered++;
-  pthread_mutex_unlock(&THR_LOCK_BML);
-  DBUG_VOID_RETURN;
+  pthread_mutex_destroy(&LOCK_mutex);
+  pthread_cond_destroy(&COND_no_slock);
+  pthread_cond_destroy(&COND_no_xlock);
 }
 
 /**
-   bml_leave()
+   Check if the exclusive lock has been set. If so, wait until it has
+   been released. When the exclusive lock has been released, acquire
+   a Shared lock by increasing the Shared Lock Counter (slock_count).
 
-   Unregister operation which checked for BML with bml_enter(). 
-   Decrements the BML_registered counter to indicate the operation 
-   is done. Signals COND_BML_registered if counter == 0.
-*/
-void BML_class::bml_leave()
-{
-  DBUG_ENTER("BML_class::bml_leave()");
-  pthread_mutex_lock(&THR_LOCK_BML);
-  if (BML_registered > 0)
-    BML_registered--;
-  if (BML_registered == 0)
-    pthread_cond_broadcast(&COND_BML_registered);
-  pthread_mutex_unlock(&THR_LOCK_BML);
-  DBUG_VOID_RETURN;
-}
-
-/**
-   bml_enter
-
-   Check to see if BML is active. If so, wait until it is deactivated.
-   When BML is not active, register the operation with BML.
-
-   If a timeout specified by backup_wait_timeout variable occurs, this
-   method returns FALSE. The operation is not registered in that case.
-    
    @param[in] thd        The THD object from the caller.
 
-   @note: A successful call to bml_enter() must be matched by bml_leave().
+   @note: A successful call to get_shared_lock() must be matched by
+   release_shared_lock().
 
    @return Operation status
-     @retval TRUE if the BML was not set
-     @retval FALSE if timeout occurred while waiting for BML to be released
+     @retval TRUE if a Shared Lock was successfully acquired
+     @retval FALSE if timeout occurred while waiting for the exclusive
+             lock to be released
 */
-my_bool BML_class::bml_enter(THD *thd)
+my_bool Backup_sx_lock::get_shared_lock(THD *thd)
 {
   int ret = 0;
   struct timespec ddl_timeout;
-  DBUG_ENTER("BML_class::bml_enter()");
+  DBUG_ENTER("Backup_sx_lock::get_shared_lock()");
 
   set_timespec(ddl_timeout, thd->backup_wait_timeout);
 
   /*
-    Check whether BML is active. If yes, wait for deactivation which is 
-    signalled with COND_BML.
+    Check whether an exclusive lock is set. If yes, wait for release
+    which is signalled with COND_no_xlock.
   */
-  pthread_mutex_lock(&THR_LOCK_BML_active);
-  thd->enter_cond(&COND_BML, &THR_LOCK_BML_active,
-                  "BML: waiting until released");
-  DEBUG_SYNC(thd, "bml_enter_check");
-  while (BML_active && !thd->killed && !thd->BML_exception && (ret == 0))
+  pthread_mutex_lock(&LOCK_mutex);
+  thd->enter_cond(&COND_no_xlock, &LOCK_mutex,
+                  "Backup_sx_lock: waiting until exclusive lock is released");
+  while (xlock_set && xlock_set!=thd && !thd->killed && (ret == 0))
   {
     if (thd->backup_wait_timeout == 0)
+    {
       ret = -1;
+    }
     else
-      ret= pthread_cond_timedwait(&COND_BML, &THR_LOCK_BML_active,
+    {
+      /*
+        The below sync point fires if the exclusive lock is set.
+        
+        WARNING: Be careful when using WAIT_FOR with this sync point.
+        We hold LOCK_mutex here.
+      */
+      DEBUG_SYNC(thd, "wait_if_backup_exclusive_locked");
+      ret= pthread_cond_timedwait(&COND_no_xlock, &LOCK_mutex,
                                   &ddl_timeout);
+    }
   }
+
   if (thd->killed)
   {
-    /* Releases THR_LOCK_BML_active */
-    thd->exit_cond("BML: Thread was killed");
+    /* Releases LOCK_mutex */
+    thd->exit_cond("Backup_sx_lock: Thread was killed");
     DBUG_RETURN(FALSE);
   }
 
-  thd->exit_cond("BML: entered");
   if (ret == 0)
-    do_enter();
+    slock_count++;
   else
     my_error(ER_DDL_TIMEOUT, MYF(0), thd->query());
 
+  thd->exit_cond("Backup_sx_lock: entered");
+
+  DEBUG_SYNC(thd, "backup_got_shared_lock");
   DBUG_RETURN(ret == 0);
 }
 
 /**
-   bml_get
+   Release the Shared lock by decreasing slock_count
+*/
+void Backup_sx_lock::release_shared_lock()
+{
+  DBUG_ENTER("Backup_sx_lock::release_shared_lock()");
+  pthread_mutex_lock(&LOCK_mutex);
+  
+  DBUG_ASSERT(slock_count > 0);
+  slock_count--;
 
-  This method is used to activate BML. It waits for any operations which
-  registered with bml_enter() to unregister using bml_leave().
-  The method also prevents any other thread from activating the lock until
-  bml_release() is called.
-
-  It checks the counter BML_registered and if > 0 it blocks the process until 
-  all registerd operations are complete and the condition variable has been 
-  signaled. The fact that BML is in force is indicated by setting the boolean 
-  BML_active to TRUE.
+  if (slock_count == 0 && xlock_set) 
+    pthread_cond_signal(&COND_no_slock);
 
-   @params thd THD object.
-   @return TRUE if the lock was set successfully, FALSE otherwise
-  */
-my_bool BML_class::bml_get(THD *thd)
-{
-  DBUG_ENTER("BML_class::bml_get()");
+  pthread_mutex_unlock(&LOCK_mutex);
+  DBUG_VOID_RETURN;
+}
 
-  /*
-    Only 1 thread can hold the BML. If BML_active is TRUE, wait for
-    bml_release() which signals COND_BML_release condition.
-  */
-  pthread_mutex_lock(&THR_LOCK_BML_get);
-  thd->enter_cond(&COND_BML_release, &THR_LOCK_BML_get,
-                  "BML: waiting for release before activating");
-  DEBUG_SYNC(thd, "bml_get_check1");
-  while (BML_active && !thd->killed)
-    pthread_cond_wait(&COND_BML_release, &THR_LOCK_BML_get);
+/**
+   Block new shared lock requests by setting the exclusive lock. Wait
+   until all currently active shared locks have been released and then
+   return.
 
-  if (thd->killed)
+   @param[in] thd        The THD object from the caller.
+
+   @note: A successful call to get_exclusive_lock() must be matched by
+   release_exclusive_lock().
+
+   @return Operation status
+     @retval TRUE if an exclusive lock was successfully acquired
+     @retval FALSE otherwise
+*/
+my_bool Backup_sx_lock::get_exclusive_lock(THD *thd)
+{
+  DBUG_ENTER("Backup_sx_lock::get_exclusive_lock()");
+
+  //part 1 - get the exclusive lock
+  pthread_mutex_lock(&LOCK_mutex);
+  if (unlikely(xlock_set)) 
   {
-    thd->exit_cond("BML: Thread was killed");
+    /* 
+       Should never happen since only one backup/restore operation is
+       allowed at any time 
+    */
+    thd->exit_cond("Backup_sx_lock: An exclusive lock has already been set");
     DBUG_RETURN(FALSE);
   }
 
-  BML_active= TRUE;
-  thd->exit_cond("BML: activating");
+  xlock_set= thd; // Blocks new attempts at getting a shared lock
 
-  /*
-    Wait for all registered statements to complete, i.e., until BML_registered
-    is zero in which case COND_BML_registered is signalled.
-  */
-  pthread_mutex_lock(&THR_LOCK_BML);
-  thd->enter_cond(&COND_BML_registered, &THR_LOCK_BML,
-                  "BML: waiting for all statements to leave");
-  DEBUG_SYNC(thd, "bml_get_check2");
-  while (BML_registered != 0 && !thd->killed)
-    pthread_cond_wait(&COND_BML_registered, &THR_LOCK_BML);
+  //part 2 - wait for all shared locks to be released
+  thd->enter_cond(&COND_no_slock, &LOCK_mutex,
+                  "Backup_sx_lock: waiting for release of all Shared locks");
+  while (slock_count != 0 && !thd->killed) 
+  {
+    /*
+      The below sync point fires if a shared lock is set.
+      
+      WARNING: Be careful when using WAIT_FOR with this sync point.
+      We hold LOCK_mutex here.
+    */
+    DEBUG_SYNC(thd, "wait_backup_exclusive_lock");
+    /* wait in queue that is activated when slock_count drops to 0 */
+    pthread_cond_wait(&COND_no_slock, &LOCK_mutex); 
+  }
+  thd->exit_cond("Backup_sx_lock: Exclusive lock set (or thread killed)");
 
   if (thd->killed)
   {
-    /* Releases THR_LOCK_BML */
-    thd->exit_cond("BML: Thread was killed");
-    /* This thread still has BML_active set - release it */
-    bml_release();
+    /* This thread alread got X lock; release it */
+    release_exclusive_lock();
     DBUG_RETURN(FALSE);
   }
 
-  thd->exit_cond("BML: activated");
-
-  DEBUG_SYNC(thd, "after_bml_activated");
+  DEBUG_SYNC(thd, "after_backup_exclusivelock_set");
   DBUG_RETURN(TRUE);
 }
 
 /**
-   bml_release
+   Release the Exclusive lock by setting xlock_set= NULL. Since there
+   cannot be more than one BACKUP/RESTORE thread at any time, it is
+   safe for BACKUP/RESTORE to call this even if get_exclusive_lock()
+   failed.
 
-   This method is used to deactivate BML. All operations which are waiting
-   in bml_enter() call (if any) will be allowed to continue.
+   @todo Take THD *thd as argument and verify that xlock_set==thd
+         before doing xlock_set= NULL
+*/
+void Backup_sx_lock::release_exclusive_lock()
+{
+  DBUG_ENTER("Backup_sx_lock::release_exclusive_lock()");
+  pthread_mutex_lock(&LOCK_mutex);
+  xlock_set= NULL;
+  pthread_cond_broadcast(&COND_no_xlock);
+  pthread_mutex_unlock(&LOCK_mutex);
+  DBUG_VOID_RETURN;
+}
 
-   The BML_active flag is set to FALSE to indicate that BML is not active and
-   conditions COND_BML and COND_BML_release are signalled.
+Backup_sx_lock *Backup_sx_lock::bml_instance= NULL;
+Backup_sx_lock *Backup_sx_lock::bcb_instance= NULL;
+
+/**
+  Singleton method to get the Backup Metadata Lock instance
 */
-void BML_class::bml_release()
+Backup_sx_lock *Backup_sx_lock::get_BML_instance()
 {
-  pthread_mutex_lock(&THR_LOCK_BML);
-  BML_active= FALSE;
-  pthread_cond_broadcast(&COND_BML);
-  pthread_cond_signal(&COND_BML_release);
-  pthread_mutex_unlock(&THR_LOCK_BML);
+  if (bml_instance == NULL)
+    bml_instance = new Backup_sx_lock();
+  return bml_instance;
 }
+
+/**
+  Singleton method to destroy the Backup Metadata Lock instance
+*/
+void Backup_sx_lock::destroy_BML_instance()
+{
+  delete bml_instance;
+  bml_instance= NULL;
+}
+
+
+/**
+  Singleton method to get the Backup Commit Blocker instance
+*/
+Backup_sx_lock *Backup_sx_lock::get_BCB_instance()
+{
+  if (bcb_instance == NULL)
+    bcb_instance = new Backup_sx_lock();
+  return bcb_instance;
+}
+
+/**
+  Singleton method to destroy the Backup Commit Blocker instance
+*/
+void Backup_sx_lock::destroy_BCB_instance()
+{
+  delete bcb_instance;
+  bcb_instance= NULL;
+}
+

=== modified file 'sql/bml.h'
--- a/sql/bml.h	2009-10-12 09:08:34 +0000
+++ b/sql/bml.h	2009-11-26 09:52:48 +0000
@@ -10,118 +10,102 @@
 #include "mysql_priv.h"
 
 /**
-   @class BML_class
+   @class Backup_sx_lock
  
-   @brief Implements a simple Backup Metadata Lock (BML) mechanism.
- 
-   The BML_class is a singleton class designed to allow blocking statements 
-   changing metadata which should be constant during backup/restore operation.
-   Only one thread can hold the lock but there is no restriction on number
-   of blocked statements which can run in parallel. 
+   @brief Implements a simple Backup Shared/Exclusive Lock service
+   used by BML (backup metadata locking) and Backup Commit Blocker.
+
+   Two singleton instances are created of this class:
+     * BML_instance, which is used by Backup to block concurrent 
+       DDL statements
+     * bcb_instance, which is used by Backup to block concurrent
+       transactions from committing while backup performs the
+       synchronization stage.
+
+   Backup Metadata Locking works as follows:
+     * A transaction that wants to modify the database metada by
+       performing a DDL operation first needs to acquire a shared lock
+       in the BML_instance. It does so by calling get_shared_lock(). A
+       transaction that has taken a shared lock has to release it
+       by calling release_shared_lock() before committing.
+     * When backup want's to block DDL statements so that the database
+       metadata remains unchanged for the duration of backup, it has
+       to acquire the exclusive lock in the BML_instance. It does so
+       by calling get_exclusive_lock(). Once metadata changes no
+       longer need to be blocked, backup will release the exlusive
+       lock by calling release_exclusive_lock().
+
+   Backup Commit Blocking works as follows:
+     * A transaction that wants to commit has to acquire the shared
+       lock in the bcb_instance first. Once it has committed, the
+       shared lock must be released.
+     * When backup reaches the synchronization phase and needs to
+       block commits, it acquires the exclusive lock. Once
+       synchronization is completed, it releases the lock.
 
-   If a thread has acquired BML and another thread attempts to activate it,
-   the second thread will wait until the first one is complete.
- 
-   Checking for Block
-   Any statement that needs to be blocked by BML should call @c bml_enter() at
-   the beginning of its execution. This method will return when BML is not active
-   or wait until it becomes inactive. Once the method returns, the statement
-   which called the method is registered and while it is running, it will be not
-   possible to activate BML. When the statement is complete, you must unregister
-   it by calling bml_leave(). All this is done inside the parser
-   (@c mysql_execute_command()).
-
-   Blocking Statements
-   To prevent metadata changes, call bml_get(). This activates the lock and
-   prevents any statements which use bml_enter() from executing. To remove the
-   lock bml_release().
 
    Singleton Methods
-   The creation of the singleton is accomplished using 
-   get_BML_class_instance(). This method is called from mysqld.cc
-   and creates and initializes all of the private mutex, condition, and
-   controlling variables. The method destroy_BML_class_instance()
-   destroys the mutex and condition variables. 
-
-   Calling the Singleton
-   To call the singleton class, you must declare an external variable
-   to the global variable BML_instance as shown below.
+   The creation of the locking instances is accomplished using the
+   get_BML_instance() and get_BCB_instance() methods. These methods
+   are called from mysqld.cc and creates and initializes all of the
+   private mutex, condition, and controlling variables. The methods
+   destroy_BML_instance() and destroy_BCB_instance() destroys the
+   mutex and condition variables.
+
+   Calling the Singletons
+
+   To call the BML or BCB singletons, you must declare external
+   variables to the global variables BML_instance and BCB_instance as
+   shown below.
 
-   @c extern BML_class *BML_instance;
+   @c extern Backup_sx_lock *BML_instance;
+   @c extern Backup_sx_lock *BCB_instance;
 
-   Calling methods on the singleton is accomplished using the BML_instance
-   variable such as: @c BML_instance->bml_get().
+
+   Calling methods on the singleton is accomplished using the
+   BML_instance or BCB_instance variable such as: 
+
+   @c BML_instance->get_shared_lock().
 
    @note: This class is currently only used in MySQL backup. If you would
-          like to use it elsewhere and have questions, please contact
-          Chuck Bell (cbell@stripped) for more details and how to setup
-          a test case to test the BML mechanism for your use.
-  */
-class BML_class
+   like to use it elsewhere and have questions, please contact
+   Chuck Bell (cbell@stripped) for more details and how to setup
+   a test case to test the Backup_sx_lock mechanism for your use.
+*/
+class Backup_sx_lock
 {
-  public:
-
-    /*
-      Singleton class
-    */
-    static BML_class *get_BML_class_instance();
-    static void destroy_BML_class_instance();
-
-    /*
-      Check to see if BML is active. If so, wait until it is deactivated.
-      When BML is not active, register the operation with BML.
-    */
-    my_bool bml_enter(THD *thd);
-
-    /*
-      Unregister operation which checked for BML with bml_enter(). 
-    */
-    void bml_leave();
-
-    /*
-      This method is used to activate BML. It waits for any operations which
-      registered with bml_enter() to unregister using bml_leave().
-      The method also prevents any other thread from activating the lock until
-      bml_release() is called.
-    */
-    my_bool bml_get(THD *thd);
-
-    /*
-      This method is used to deactivate BML. All operations which are waiting
-      in bml_enter() call (if any) will be allowed to continue.
-    */
-    void bml_release();
-
-  private:
-
-    BML_class();
-    ~BML_class();
-
-    /*
-      Registers operation which obeys BML.
-    */
-    void do_enter();
-
-    /*
-      These variables are used to implement the Backup Metadata Lock.
-    */
-
-    /// Mutex for protecting BML_registered counter.
-    pthread_mutex_t THR_LOCK_BML;
-    /// Mutex for proteting BML_active falg.
-    pthread_mutex_t THR_LOCK_BML_active;
-    /// Mutex for serializing BML usage. 
-    pthread_mutex_t THR_LOCK_BML_get;
-    /// Signals deactivation of BML for statements waiting in bml_enter(). 
-    pthread_cond_t COND_BML;
-    /// Signals deactivation of BML for threads waiting in bml_get().
-    pthread_cond_t COND_BML_release;
-    /// Signals that BML_reagistered count dropped to 0.
-    pthread_cond_t COND_BML_registered;
-
-    my_bool BML_active;           ///< Is BML activated.
-    int BML_registered;           ///< Number of statements registered with BML.
-    static BML_class *m_instance; ///< instance var for singleton 
+ public:
+  
+  static Backup_sx_lock *get_BML_instance();
+  static void destroy_BML_instance();
+  static Backup_sx_lock *get_BCB_instance();
+  static void destroy_BCB_instance();
+  
+  my_bool get_shared_lock(THD *thd);
+  my_bool get_exclusive_lock(THD *thd);
+  
+  void release_shared_lock();
+  void release_exclusive_lock();
+  
+ private:
+  Backup_sx_lock();
+  ~Backup_sx_lock();
+  
+  /// Mutex for protecting xlock_set and slock_count
+  pthread_mutex_t LOCK_mutex;
+  /// Signals THR_LOCK_lock mutex was released and slock_count dropped to zero
+  pthread_cond_t COND_no_slock;
+  /// Signals wlock was released
+  pthread_cond_t COND_no_xlock;
+  
+  /// THD that has the X lock, or NULL if X lock is not set
+  THD *xlock_set;
+  /// Number of shared locks currently set
+  int slock_count; 
+
+  
+  static Backup_sx_lock *bml_instance; ///< instance var for singleton 
+  static Backup_sx_lock *bcb_instance; ///< instance var for singleton 
+  
 };
-
 #endif /* BML_INCLUDED */

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2009-10-26 14:02:26 +0000
+++ b/sql/handler.cc	2009-11-26 09:52:48 +0000
@@ -33,6 +33,7 @@
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
+#include "bml.h"
 #endif
 
 #include "rpl_handler.h"
@@ -110,6 +111,8 @@ handlerton *ha_default_handlerton(THD *t
 }
 
 
+extern Backup_sx_lock *BCB_instance;
+
 /**
   Return the storage engine handlerton for the supplied name
   
@@ -1145,6 +1148,8 @@ int ha_commit_trans(THD *thd, bool all)
     DBUG_RETURN(2);
   }
 
+  bool bcb_registered= FALSE;
+
   if (ha_info)
   {
     uint rw_ha_count;
@@ -1162,7 +1167,8 @@ int ha_commit_trans(THD *thd, bool all)
     rw_trans= is_real_trans && (rw_ha_count > 0);
 
     if (rw_trans &&
-        wait_if_global_read_lock(thd, 0, 0))
+        (wait_if_global_read_lock(thd, 0, 0) ||
+         !(bcb_registered= BCB_instance->get_shared_lock(thd))))
     {
       ha_rollback_trans(thd, all);
       DBUG_RETURN(1);
@@ -1174,6 +1180,11 @@ int ha_commit_trans(THD *thd, bool all)
         !thd->slave_thread)
     {
       my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
+      if (bcb_registered) 
+      {
+        BCB_instance->release_shared_lock();
+        bcb_registered=FALSE;
+      }
       ha_rollback_trans(thd, all);
       error= 1;
       goto end;
@@ -1229,6 +1240,7 @@ end:
   /* Free resources and perform other cleanup even for 'empty' transactions. */
   else if (is_real_trans)
     thd->transaction.cleanup();
+  if (bcb_registered) BCB_instance->release_shared_lock();
   DBUG_RETURN(error);
 }
 

=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc	2009-11-24 16:47:23 +0000
+++ b/sql/mysqld.cc	2009-11-26 09:52:48 +0000
@@ -458,7 +458,8 @@ static pthread_cond_t COND_thread_cache,
 
 /* Global variables */
 
-extern BML_class *BML_instance;
+extern Backup_sx_lock *BML_instance;
+extern Backup_sx_lock *BCB_instance;
 bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0;
 my_bool opt_log, opt_slow_log;
 my_bool opt_backup_history_log;
@@ -1591,7 +1592,8 @@ static void clean_up_mutexes()
   (void) pthread_cond_destroy(&COND_thread_cache);
   (void) pthread_cond_destroy(&COND_flush_thread_cache);
   (void) pthread_cond_destroy(&COND_manager);
-  BML_class::destroy_BML_class_instance();
+  Backup_sx_lock::destroy_BML_instance();
+  Backup_sx_lock::destroy_BCB_instance();
   DBUG_VOID_RETURN;
 }
 
@@ -3878,9 +3880,10 @@ static int init_thread_environment()
   (void) pthread_cond_init(&COND_server_started,NULL);
 
   /*
-    Initialize the DDL blocker
+    Initialize the backup DDL and commit blockers
   */
-  BML_instance= BML_class::get_BML_class_instance();
+  BML_instance= Backup_sx_lock::get_BML_instance();
+  BCB_instance= Backup_sx_lock::get_BCB_instance();
 
   sp_cache_init();
 #ifdef HAVE_EVENT_SCHEDULER

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2009-11-24 16:47:23 +0000
+++ b/sql/si_objects.cc	2009-11-26 09:52:48 +0000
@@ -32,7 +32,8 @@
 #include "event_db_repository.h"
 #endif
 
-BML_class *BML_instance= NULL;
+Backup_sx_lock *BML_instance= NULL;
+Backup_sx_lock *BCB_instance= NULL;
 
 extern my_bool disable_slaves;
 
@@ -776,9 +777,6 @@ bool Abstract_obj::create(THD *thd)
   session_context.save_si_ctx(thd);
   session_context.reset_si_ctx(thd);
 
-  /* Allow to execute DDL operations. */
-  ::obs::bml_exception_on(thd);
-
   /* Run queries from the serialization image. */
   while ((sql_text= it++))
   {
@@ -793,9 +791,6 @@ bool Abstract_obj::create(THD *thd)
       break;
   }
 
-  /* Disable further DDL execution. */
-  ::obs::bml_exception_off(thd);
-
   session_context.restore_si_ctx(thd);
 
   DBUG_RETURN(rc);
@@ -833,9 +828,6 @@ bool Abstract_obj::drop(THD *thd)
   session_context.save_si_ctx(thd);
   session_context.reset_si_ctx(thd);
 
-  /* Allow to execute DDL operations. */
-  ::obs::bml_exception_on(thd);
-
   /* Execute DDL operation. */
   rc= ed_connection.execute_direct(*sql_text);
 
@@ -843,9 +835,6 @@ bool Abstract_obj::drop(THD *thd)
   if (rc)
     m_errno= ed_connection.get_last_errno();
 
-  /* Disable further DDL execution. */
-  ::obs::bml_exception_off(thd);
-
   session_context.restore_si_ctx(thd);
 
   DBUG_RETURN(rc);
@@ -3249,6 +3238,37 @@ bool compare_tablespace_attributes(Obj *
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Implementation: Backup Commit Blocker
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+/*
+  BCB methods
+*/
+
+bool bcb_get(THD *thd)
+{
+  DBUG_ASSERT(BCB_instance);
+  DBUG_ENTER("obs::bcb_get");
+  if (!BCB_instance->get_exclusive_lock(thd))
+    DBUG_RETURN(TRUE);
+  DBUG_RETURN(FALSE);
+}
+
+
+void bcb_release()
+{
+  DBUG_ASSERT(BCB_instance);
+  DBUG_ENTER("obs::bcb_release");
+  BCB_instance->release_exclusive_lock();
+  DBUG_VOID_RETURN;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Implementation: Backup Metadata Lock.
 //
 
@@ -3274,7 +3294,7 @@ bool compare_tablespace_attributes(Obj *
 bool bml_get(THD *thd)
 {
   DBUG_ENTER("obs::bml_get");
-  if (!BML_instance->bml_get(thd))
+  if (!BML_instance->get_exclusive_lock(thd))
     DBUG_RETURN(TRUE);
   DBUG_RETURN(FALSE);
 }
@@ -3286,42 +3306,10 @@ bool bml_get(THD *thd)
 void bml_release()
 {
   DBUG_ENTER("obs::bml_release");
-  BML_instance->bml_release();
-  DBUG_VOID_RETURN;
-}
-
-
-/**
-   Turn on the backup metadata lock exception
-
-   The thread for which this method is called is allowed to execute statements 
-   which normally are blocked by BML.
-
-   @param[in] thd  current thread
-*/
-void bml_exception_on(THD *thd)
-{
-  DBUG_ENTER("obs::bml_exception_on");
-  thd->BML_exception= TRUE;
-  DBUG_VOID_RETURN;
-}
-
-
-/**
-   Turn off the backup metadata lock exception
-
-   This method cancels the exception activated with @c bml_exception_on().
-
-   @param[in] thd  current thread
-  */
-void bml_exception_off(THD *thd)
-{
-  DBUG_ENTER("obs::bml_exception_off");
-  thd->BML_exception= FALSE;
+  BML_instance->release_exclusive_lock();
   DBUG_VOID_RETURN;
 }
 
-
 /**
   Build a table list from a list of tables as class Obj.
 
@@ -3551,9 +3539,6 @@ bool truncate_tables(THD *thd, TABLE_LIS
   TABLE_LIST *tlist;
   DBUG_ENTER("obs:truncate_tables");
 
-  /* Allow to execute DDL operations. */
-  ::obs::bml_exception_on(thd);
-
   for (tlist= table_list; tlist; tlist= tlist->next_global)
   {
     s_stream.reset();
@@ -3564,9 +3549,6 @@ bool truncate_tables(THD *thd, TABLE_LIS
       DBUG_RETURN(TRUE);
   }
 
-  /* Disable further DDL execution. */
-  ::obs::bml_exception_off(thd);
-
   DBUG_RETURN(FALSE);
 }
 

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2009-11-24 16:47:23 +0000
+++ b/sql/si_objects.h	2009-11-26 09:52:48 +0000
@@ -428,6 +428,30 @@ bool compare_tablespace_attributes(Obj *
 ///////////////////////////////////////////////////////////////////////////
 
 //
+// Backup Commit Blocker (BCB) methods.
+//
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+   Get the backup commit blocker.
+
+   @param[in] thd  current thread
+
+  @return Error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+*/
+bool bcb_get(THD *thd);
+
+/**
+  Release the backup commit blocker if acquired earlier.
+*/
+void bcb_release();
+
+///////////////////////////////////////////////////////////////////////////
+
+//
 // Backup Metadata Lock (BML) methods.
 //
 
@@ -453,25 +477,6 @@ bool bml_get(THD *thd);
 */
 void bml_release();
 
-/**
-   Turn on the backup metadata lock exception
-
-   The thread for which this method is called is allowed to execute statements 
-   which normally are blocked by BML.
-
-   @param[in] thd  current thread
-*/
-void bml_exception_on(THD *thd);
-
-/**
-   Turn off the backup metadata lock exception
-
-   This method cancels the exception activated with @c bml_exception_on().
-
-   @param[in] thd  current thread
-  */
-void bml_exception_off(THD *thd);
-
 /*
   The following class is used to manage name locks on a list of tables.
 

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2009-10-26 14:02:26 +0000
+++ b/sql/sql_class.cc	2009-11-26 09:52:48 +0000
@@ -465,13 +465,6 @@ THD::THD()
    derived_tables_processing(FALSE),
    spcont(NULL),
    m_parser_state(NULL),
-  /*
-    @todo The following is a work around for MySQL backup and the Backup 
-    Metadata Lock (BML). It should be removed when the generalized solution 
-    is in place. This is needed to ensure the restore thread (which uses BML) 
-    is not blocked by the lock.
-  */
-   BML_exception(FALSE),
    backup_wait_timeout(BACKUP_WAIT_TIMEOUT_DEFAULT),
    backup_in_progress(0),
 #if defined(ENABLED_DEBUG_SYNC)

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2009-11-24 16:47:23 +0000
+++ b/sql/sql_class.h	2009-11-26 09:52:48 +0000
@@ -2054,13 +2054,6 @@ public:
   */
   Parser_state *m_parser_state;
 
-  /*
-    @todo The following is a work around for MySQL backup and the Backup 
-    Metadata Lock (BML). It should be removed when the generalized solution 
-    is in place. This is needed to ensure the restore thread (which uses BML) 
-    is not blocked by the lock.
-  */
-  my_bool BML_exception; // Allow some DDL if there is an exception
   ulong backup_wait_timeout;
   /*
     If online backup/restore in progress, set to SQLCOM_BACKUP or

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2009-11-02 14:05:19 +0000
+++ b/sql/sql_parse.cc	2009-11-26 09:52:48 +0000
@@ -97,7 +97,7 @@ const char *xa_state_names[]={
   "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY"
 };
 
-extern BML_class *BML_instance;
+extern Backup_sx_lock *BML_instance;
 
 #ifdef HAVE_REPLICATION
 /**
@@ -1859,7 +1859,7 @@ mysql_execute_command(THD *thd)
    with bml_enter() in which case a matching call to bml_leave() must be made
    after it has been executed.
   */ 
-  bool bml_registered= FALSE;
+  bool has_bml_shared_lock= FALSE;
 
   /*
     In many cases first table of main SELECT_LEX have special meaning =>
@@ -2049,21 +2049,23 @@ mysql_execute_command(THD *thd)
   }
 
   /*
-    If the SQL command to be executed should be blocked by BML, call 
-    bml_enter() to regiser it. The call will block if the lock is taken 
-    currently and will wait for its release (possibly timing-out).
+    If the SQL command to be executed should be blocked by BML, call
+    get_shred_lock() to regiser it. The call will block if the lock is
+    taken currently and will wait for its release (possibly
+    timing-out).
     
-    If registering is successful, either because the lock was not taken, or it
-    was removed before the timeout, then bml_enter() returns TRUE and 
-    bml_registered flag becomes TRUE. This flag is later used to de-register
-    the command using bml_leave().
+    If the lock was successfully taken, either because the lock was
+    not taken, or it was removed before the timeout, then
+    get_shared_lock() returns TRUE and has_bml_shared_lock flag
+    becomes TRUE. This flag is later used to unlock using
+    release_shared_lock().
     
-    In case of timeout, when the registration has failed, bml_enter() will
-    return false, bml_registered will be FALSE and bml_leave() will not be 
-    called. 
+    In case of timeout, when the registration has failed,
+    get_shared_lock() will return false, has_bml_shared_lock will be
+    FALSE and release_shared_lock() will not be called.
   */ 
   if (is_bml_blocked(lex->sql_command) && 
-      !(bml_registered= BML_instance->bml_enter(thd)))
+      !(has_bml_shared_lock= BML_instance->get_shared_lock(thd)))
     goto error;
   
   /*
@@ -4878,8 +4880,8 @@ finish:
   /*
     De-register command from the BML system, if it was registered.
   */
-  if (bml_registered)
-    BML_instance->bml_leave();
+  if (has_bml_shared_lock)
+    BML_instance->release_shared_lock();
 
   if (thd->global_read_lock_protection > 0)
   {


Attachment: [text/bzr-bundle] bzr/jorgen.loland@sun.com-20091126095248-w457r9y0pygpj6eh.bundle
Thread
bzr commit into mysql-6.0-backup branch (jorgen.loland:2896) Bug#44568Jorgen Loland26 Nov