List:Commits« Previous MessageNext Message »
From:cbell Date:May 1 2008 5:28pm
Subject:bk commit into 6.0 tree (cbell:1.2614) BUG#33414
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of cbell.  When cbell does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-05-01 13:27:39-04:00, cbell@mysql_cab_desk. +11 -0
  BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
  
  Added ability to set a timeout for blocked DDL operations. The
  timeout is the number of seconds a blocked DDL operation will 
  wait before aborting with an error message. The variable can be
  set only as a session variable.
  
  Note: timeout must be set before DDL is executed.

  include/mysql_com.h@stripped, 2008-05-01 13:27:25-04:00, cbell@mysql_cab_desk. +2 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added maximum ddl timeout value.

  mysql-test/r/backup_ddl_blocker_timeout.result@stripped, 2008-05-01 13:27:33-04:00, cbell@mysql_cab_desk. +139 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    New result file. 

  mysql-test/r/backup_ddl_blocker_timeout.result@stripped, 2008-05-01 13:27:33-04:00, cbell@mysql_cab_desk. +0 -0

  mysql-test/t/backup_ddl_blocker_timeout.test@stripped, 2008-05-01 13:27:33-04:00, cbell@mysql_cab_desk. +259 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added new test for DDL timeout. 

  mysql-test/t/backup_ddl_blocker_timeout.test@stripped, 2008-05-01 13:27:33-04:00, cbell@mysql_cab_desk. +0 -0

  mysql-test/t/disabled.def@stripped, 2008-05-01 13:27:26-04:00, cbell@mysql_cab_desk. +1 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Disabled new test for same reason as others: Waiting for BUG#34235.

  sql/ddl_blocker.cc@stripped, 2008-05-01 13:27:27-04:00, cbell@mysql_cab_desk. +28 -10
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added ability to timeout based on the variable ddl_wait_timeout.

  sql/set_var.cc@stripped, 2008-05-01 13:27:27-04:00, cbell@mysql_cab_desk. +19 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added session variable ddl_wait_timeout.

  sql/set_var.h@stripped, 2008-05-01 13:27:28-04:00, cbell@mysql_cab_desk. +13 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added session variable ddl_wait_timeout class.

  sql/share/errmsg.txt@stripped, 2008-05-01 13:27:32-04:00, cbell@mysql_cab_desk. +3 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added new error message for DDL timeout. 

  sql/sql_class.cc@stripped, 2008-05-01 13:27:29-04:00, cbell@mysql_cab_desk. +2 -1
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added default value setting for ddl_wait_timeout.

  sql/sql_class.h@stripped, 2008-05-01 13:27:30-04:00, cbell@mysql_cab_desk. +1 -0
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Added thread variable ddl_wait_timeout.

  sql/sql_parse.cc@stripped, 2008-05-01 13:27:31-04:00, cbell@mysql_cab_desk. +27 -12
    BUG#33414 : Backup: DDL hangs indefinitely if ongoing backup
    
    Modified code to check for a failed return which indicates the
    ddl blocker has timed out.

diff -Nrup a/include/mysql_com.h b/include/mysql_com.h
--- a/include/mysql_com.h	2008-04-01 09:44:50 -04:00
+++ b/include/mysql_com.h	2008-05-01 13:27:25 -04:00
@@ -219,6 +219,8 @@ enum enum_server_command
 #define NET_WRITE_TIMEOUT	60		/* Timeout on write */
 #define NET_WAIT_TIMEOUT	8*60*60		/* Wait for new query */
 
+#define DDL_WAIT_TIMEOUT	LONG_MAX/1000  /* Wait for ddl blocker */
+
 #define ONLY_KILL_QUERY         1
 
 struct st_vio;					/* Only C */
diff -Nrup a/mysql-test/r/backup_ddl_blocker_timeout.result b/mysql-test/r/backup_ddl_blocker_timeout.result
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/r/backup_ddl_blocker_timeout.result	2008-05-01 13:27:33 -04:00
@@ -0,0 +1,139 @@
+SET GLOBAL debug="d,backup_debug:d,backup";
+DROP DATABASE IF EXISTS bup_ddl_blocker;
+CREATE DATABASE bup_ddl_blocker;
+con1: Creating tables
+CREATE TABLE bup_ddl_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
+CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MYISAM;
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=INNODB;
+CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MYISAM;
+con1: Loading data
+INSERT INTO bup_ddl_blocker.t1 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("03 Some data to test");
+INSERT INTO bup_ddl_blocker.t2 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t2 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t2 VALUES ("03 Some data to test");
+INSERT INTO bup_ddl_blocker.t3 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t3 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t3 VALUES ("03 Some data to test");
+INSERT INTO bup_ddl_blocker.t4 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t4 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t4 VALUES ("03 Some data to test");
+DROP TABLE IF EXISTS bup_ddl_blocker.t1, bup_ddl_blocker.t2,
+bup_ddl_blocker.t3, bup_ddl_blocker.t4;
+con1: Creating tables
+CREATE TABLE bup_ddl_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
+con1: Loading data
+INSERT INTO bup_ddl_blocker.t1 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("03 Some data to test");
+Part A
+con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+get_lock("DDL_blocked", 0)
+1
+con1: Get a backup going and stop after the DDL blocker is fired.
+BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+con6: Checking locks
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "BACKUP DATABASE%";
+state	info
+debug_sync_point: DDL_blocked	BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak"
+Set ddl timeout to 1 second
+SET ddl_wait_timeout = 1;
+SHOW VARIABLES LIKE 'ddl%';
+Variable_name	Value
+ddl_wait_timeout	1
+con2: Try a ddl operation and watch it expire
+CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The DDL operation has timed out for query CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY.
+release the lock.
+con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+release_lock("DDL_blocked")
+1
+backup_id
+#
+Part B
+con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+get_lock("DDL_blocked", 0)
+1
+con1: Get a backup going and stop after the DDL blocker is fired.
+BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+con6: Checking locks
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST 
+WHERE info LIKE "BACKUP DATABASE%";
+state	info
+debug_sync_point: DDL_blocked	BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak"
+Set ddl timeout to 0 seconds
+SET ddl_wait_timeout = 0;
+SHOW VARIABLES LIKE 'ddl%';
+Variable_name	Value
+ddl_wait_timeout	0
+con2: Try a ddl operation and it should expire
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The DDL operation has timed out for query CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY.
+SET ddl_wait_timeout = 100;
+SHOW VARIABLES LIKE 'ddl%';
+Variable_name	Value
+ddl_wait_timeout	100
+con3: Try a ddl operation and it should not expire
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+con6: Checking locks
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "CREATE TABLE bup_ddl_blocker.t3%";
+state	info
+DDL blocker: DDL is blocked	CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY
+release the lock.
+con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+release_lock("DDL_blocked")
+1
+backup_id
+#
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+Tables_in_bup_ddl_blocker	Table_type
+t1	BASE TABLE
+t3	BASE TABLE
+Part C
+con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+get_lock("DDL_blocked", 0)
+1
+con1: Get a backup going and stop after the DDL blocker is fired.
+BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+con6: Checking locks
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "BACKUP DATABASE%";
+state	info
+debug_sync_point: DDL_blocked	BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak"
+Set ddl timeout to 0 seconds
+SET ddl_wait_timeout = 0;
+SHOW VARIABLES LIKE 'ddl%';
+Variable_name	Value
+ddl_wait_timeout	0
+con2: Try a ddl operation and it should expire
+CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The DDL operation has timed out for query CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY.
+SET ddl_wait_timeout = 0;
+SHOW VARIABLES LIKE 'ddl%';
+Variable_name	Value
+ddl_wait_timeout	0
+con3: Try a ddl operation and it should expire
+CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY;
+ERROR HY000: The DDL operation has timed out for query CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY.
+release the lock.
+con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+release_lock("DDL_blocked")
+1
+backup_id
+#
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+Tables_in_bup_ddl_blocker	Table_type
+t1	BASE TABLE
+t3	BASE TABLE
+DROP DATABASE bup_ddl_blocker;
diff -Nrup a/mysql-test/t/backup_ddl_blocker_timeout.test b/mysql-test/t/backup_ddl_blocker_timeout.test
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/t/backup_ddl_blocker_timeout.test	2008-05-01 13:27:33 -04:00
@@ -0,0 +1,259 @@
+#
+# This test is for the DDL blocker timeout feature.
+# TODO : Add a native driver to the test when one becomes available
+#
+# Notes
+#   You must use a dedicated connection for getting and releasing locks.
+# Do not issue a get_lock() or release_lock() in the same connection
+# (thread) as code that calls BACKUP_BREAKPOINT(). Using the same connection
+# to get/release locks and run code that issues BACKUP_BREAKPOINTs will result
+# in an assertion using DEBUG_ASSERT(thd->ull == NULL) from debug_sync_point()
+# in item_func.cc.
+#
+
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/not_embedded.inc
+
+#
+# Remove backup files (if they exist)
+#
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker_orig.bak;
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak;
+
+#
+# Connections used in this test
+#
+# con1       used to create data, load data, and run the backup 
+# con2-con5  used for DDL statements: 2 before backup and 2 during backup
+# con6       used for setting and releasing breakpoints
+#
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connect (con3,localhost,root,,);
+connect (con4,localhost,root,,);
+connect (con5,localhost,root,,);
+connect (con6,localhost,root,,);
+
+connection con1;
+
+# Setup the server to use the backup breakpoints
+SET GLOBAL debug="d,backup_debug:d,backup";
+
+# Create data for this test and tailor it to the test.
+--source include/backup_ddl_create_data.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS bup_ddl_blocker.t1, bup_ddl_blocker.t2,
+                     bup_ddl_blocker.t3, bup_ddl_blocker.t4;
+--enable_warnings
+
+# Create a table and load it with data.
+--echo con1: Creating tables
+CREATE TABLE bup_ddl_blocker.t1 (col_a CHAR(40)) ENGINE=INNODB;
+
+--echo con1: Loading data
+INSERT INTO bup_ddl_blocker.t1 VALUES ("01 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("02 Some data to test");
+INSERT INTO bup_ddl_blocker.t1 VALUES ("03 Some data to test");
+
+#
+# Part A - test timeout for one session 
+#
+--echo Part A
+
+connection con5;
+
+# Set the breakpoint for DDL in progress.
+--echo con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
+
+connection con1;
+
+--echo con1: Get a backup going and stop after the DDL blocker is fired.
+send BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+
+connection con6;
+
+--echo con6: Checking locks
+let $wait_condition = SELECT state = "debug_sync_point: DDL_blocked"
+                      FROM INFORMATION_SCHEMA.PROCESSLIST
+                      WHERE info LIKE "BACKUP DATABASE%";
+--source include/wait_condition.inc
+
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "BACKUP DATABASE%";
+
+connection con2;
+
+--echo Set ddl timeout to 1 second
+SET ddl_wait_timeout = 1; 
+SHOW VARIABLES LIKE 'ddl%';
+
+--echo con2: Try a ddl operation and watch it expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t2 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con5;
+--echo release the lock.
+--echo con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+
+# Reconnect to con1 and let backup finish.
+
+connection con1;
+--replace_column 1 #
+reap;
+
+#
+# Part B - test timeout for a session with a timeout, 
+#          and a session with no timeout (ddl_wait_timeout = 0)
+#
+--echo Part B
+
+connection con5;
+
+# Set the breakpoint for DDL in progress.
+--echo con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
+
+connection con1;
+
+--echo con1: Get a backup going and stop after the DDL blocker is fired.
+send BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+
+connection con6;
+
+--echo con6: Checking locks
+let $wait_condition = SELECT state = "debug_sync_point: DDL_blocked"
+                      FROM INFORMATION_SCHEMA.PROCESSLIST
+                      WHERE info LIKE "BACKUP DATABASE%";
+--source include/wait_condition.inc
+
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST 
+WHERE info LIKE "BACKUP DATABASE%";
+
+connection con2;
+
+--echo Set ddl timeout to 0 seconds
+SET ddl_wait_timeout = 0; 
+SHOW VARIABLES LIKE 'ddl%';
+
+--echo con2: Try a ddl operation and it should expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con3;
+
+SET ddl_wait_timeout = 100;
+SHOW VARIABLES LIKE 'ddl%';
+
+--echo con3: Try a ddl operation and it should not expire
+send CREATE TABLE bup_ddl_blocker.t3 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con6;
+
+--echo con6: Checking locks
+let $wait_condition = SELECT state = "DDL blocker: DDL is blocked"
+                      FROM INFORMATION_SCHEMA.PROCESSLIST
+                      WHERE info LIKE "CREATE TABLE bup_ddl_blocker.t3%";
+--source include/wait_condition.inc
+
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "CREATE TABLE bup_ddl_blocker.t3%";
+
+connection con5;
+
+--echo release the lock.
+--echo con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+
+# Reconnect to con1 and let backup finish.
+
+connection con1;
+--replace_column 1 #
+reap;
+
+connection con3;
+reap;
+
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+
+#
+# Part C - test default behavior: timeout if ddl_wait_timeout = 0
+#
+--echo Part C
+
+connection con5;
+
+# Set the breakpoint for DDL in progress.
+--echo con5: Getting lock on DDL in progress.
+SELECT get_lock("DDL_blocked", 0);
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
+
+connection con1;
+
+--echo con1: Get a backup going and stop after the DDL blocker is fired.
+send BACKUP DATABASE bup_ddl_blocker TO "bup_ddl_blocker.bak";
+
+connection con6;
+
+--echo con6: Checking locks
+let $wait_condition = SELECT state = "debug_sync_point: DDL_blocked"
+                      FROM INFORMATION_SCHEMA.PROCESSLIST
+                      WHERE info LIKE "BACKUP DATABASE%";
+--source include/wait_condition.inc
+
+SELECT state, info FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE info LIKE "BACKUP DATABASE%";
+
+connection con2;
+
+--echo Set ddl timeout to 0 seconds
+SET ddl_wait_timeout = 0; 
+SHOW VARIABLES LIKE 'ddl%';
+
+--echo con2: Try a ddl operation and it should expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con3;
+
+SET ddl_wait_timeout = 0;
+SHOW VARIABLES LIKE 'ddl%';
+
+--echo con3: Try a ddl operation and it should expire
+--error ER_DDL_TIMEOUT
+CREATE TABLE bup_ddl_blocker.t4 (col_a CHAR(40)) ENGINE=MEMORY;
+
+connection con5;
+
+--echo release the lock.
+--echo con5: Releasing lock
+SELECT release_lock("DDL_blocked");
+
+# Reconnect to con1 and let backup finish.
+
+connection con1;
+--replace_column 1 #
+reap;
+
+USE bup_ddl_blocker;
+SHOW FULL TABLES;
+
+DROP DATABASE bup_ddl_blocker;
+
+--remove_file $MYSQLTEST_VARDIR/master-data/bup_ddl_blocker.bak
diff -Nrup a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
--- a/mysql-test/t/disabled.def	2008-04-21 06:45:26 -04:00
+++ b/mysql-test/t/disabled.def	2008-05-01 13:27:26 -04:00
@@ -27,6 +27,7 @@ user_limits          : Bug#23921 2007-12
 backup                :BUG#34235 pending replacement of test facility with WL#4259
 backup_commit_blocker :BUG#34235 pending replacement of test facility with WL#4259
 backup_ddl_blocker    :BUG#34235 pending replacement of test facility with WL#4259
+backup_ddl_blocker_timeout    :BUG#34235 pending replacement of test facility with WL#4259
 backup_progress       :BUG#34235 pending replacement of test facility with WL#4259
 backup_security       :BUG#34235 pending replacement of test facility with WL#4259
 backup_snapshot       :BUG#34235 pending replacement of test facility with WL#4259
diff -Nrup a/sql/ddl_blocker.cc b/sql/ddl_blocker.cc
--- a/sql/ddl_blocker.cc	2007-12-12 15:13:23 -05:00
+++ b/sql/ddl_blocker.cc	2008-05-01 13:27:27 -04:00
@@ -101,29 +101,47 @@ void DDL_blocker_class::end_DDL()
 /**
     check_DDL_blocker
 
-    Check to see if we are blocked from continuing. If so,
-    wait until the blocked process signals the condition.
+    Check to see if we are blocked from continuing. If so, wait until block is 
+    removed or the timeout specified by ddl_block_timeout variable occurs.
+    
+    @param[in] thd        The THD object from the caller.
 
-    @param thd The THD object from the caller.
-    @returns TRUE
+    @returns TRUE if not blocked
+    @returns FALSE if ddl is blocked and timeout occurs
   */
 my_bool DDL_blocker_class::check_DDL_blocker(THD *thd)
 {
+  int ret = 0;
+  struct timespec ddl_timeout;
   DBUG_ENTER("check_DDL_blocker()");
   BACKUP_BREAKPOINT("DDL_not_blocked");
 
+  set_timespec(ddl_timeout, thd->ddl_wait_timeout);
+
   /*
     Check the ddl blocker condition. Rest until ddl blocker is released.
   */
   pthread_mutex_lock(&THR_LOCK_DDL_is_blocked);
   thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
                   "DDL blocker: DDL is blocked");
-  while (DDL_blocked && !thd->DDL_exception)
-    pthread_cond_wait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked);
-  start_DDL();
-  thd->exit_cond("DDL blocker: Ok to run DDL");
-  BACKUP_BREAKPOINT("DDL_in_progress");
-  DBUG_RETURN(TRUE);
+  while (DDL_blocked && !thd->DDL_exception && (ret == 0))
+  {
+    if (thd->ddl_wait_timeout == 0)
+      ret = -1;
+    else
+      ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+                                  &ddl_timeout);
+  }
+  thd->exit_cond("DDL blocker: DDL is not blocked");
+  if (ret == 0)
+  {
+    start_DDL();
+    BACKUP_BREAKPOINT("DDL_in_progress");
+  }
+  else
+    my_error(ER_DDL_TIMEOUT, MYF(0), thd->query);
+
+  DBUG_RETURN(ret == 0);
 }
 
 /**
diff -Nrup a/sql/set_var.cc b/sql/set_var.cc
--- a/sql/set_var.cc	2008-04-01 09:44:53 -04:00
+++ b/sql/set_var.cc	2008-05-01 13:27:27 -04:00
@@ -227,6 +227,7 @@ static sys_var_long_ptr	sys_concurrent_i
 static sys_var_long_ptr	sys_connect_timeout(&vars, "connect_timeout",
 					    &connect_timeout);
 static sys_var_const_str       sys_datadir(&vars, "datadir", mysql_real_data_home);
+static sys_var_ddl_wait_timeout sys_ddl_wait_timeout(&vars, "ddl_wait_timeout");
 #ifndef DBUG_OFF
 static sys_var_thd_dbug        sys_dbug(&vars, "debug");
 #endif
@@ -2644,6 +2645,24 @@ uchar *sys_var_last_insert_id::value_ptr
 bool sys_var_insert_id::update(THD *thd, set_var *var)
 {
   thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
+  return 0;
+}
+
+
+uchar *sys_var_ddl_wait_timeout::value_ptr(THD *thd, enum_var_type type,
+				   LEX_STRING *base)
+{
+  thd->sys_var_tmp.ulong_value= thd->ddl_wait_timeout;
+  return (uchar*) &thd->sys_var_tmp.ulonglong_value;
+}
+
+
+bool sys_var_ddl_wait_timeout::update(THD *thd, set_var *var)
+{
+  if (var->save_result.ulong_value > (LONG_MAX/1000))
+    thd->ddl_wait_timeout= LONG_MAX/1000;
+  else
+    thd->ddl_wait_timeout= var->save_result.ulong_value;
   return 0;
 }
 
diff -Nrup a/sql/set_var.h b/sql/set_var.h
--- a/sql/set_var.h	2008-03-27 06:13:13 -04:00
+++ b/sql/set_var.h	2008-05-01 13:27:28 -04:00
@@ -620,6 +620,19 @@ public:
 };
 
 
+class sys_var_ddl_wait_timeout :public sys_var
+{
+public:
+  sys_var_ddl_wait_timeout(sys_var_chain *chain, const char *name_arg)
+    :sys_var(name_arg)
+  { chain_sys_var(chain); }
+  bool update(THD *thd, set_var *var);
+  bool check_type(enum_var_type type) { return type == OPT_GLOBAL; }
+  SHOW_TYPE show_type() { return SHOW_LONG; }
+  uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
+};
+
+
 class sys_var_insert_id :public sys_var
 {
 public:
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt	2008-04-21 06:45:27 -04:00
+++ b/sql/share/errmsg.txt	2008-05-01 13:27:32 -04:00
@@ -6350,3 +6350,6 @@ ER_BACKUP_GET_META_TS
         eng "Failed to obtain meta-data for tablespace %-.64s."
 ER_BACKUP_CATALOG_ADD_TS
         eng "Failed to add tablespace `%-.64s` to the catalog"
+
+ER_DDL_TIMEOUT
+  eng "The DDL operation has timed out for query %-64s."
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2008-04-07 11:26:38 -04:00
+++ b/sql/sql_class.cc	2008-05-01 13:27:29 -04:00
@@ -524,7 +524,8 @@ THD::THD()
           This is needed to ensure the restore (which uses DDL) is not blocked
           when the DDL blocker is engaged.
   */
-   DDL_exception(FALSE)
+   DDL_exception(FALSE),
+   ddl_wait_timeout(50)
 {
   ulong tmp;
 
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h	2008-04-01 09:44:53 -04:00
+++ b/sql/sql_class.h	2008-05-01 13:27:30 -04:00
@@ -1771,6 +1771,7 @@ public:
           when the DDL blocker is engaged.
   */
   my_bool DDL_exception; // Allow some DDL if there is an exception
+  ulong ddl_wait_timeout;
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   partition_info *work_part_info;
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2008-04-17 06:42:27 -04:00
+++ b/sql/sql_parse.cc	2008-05-01 13:27:31 -04:00
@@ -2282,7 +2282,11 @@ mysql_execute_command(THD *thd)
       TABLE in the same way. That way we avoid that a new table is
       created during a gobal read lock.
     */
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+    {
+      res= 1;
+      goto end_with_restore_list;
+    }
     if (!thd->locked_tables &&
         !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
     {
@@ -2423,7 +2427,8 @@ end_with_restore_list:
     table without having to do a full rebuild.
   */
   {
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     /* Prepare stack copies to be re-execution safe */
     HA_CREATE_INFO create_info;
     Alter_info alter_info(lex->alter_info, thd->mem_root);
@@ -2493,7 +2498,8 @@ end_with_restore_list:
   case SQLCOM_ALTER_TABLE:
     DBUG_ASSERT(first_table == all_tables && first_table != 0);
     {
-      DDL_blocker->check_DDL_blocker(thd);
+      if (!DDL_blocker->check_DDL_blocker(thd))
+        goto error;
       ulong priv=0;
       ulong priv_needed= ALTER_ACL;
       /*
@@ -2605,7 +2611,8 @@ end_with_restore_list:
         goto error;
     }
 
-      DDL_blocker->check_DDL_blocker(thd);
+      if (!DDL_blocker->check_DDL_blocker(thd))
+        goto error;
     if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0))
       {
         DDL_blocker->end_DDL();
@@ -2663,7 +2670,8 @@ end_with_restore_list:
                            UINT_MAX, FALSE))
       goto error; /* purecov: inspected */
     thd->enable_slow_log= opt_log_slow_admin_statements;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_repair_table(thd, first_table, &lex->check_opt);
     DDL_blocker->end_DDL();
     /* ! we write after unlocking the table */
@@ -2718,7 +2726,8 @@ end_with_restore_list:
                            UINT_MAX, FALSE))
       goto error; /* purecov: inspected */
     thd->enable_slow_log= opt_log_slow_admin_statements;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
       mysql_recreate_table(thd, first_table) :
       mysql_optimize_table(thd, first_table, &lex->check_opt);
@@ -2963,7 +2972,8 @@ end_with_restore_list:
       goto error;
     }
 
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_truncate(thd, first_table, 0);
     DDL_blocker->end_DDL();
 
@@ -3068,7 +3078,8 @@ end_with_restore_list:
       /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */
       thd->options|= OPTION_KEEP_LOG;
     }
-      DDL_blocker->check_DDL_blocker(thd);
+      if (!DDL_blocker->check_DDL_blocker(thd))
+        goto error;
     /* DDL and binlog write order protected by LOCK_open */
     res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
 			lex->drop_temporary);
@@ -3316,7 +3327,8 @@ end_with_restore_list:
     if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0,
                      is_schema_db(lex->name.str)))
       break;
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
                               lex->name.str), &create_info, 0);
     DDL_blocker->end_DDL();
@@ -3359,7 +3371,8 @@ end_with_restore_list:
                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
       goto error;
     }
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0);
     DDL_blocker->end_DDL();
     break;
@@ -3402,7 +3415,8 @@ end_with_restore_list:
       goto error;
     }
 
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_upgrade_db(thd, db);
     DDL_blocker->end_DDL();
     if (!res)
@@ -3442,7 +3456,8 @@ end_with_restore_list:
                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
       goto error;
     }
-    DDL_blocker->check_DDL_blocker(thd);
+    if (!DDL_blocker->check_DDL_blocker(thd))
+      goto error;
     res= mysql_alter_db(thd, db->str, &create_info);
     DDL_blocker->end_DDL();
     break;

Thread
bk commit into 6.0 tree (cbell:1.2614) BUG#33414cbell1 May