List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:February 13 2008 10:37pm
Subject:bk commit into 6.0 tree (istruewing:1.2553)
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of istruewing.  When istruewing 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-02-13 23:37:45+01:00, istruewing@stripped +25 -0
  Conversion of backup test to the Test Synchronization Facility
  
  Not to be pushed. This is an example for changing the
  synchronization facility.
  
  It contains the pre-review version of the patch for the
  Test Synchronization Facility
  
  plus sync points in the backup code and synchronization
  statements as replacements for the user level locks.

  libmysqld/CMakeLists.txt@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +1 -1
    Pre-review version of WL 4259 - Test Synchronization Facility

  libmysqld/Makefile.am@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +1 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  mysql-test/mysql-test-run.pl@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +8 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  mysql-test/r/backup_progress.result@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +31 -37
    Changed result for conversion to the Test Synchronization Facility

  mysql-test/r/grant.result@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +4 -4
    Pre-review version of WL 4259 - Test Synchronization Facility

  mysql-test/r/merge.result@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +117 -86
    Pre-review version of WL 4259 - Test Synchronization Facility

  mysql-test/t/backup_progress.test@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +31 -63
    Changed test for conversion to the Test Synchronization Facility

  mysql-test/t/merge.test@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +294 -63
    Pre-review version of WL 4259 - Test Synchronization Facility

  mysys/thr_lock.c@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +13 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/CMakeLists.txt@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +1 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/Makefile.am@stripped, 2008-02-13 23:37:41+01:00, istruewing@stripped +2 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/backup/data_backup.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +2 -0
    New synchronization points for conversion to the
    Test Synchronization Facility

  sql/backup/kernel.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +4 -0
    New synchronization points for conversion to the
    Test Synchronization Facility

  sql/item_func.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +2 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/lex.h@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +7 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/lock.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +2 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/mysqld.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +27 -1
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_base.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +6 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_class.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +9 -1
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_class.h@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +7 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_lex.h@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +4 -1
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_parse.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +15 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_table.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +1 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  sql/sql_yacc.yy@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +107 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

  storage/myisammrg/ha_myisammrg.cc@stripped, 2008-02-13 23:37:42+01:00, istruewing@stripped +4 -0
    Pre-review version of WL 4259 - Test Synchronization Facility

diff -Nrup a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
--- a/libmysqld/CMakeLists.txt	2007-12-13 13:47:11 +01:00
+++ b/libmysqld/CMakeLists.txt	2008-02-13 23:37:41 +01:00
@@ -187,7 +187,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
            ../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
            ../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
            ../sql/partition_info.cc ../sql/sql_connect.cc 
-           ../sql/scheduler.cc
+           ../sql/scheduler.cc ../sql/mysql_test_sync.cc
            ${GEN_SOURCES}
            ${LIB_SOURCES})
 
diff -Nrup a/libmysqld/Makefile.am b/libmysqld/Makefile.am
--- a/libmysqld/Makefile.am	2008-02-08 21:22:26 +01:00
+++ b/libmysqld/Makefile.am	2008-02-13 23:37:41 +01:00
@@ -80,6 +80,7 @@ sqlsources = derror.cc field.cc field_co
 	rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
 	sql_tablespace.cc \
 	rpl_injector.cc my_user.c partition_info.cc \
+	mysql_test_sync.cc \
 	sql_servers.cc ddl_blocker.cc si_objects.cc
 
 libmysqld_int_a_SOURCES= $(libmysqld_sources)
diff -Nrup a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
--- a/mysql-test/mysql-test-run.pl	2008-02-08 17:02:56 +01:00
+++ b/mysql-test/mysql-test-run.pl	2008-02-13 23:37:41 +01:00
@@ -268,6 +268,7 @@ my @default_valgrind_args= ("--show-reac
 my @valgrind_args;
 my $opt_valgrind_path;
 my $opt_callgrind;
+my $opt_test_synchronize= 300; # Default timeout for WAIT_FOR actions.
 
 our $opt_stress=               "";
 our $opt_stress_suite=     "main";
@@ -617,6 +618,7 @@ sub command_line_setup () {
              'valgrind-option=s'        => \@valgrind_args,
              'valgrind-path=s'          => \$opt_valgrind_path,
 	     'callgrind'                => \$opt_callgrind,
+	     'test-synchronize=i'       => \$opt_test_synchronize,
 
              # Stress testing 
              'stress'                   => \$opt_stress,
@@ -3590,6 +3592,10 @@ sub mysqld_arguments ($$$$) {
   # see BUG#28359
   mtr_add_arg($args, "%s--connect-timeout=60", $prefix);
 
+  # Enable the TEST SYNCHRONIZE facility, set default wait timeout.
+  # Facility stays disabled if timeout value is zero.
+  mtr_add_arg($args, "%s--test-synchronize=%s", $prefix,
+              $opt_test_synchronize);
 
   # When mysqld is run by a root user(euid is 0), it will fail
   # to start unless we specify what user to run as. If not running
@@ -5032,6 +5038,8 @@ Options for coverage, profiling etc
                         can be specified more then once
   valgrind-path=[EXE]   Path to the valgrind executable
   callgrind             Instruct valgrind to use callgrind
+  test-synchronize=NUM  Set default timeout for WAIT_FOR test synchronize
+                        actions. Disable facility with NUM=0.
 
 Misc options
 
diff -Nrup a/mysql-test/r/backup_progress.result b/mysql-test/r/backup_progress.result
--- a/mysql-test/r/backup_progress.result	2007-12-20 21:32:15 +01:00
+++ b/mysql-test/r/backup_progress.result	2008-02-13 23:37:41 +01:00
@@ -1,6 +1,6 @@
 DROP DATABASE IF EXISTS backup_progress;
 DROP TABLE IF EXISTS backup_progress.t1_res;
-SET GLOBAL debug="d,backup_debug:d,backup";
+SET GLOBAL debug="+d,backup_debug,backup";
 CREATE DATABASE backup_progress;
 con1: Create table and new users.
 CREATE TABLE backup_progress.t1 (a char(30)) ENGINE=MYISAM;
@@ -25,48 +25,44 @@ INSERT INTO backup_progress.t3 VALUES ("
 INSERT INTO backup_progress.t3 VALUES ("03 Test #1 - progress");
 INSERT INTO backup_progress.t3 VALUES ("04 Test #1 - progress");
 Do backup of database
-SELECT get_lock("bp_starting_state", 0);
-get_lock("bp_starting_state", 0)
-1
+con2: Activate sync points for the backup statement.
+TEST SYNCHRONIZE before_backup_start_backup SIGNAL started   WAIT_FOR do_run;
+TEST SYNCHRONIZE  after_backup_start_backup SIGNAL phase1    WAIT_FOR backup;
+TEST SYNCHRONIZE  after_backup_validated    SIGNAL validated WAIT_FOR do_phase2;
+TEST SYNCHRONIZE before_backup_binlog       SIGNAL phase2    WAIT_FOR finish;
 con2: Send backup command.
 BACKUP DATABASE backup_progress to 'backup_progress_orig.bak';
-con1: Checking locks.
+con1: Wait for the backup to be started.
+TEST SYNCHRONIZE now WAIT_FOR started;
 con1: Checking progress.
+con1: Display progress
 INSERT INTO backup_progress.t1_res (id) SELECT backup_id FROM mysql.online_backup WHERE command LIKE "BACKUP DATABASE backup_progress%";
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 starting
-con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-get_lock("bp_running_state", 0)
-1
-con1: Checking locks.
+con1: Let backup step to running state.
+TEST SYNCHRONIZE now SIGNAL do_run WAIT_FOR phase1;
 con1: Checking progress.
+con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 running
-con1: Advance the lock.
-SELECT get_lock("bp_vp_state", 0);
-get_lock("bp_vp_state", 0)
-1
-con1: Checking locks.
+con1: Let backup do the backup phase1.
+TEST SYNCHRONIZE now SIGNAL backup WAIT_FOR validated;
 con1: Checking progress.
+con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 validity point
-con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-get_lock("bp_running_state", 0)
-1
-con1: Checking locks.
+con1: Let backup do the backup phase2.
+TEST SYNCHRONIZE now SIGNAL do_phase2 WAIT_FOR phase2;
 con1: Checking progress.
+con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 running
-con1: Advance the lock.
-SELECT release_lock("bp_running_state");
-release_lock("bp_running_state")
-1
+con1: Let backup finish.
+TEST SYNCHRONIZE now SIGNAL finish;
 con2: Finish backup command
 backup_id
 #
@@ -97,33 +93,31 @@ backup_id	object	start_time	stop_time	to
 #	backup kernel	#	#	0	0	0	running
 #	backup kernel	#	#	0	0	0	complete
 Do restore of database
-SELECT get_lock("bp_starting_state", 0);
-get_lock("bp_starting_state", 0)
-1
 DELETE FROM backup_progress.t1_res;
+con2: Activate sync points for the backup statement.
+TEST SYNCHRONIZE before_backup_start_restore SIGNAL started WAIT_FOR do_run;
+TEST SYNCHRONIZE  after_backup_start_restore SIGNAL running WAIT_FOR finish;
 con2: Send restore command.
 RESTORE FROM 'backup_progress_orig.bak';
-con1: Checking locks.
+con1: Wait for the restore to be started.
+TEST SYNCHRONIZE now WAIT_FOR started;
 con1: Checking progress.
+con1: Display progress
 select * from backup_progress.t1_res;
 id
 INSERT INTO backup_progress.t1_res (id) SELECT backup_id FROM mysql.online_backup WHERE command LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 starting
-con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-get_lock("bp_running_state", 0)
-1
-con1: Checking locks.
+con1: Let restore step to running state.
+TEST SYNCHRONIZE now SIGNAL do_run WAIT_FOR running;
 con1: Checking progress.
+con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 backup_state
 running
-con1: Advance the lock.
-SELECT release_lock("bp_running_state");
-release_lock("bp_running_state")
-1
+con1: Let restore do its job and finish.
+TEST SYNCHRONIZE now SIGNAL finish;
 con2: Finish restore command
 backup_id
 #
diff -Nrup a/mysql-test/r/grant.result b/mysql-test/r/grant.result
--- a/mysql-test/r/grant.result	2008-02-05 10:25:53 +01:00
+++ b/mysql-test/r/grant.result	2008-02-13 23:37:41 +01:00
@@ -213,14 +213,14 @@ set sql_quote_show_create=0;
 show grants for drop_user@localhost;
 Grants for drop_user@localhost
 GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
-GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
-GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON `test`.t1 TO 'drop_user'@'localhost'
 set sql_mode="ansi_quotes";
 show grants for drop_user@localhost;
 Grants for drop_user@localhost
 GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
-GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
-GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+GRANT ALL PRIVILEGES ON "test".* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON "test".t1 TO 'drop_user'@'localhost'
 set sql_quote_show_create=1;
 show grants for drop_user@localhost;
 Grants for drop_user@localhost
diff -Nrup a/mysql-test/r/merge.result b/mysql-test/r/merge.result
--- a/mysql-test/r/merge.result	2007-12-13 13:56:17 +01:00
+++ b/mysql-test/r/merge.result	2008-02-13 23:37:41 +01:00
@@ -1,3 +1,4 @@
+TEST SYNCHRONIZE RESET;
 drop table if exists t1,t2,t3,t4,t5,t6;
 drop database if exists mysqltest;
 create table t1 (a int not null primary key auto_increment, message char(20));
@@ -1071,28 +1072,59 @@ UNLOCK TABLES;
 DROP TABLE t1, t2, t3, t4;
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST;
+connection con1
+TEST SYNCHRONIZE after_admin_flush SIGNAL admin_flush WAIT_FOR end_repair;
 REPAIR TABLE t1;
+connection default;
+TEST SYNCHRONIZE NOW WAIT_FOR admin_flush;
+TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 3;
+TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL end_repair;
 INSERT INTO t2 VALUES (1);
+TEST SYNCHRONIZE NOW SIGNAL end_repair;
+connection con1
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
+connection default;
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2;
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST;
 LOCK TABLE t1 WRITE;
-INSERT INTO t2 VALUES (1);
 REPAIR TABLE t1;
 Table	Op	Msg_type	Msg_text
 test.t1	repair	status	OK
+connection con1
+TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 3;
+TEST SYNCHRONIZE after_insert SIGNAL end_repair;
+TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL end_repair;
+INSERT INTO t2 VALUES (1);
+connection default;
+TEST SYNCHRONIZE NOW WAIT_FOR end_repair;
 UNLOCK TABLES;
+connection con1
+connection default;
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2;
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 LOCK TABLE t1 WRITE;
+connection con1
+TEST SYNCHRONIZE before_lock_tables_takes_lock
+SIGNAL opened WAIT_FOR flushed;
+TEST SYNCHRONIZE wait_for_lock SIGNAL locked EXECUTE 2;
+TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL locked;
+TEST SYNCHRONIZE after_insert SIGNAL locked;
 INSERT INTO t1 VALUES (1);
+connection default
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
 FLUSH TABLES;
-FLUSH TABLES;
+TEST SYNCHRONIZE NOW WAIT_FOR locked;
 SELECT * FROM t1;
 c1
 UNLOCK TABLES;
+connection con1
+connection default
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1;
 #
 # Extra tests for Bug#26379 - Combination of FLUSH TABLE and
@@ -1611,6 +1643,7 @@ c1
 33
 DELETE FROM t4 WHERE c1 = 33;
 DROP TRIGGER t3_ai;
+UNLOCK TABLES;
 #
 # Trigger with table use on child
 DELETE FROM t4 WHERE c1 = 4;
@@ -1793,9 +1826,9 @@ ALTER TABLE t2 UNION=(t3,t1);
 SELECT * FROM t2;
 ERROR HY000: Table 't3' is differently defined or of non-MyISAM type or doesn't exist
 DROP TABLE t1, t2, t3;
-CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
-CREATE TABLE t2 (c1 INT) ENGINE= MyISAM;
-CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2);
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2);
 INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (2);
 SELECT * FROM t3;
@@ -1807,88 +1840,25 @@ SELECT * FROM t3;
 c1
 2
 DROP TABLE t1, t2, t3;
-CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER);
-SET @rnd_max= 2147483647;
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-SET @rnd= RAND();
-SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-SET @id_rev= @rnd_max - @id;
-SET @grp= CAST(127.0 * @rnd AS UNSIGNED);
-INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev);
-set @@read_buffer_size=2*1024*1024;
-CREATE TABLE t2 SELECT * FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-CREATE TABLE t3 (id INTEGER, grp TINYINT, id_rev INTEGER)
-ENGINE= MRG_MYISAM UNION= (t1, t2);
-SELECT COUNT(*) FROM t1;
-COUNT(*)
-130
-SELECT COUNT(*) FROM t2;
-COUNT(*)
-80
-SELECT COUNT(*) FROM t3;
-COUNT(*)
-210
-SELECT COUNT(DISTINCT a1.id) FROM t3 AS a1, t3 AS a2
-WHERE a1.id = a2.id GROUP BY a2.grp;
+CREATE TABLE t1 (c1 REAL) ENGINE=MyISAM;
+CREATE TABLE t2 (c1 REAL) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(0.1);
+INSERT INTO t2 VALUES(0.2);
+CREATE TABLE t3 (c1 REAL) ENGINE=MRG_MYISAM UNION=(t1,t2);
+connection con1
+TEST SYNCHRONIZE before_acos_function SIGNAL 'select' WAIT_FOR truncated;
+SELECT ACOS(c1) FROM t3;
+connection default
+TEST SYNCHRONIZE NOW WAIT_FOR 'select';
+TEST SYNCHRONIZE before_wait_locked_tname SIGNAL truncated;
 TRUNCATE TABLE t1;
-SELECT COUNT(*) FROM t1;
-COUNT(*)
-0
-SELECT COUNT(*) FROM t2;
-COUNT(*)
-80
-SELECT COUNT(*) FROM t3;
-COUNT(*)
-80
+TEST SYNCHRONIZE NOW SIGNAL truncated;
+connection con1
+connection default
+SELECT ACOS(c1) FROM t3;
+ACOS(c1)
+1.369438406004566
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2, t3;
 CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
 CREATE TABLE t2 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
@@ -1984,3 +1954,64 @@ test.t1	optimize	status	OK
 FLUSH TABLES m1, t1;
 UNLOCK TABLES;
 DROP TABLE t1, m1;
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+connection con1
+TEST SYNCHRONIZE before_myisammrg_attach SIGNAL attach WAIT_FOR flushed;
+INSERT INTO m1 VALUES (2);
+connection default;
+TEST SYNCHRONIZE NOW WAIT_FOR attach;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
+FLUSH TABLE m1;
+connection con1
+connection default;
+SELECT * FROM m1;
+c1
+2
+TEST SYNCHRONIZE RESET;
+DROP TABLE m1, t1;
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+connection con1
+TEST SYNCHRONIZE before_myisammrg_attach SIGNAL attach WAIT_FOR store_lock1;
+TEST SYNCHRONIZE before_myisammrg_store_lock
+SIGNAL store_lock2 WAIT_FOR flushed;
+INSERT INTO m1 VALUES (2);
+connection default;
+TEST SYNCHRONIZE NOW WAIT_FOR attach;
+TEST SYNCHRONIZE before_myisammrg_store_lock
+SIGNAL store_lock1 WAIT_FOR store_lock2;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
+FLUSH TABLE m1;
+connection con1
+connection default;
+SELECT * FROM m1;
+c1
+2
+TEST SYNCHRONIZE RESET;
+DROP TABLE m1, t1;
+CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
+LOCK TABLE t1 WRITE;
+connection con1
+TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 2;
+TEST SYNCHRONIZE before_lock_tables_takes_lock
+SIGNAL opened WAIT_FOR flushed EXECUTE 2;
+TEST SYNCHRONIZE wait_for_lock SIGNAL locked EXECUTE 4;
+TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL refresh EXECUTE 2;
+TEST SYNCHRONIZE after_insert SIGNAL locked EXECUTE 2;
+INSERT INTO t1 VALUES (1);
+connection default;
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed EXECUTE 2;
+FLUSH TABLES;
+TEST SYNCHRONIZE NOW WAIT_FOR refresh;
+UNLOCK TABLES;
+LOCK TABLE t1 WRITE;
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+FLUSH TABLES;
+TEST SYNCHRONIZE NOW WAIT_FOR locked;
+UNLOCK TABLES;
+connection con1
+connection default;
+TEST SYNCHRONIZE RESET;
+DROP TABLE t1;
diff -Nrup a/mysql-test/t/backup_progress.test b/mysql-test/t/backup_progress.test
--- a/mysql-test/t/backup_progress.test	2007-12-20 21:32:16 +01:00
+++ b/mysql-test/t/backup_progress.test	2008-02-13 23:37:41 +01:00
@@ -19,7 +19,7 @@ connect (con1,localhost,root,,);
 connect (con2,localhost,root,,);
 
 # Setup the server to use the backup breakpoints
-SET GLOBAL debug="d,backup_debug:d,backup";
+SET GLOBAL debug="+d,backup_debug,backup";
 
 #
 # Test 1 - Check output of backup.
@@ -58,20 +58,19 @@ INSERT INTO backup_progress.t3 VALUES ("
 
 --echo Do backup of database
 
-SELECT get_lock("bp_starting_state", 0);
-
 connection con2;
 
+--echo con2: Activate sync points for the backup statement.
+TEST SYNCHRONIZE before_backup_start_backup SIGNAL started   WAIT_FOR do_run;
+TEST SYNCHRONIZE  after_backup_start_backup SIGNAL phase1    WAIT_FOR backup;
+TEST SYNCHRONIZE  after_backup_validated    SIGNAL validated WAIT_FOR do_phase2;
+TEST SYNCHRONIZE before_backup_binlog       SIGNAL phase2    WAIT_FOR finish;
 --echo con2: Send backup command.
 send BACKUP DATABASE backup_progress to 'backup_progress_orig.bak';
 
 connection con1;
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_starting_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "BACKUP DATABASE %";
---source include/wait_condition.inc
+--echo con1: Wait for the backup to be started.
+TEST SYNCHRONIZE now WAIT_FOR started;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -80,19 +79,12 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "BACKUP DATABASE backup_progress%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 INSERT INTO backup_progress.t1_res (id) SELECT backup_id FROM mysql.online_backup WHERE command LIKE "BACKUP DATABASE backup_progress%";
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_running_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "BACKUP DATABASE %";
---source include/wait_condition.inc
+--echo con1: Let backup step to running state.
+TEST SYNCHRONIZE now SIGNAL do_run WAIT_FOR phase1;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -101,18 +93,11 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "BACKUP DATABASE backup_progress%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT get_lock("bp_vp_state", 0);
-
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_vp_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "BACKUP DATABASE %";
---source include/wait_condition.inc
+--echo con1: Let backup do the backup phase1.
+TEST SYNCHRONIZE now SIGNAL backup WAIT_FOR validated;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -121,18 +106,11 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "BACKUP DATABASE backup_progress%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_running_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "BACKUP DATABASE %";
---source include/wait_condition.inc
+--echo con1: Let backup do the backup phase2.
+TEST SYNCHRONIZE now SIGNAL do_phase2 WAIT_FOR phase2;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -141,11 +119,11 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "BACKUP DATABASE backup_progress%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT release_lock("bp_running_state");
+--echo con1: Let backup finish.
+TEST SYNCHRONIZE now SIGNAL finish;
 
 connection con2;
 --echo con2: Finish backup command
@@ -162,22 +140,19 @@ connection con1;
 
 --echo Do restore of database
 
-SELECT get_lock("bp_starting_state", 0);
-
 connection con2;
 
 DELETE FROM backup_progress.t1_res;
 
+--echo con2: Activate sync points for the backup statement.
+TEST SYNCHRONIZE before_backup_start_restore SIGNAL started WAIT_FOR do_run;
+TEST SYNCHRONIZE  after_backup_start_restore SIGNAL running WAIT_FOR finish;
 --echo con2: Send restore command.
 send RESTORE FROM 'backup_progress_orig.bak';
 
 connection con1;
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_starting_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
---source include/wait_condition.inc
+--echo con1: Wait for the restore to be started.
+TEST SYNCHRONIZE now WAIT_FOR started;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -186,20 +161,13 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 select * from backup_progress.t1_res;
 INSERT INTO backup_progress.t1_res (id) SELECT backup_id FROM mysql.online_backup WHERE command LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT get_lock("bp_running_state", 0);
-
-# Wait for lock to be acquired and execution to reach breakpoint
---echo con1: Checking locks.
-let $wait_condition = SELECT state = "debug_sync_point: bp_running_state"
-                      FROM INFORMATION_SCHEMA.PROCESSLIST
-                      WHERE info LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
---source include/wait_condition.inc
+--echo con1: Let restore step to running state.
+TEST SYNCHRONIZE now SIGNAL do_run WAIT_FOR running;
 
 # Wait for row to be written to progress table.
 --echo con1: Checking progress.
@@ -208,11 +176,11 @@ let $wait_condition = SELECT backup_stat
                       WHERE command LIKE "RESTORE FROM 'backup_progress_orig.bak'%";
 --source include/wait_condition.inc
 
---echo: Display progress
+--echo con1: Display progress
 SELECT backup_state FROM mysql.online_backup AS ob JOIN backup_progress.t1_res as t1 ON ob.backup_id = t1.id;
 
---echo con1: Advance the lock.
-SELECT release_lock("bp_running_state");
+--echo con1: Let restore do its job and finish.
+TEST SYNCHRONIZE now SIGNAL finish;
 
 connection con2;
 --echo con2: Finish restore command
diff -Nrup a/mysql-test/t/merge.test b/mysql-test/t/merge.test
--- a/mysql-test/t/merge.test	2007-12-13 13:56:18 +01:00
+++ b/mysql-test/t/merge.test	2008-02-13 23:37:41 +01:00
@@ -2,7 +2,9 @@
 # Test of MERGE TABLES
 #
 
+# Clean up resources used in this test case.
 --disable_warnings
+TEST SYNCHRONIZE RESET;
 drop table if exists t1,t2,t3,t4,t5,t6;
 drop database if exists mysqltest;
 --enable_warnings
@@ -693,12 +695,6 @@ DROP TABLE t1, t2, t3, t4;
 
 #
 # Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table
-# Preparation
-connect (con1,localhost,root,,);
-connect (con2,localhost,root,,);
-connection default;
-#
-# Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table
 # Problem #1
 # A thread trying to lock a MERGE table performed busy waiting while
 # REPAIR TABLE or a similar table administration task was ongoing on one or
@@ -720,12 +716,39 @@ connection default;
 #
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST;
-send REPAIR TABLE t1;
+#
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # When reaching repair code, signal admin_flush and wait for end_repair.
+    TEST SYNCHRONIZE after_admin_flush SIGNAL admin_flush WAIT_FOR end_repair;
+    send REPAIR TABLE t1;
+#
+--echo connection default;
+connection default;
+# Wait that the other thread reaches repair.
+TEST SYNCHRONIZE NOW WAIT_FOR admin_flush;
+#
+# If the bug exists, INSERT will loop infinitely in getting its lock.
+# Bail out if lock retry is done 3 times.
+TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 3;
+# When the bug is fixed, we wait for refresh of repaired table.
+# In this case resume repair thread so that we do not deadlock.
+TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL end_repair;
+# Succeeds with bug fixed.
+INSERT INTO t2 VALUES (1);
+#
+# Resume the other thread. (non-bug fixed case)
+TEST SYNCHRONIZE NOW SIGNAL end_repair;
+#
+    --echo connection con1
     connection con1;
-    sleep 1; # let repair run into its sleep
-    INSERT INTO t2 VALUES (1);
+    reap;
+    disconnect con1;
+#
+--echo connection default;
 connection default;
-reap;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2;
 #
 # Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table
@@ -740,20 +763,39 @@ DROP TABLE t1, t2;
 # This is the same test case as for
 # Bug#26867 - LOCK TABLES + REPAIR + merge table result in memory/cpu hogging
 #
-#
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 CREATE TABLE t2 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1) INSERT_METHOD= LAST;
 LOCK TABLE t1 WRITE;
-    connection con1;
+REPAIR TABLE t1;
+#
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # If the bug exists, the insert will loop infinitely in getting its lock.
+    # Bail out if lock retry is done 3 times.
+    TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 3;
+    # If the bug exists, resume repair thread after reaching the retry limit.
+    TEST SYNCHRONIZE after_insert SIGNAL end_repair;
+    # If the bug is fixed, we wait for refresh of repaired table.
+    # In this case resume repair thread so that we do not deadlock.
+    TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL end_repair;
     send INSERT INTO t2 VALUES (1);
+#
+--echo connection default;
 connection default;
-sleep 1; # Let INSERT go into thr_multi_lock().
-REPAIR TABLE t1;
-sleep 2; # con1 performs busy waiting during this sleep.
+# Wait for signal from insert. Would be infinite with bug and no retry limit.
+TEST SYNCHRONIZE NOW WAIT_FOR end_repair;
 UNLOCK TABLES;
+#
+    --echo connection con1
     connection con1;
+    # Succeeds with bug fixed.
     reap;
+    disconnect con1;
+#
+--echo connection default;
 connection default;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2;
 #
 # Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table
@@ -775,28 +817,54 @@ DROP TABLE t1, t2;
 # FLUSH TABLES must happen while the INSERT was on its way from
 # wait_for_tables() to the next call of thr_multi_lock(). This needed to be
 # supported by a sleep to make it repeatable.
+# In >= 5.0, when waiting after open_tables() one FLUSH is sufficient
+# to allow the INSERT to step in.
 #
 CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
 LOCK TABLE t1 WRITE;
-    connection con1;
+#
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # After open, wait for flush.
+    TEST SYNCHRONIZE before_lock_tables_takes_lock
+      SIGNAL opened WAIT_FOR flushed;
+    # If bug is fixed, INSERT will go into wait_for_lock.
+    # Retain action after use. First used by general_log.
+    TEST SYNCHRONIZE wait_for_lock SIGNAL locked EXECUTE 2;
+    # Alternatively INSERT can wait for refresh in open_table().
+    TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL locked;
+    # If bug is not fixed, INSERT will succeed. Pretend locked.
+    TEST SYNCHRONIZE after_insert SIGNAL locked;
     send INSERT INTO t1 VALUES (1);
+#
+--echo connection default
 connection default;
-sleep 1; # Let INSERT go into thr_multi_lock().
-FLUSH TABLES;
-sleep 1; # Let INSERT go through wait_for_tables() where it sleeps.
+# Wait until INSERT opened the table.
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+#
+# Let INSERT exploit the gap when flush waits wthout lock
+# for other threads to close the tables.
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
 FLUSH TABLES;
-# This should give no result. But it will with sleep(2) at the right place.
+#
+# Wait until INSERT is locked (bug fixed) or finished (bug not fixed).
+TEST SYNCHRONIZE NOW WAIT_FOR locked;
+#
+# This should give no result. But it will if the bug exists.
 SELECT * FROM t1;
 UNLOCK TABLES;
+#
+    --echo connection con1
     connection con1;
     reap;
+    disconnect con1;
+#
+--echo connection default
 connection default;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1;
 #
-# Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE corrupts a MERGE table
-# Cleanup
-disconnect con1;
-disconnect con2;
 #
 --echo #
 --echo # Extra tests for Bug#26379 - Combination of FLUSH TABLE and
@@ -1122,6 +1190,7 @@ SELECT @a;
 SELECT * FROM t4 ORDER BY c1;
 DELETE FROM t4 WHERE c1 = 33;
 DROP TRIGGER t3_ai;
+UNLOCK TABLES;
 --echo #
 --echo # Trigger with table use on child
 DELETE FROM t4 WHERE c1 = 4;
@@ -1225,11 +1294,12 @@ DROP TABLE t1, t2, t3;
 
 #
 # Bug#25038 - Waiting TRUNCATE
+# Truncate failed with error message when table was in use by MERGE.
 #
 # Show that truncate of child table after use of parent table works.
-CREATE TABLE t1 (c1 INT) ENGINE= MyISAM; 
-CREATE TABLE t2 (c1 INT) ENGINE= MyISAM; 
-CREATE TABLE t3 (c1 INT) ENGINE= MRG_MYISAM UNION= (t1, t2); 
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM; 
+CREATE TABLE t2 (c1 INT) ENGINE=MyISAM; 
+CREATE TABLE t3 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1,t2); 
 INSERT INTO t1 VALUES (1);
 INSERT INTO t2 VALUES (2);
 SELECT * FROM t3;
@@ -1238,49 +1308,44 @@ SELECT * FROM t3;
 DROP TABLE t1, t2, t3;
 #
 # Show that truncate of child table waits while parent table is used.
-# (test partly borrowed from count_distinct3.)
-CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER);
-SET @rnd_max= 2147483647;
-let $1 = 10;
-while ($1)
-{
-  SET @rnd= RAND();
-  SET @id = CAST(@rnd * @rnd_max AS UNSIGNED);
-  SET @id_rev= @rnd_max - @id;
-  SET @grp= CAST(127.0 * @rnd AS UNSIGNED); 
-  INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); 
-  dec $1;
-}
-set @@read_buffer_size=2*1024*1024;
-CREATE TABLE t2 SELECT * FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1;
-INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2;
-CREATE TABLE t3 (id INTEGER, grp TINYINT, id_rev INTEGER)
-  ENGINE= MRG_MYISAM UNION= (t1, t2);
-SELECT COUNT(*) FROM t1;
-SELECT COUNT(*) FROM t2;
-SELECT COUNT(*) FROM t3;
-connect (con1,localhost,root,,);
-    # As t3 contains random numbers, results are different from test to test. 
-    # That's okay, because we test only that select doesn't yield an
-    # error. Note, that --disable_result_log doesn't suppress error output.
-    --disable_result_log
-    send SELECT COUNT(DISTINCT a1.id) FROM t3 AS a1, t3 AS a2
-      WHERE a1.id = a2.id GROUP BY a2.grp;
+CREATE TABLE t1 (c1 REAL) ENGINE=MyISAM;
+CREATE TABLE t2 (c1 REAL) ENGINE=MyISAM;
+INSERT INTO t1 VALUES(0.1);
+INSERT INTO t2 VALUES(0.2);
+CREATE TABLE t3 (c1 REAL) ENGINE=MRG_MYISAM UNION=(t1,t2);
+#
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # When reaching acos(), send 'select' and wait for truncated.
+    TEST SYNCHRONIZE before_acos_function SIGNAL 'select' WAIT_FOR truncated;
+    send SELECT ACOS(c1) FROM t3;
+#
+--echo connection default
 connection default;
-sleep 1;
+# Wait for con1 to reach acos().
+TEST SYNCHRONIZE NOW WAIT_FOR 'select';
+#
+# With bug fix present, TRUNCATE runs into wait_for_locked_table_names().
+TEST SYNCHRONIZE before_wait_locked_tname SIGNAL truncated;
 TRUNCATE TABLE t1;
+#
+# With bug fix not present, we need to signal after TRUNCATE.
+TEST SYNCHRONIZE NOW SIGNAL truncated;
+#
+    --echo connection con1
     connection con1;
+    # In non-debug server, the order of select and truncate is undetermined.
+    # So we may have one or two rows here.
+    --disable_result_log
     reap;
     --enable_result_log
     disconnect con1;
+#
+--echo connection default
 connection default;
-SELECT COUNT(*) FROM t1;
-SELECT COUNT(*) FROM t2;
-SELECT COUNT(*) FROM t3;
+SELECT ACOS(c1) FROM t3;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
 DROP TABLE t1, t2, t3;
 
 #
@@ -1380,4 +1445,170 @@ OPTIMIZE TABLE t1;
 FLUSH TABLES m1, t1;
 UNLOCK TABLES;
 DROP TABLE t1, m1;
+#
+# In-depth test.
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # Wait for flush before attaching children.
+    TEST SYNCHRONIZE before_myisammrg_attach SIGNAL attach WAIT_FOR flushed;
+    send INSERT INTO m1 VALUES (2);
+--echo connection default;
+connection default;
+#
+# Wait for con1 to reach attach_merge_children(), then flush and signal.
+TEST SYNCHRONIZE NOW WAIT_FOR attach;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
+FLUSH TABLE m1;
+#
+    --echo connection con1
+    connection con1;
+    reap;
+    disconnect con1;
+--echo connection default;
+connection default;
+SELECT * FROM m1;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
+DROP TABLE m1, t1;
+#
+# Test derived from test program for
+# Bug#30273 - merge tables: Can't lock file (errno: 155)
+# Second test try to step in between lock_count() and store_lock().
+#
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE m1 (c1 INT) ENGINE=MRG_MYISAM UNION=(t1) INSERT_METHOD=LAST;
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    # When reaching attach_merge_children(), signal attach and
+    # wait for store_lock1 before attaching children.
+    # Then run through attach of children until store_lock().
+    # Signal store_lock2 and wait for flushed.
+    TEST SYNCHRONIZE before_myisammrg_attach SIGNAL attach WAIT_FOR store_lock1;
+    TEST SYNCHRONIZE before_myisammrg_store_lock
+      SIGNAL store_lock2 WAIT_FOR flushed;
+    send INSERT INTO m1 VALUES (2);
+--echo connection default;
+connection default;
+#
+# Wait for con1 to reach attach.
+TEST SYNCHRONIZE NOW WAIT_FOR attach;
+# Run until myisammrg store_lock(),
+# then signal store_lock1 and
+# wait for con1 to go through attach until store_lock() (store_lock2),
+# then flush and signal flushed.
+TEST SYNCHRONIZE before_myisammrg_store_lock
+  SIGNAL store_lock1 WAIT_FOR store_lock2;
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
+FLUSH TABLE m1;
+#
+    --echo connection con1
+    connection con1;
+    reap;
+    disconnect con1;
+--echo connection default;
+connection default;
+SELECT * FROM m1;
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
+DROP TABLE m1, t1;
+
+#
+# Coverage test for get_user_var().
+# Same test as for Bug#26379, Problem #3.
+# But mysql_test_sync_lock_retry_limit set to null.
+#
+#CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
+#LOCK TABLE t1 WRITE;
+#    --echo connection con1
+#    connect (con1,localhost,root,,);
+#    # Set a null integer value.
+#    SET @mysql_test_sync_lock_retry_limit= NULL;
+#    TEST SYNCHRONIZE before_lock_tables_takes_lock
+#      SIGNAL opened WAIT_FOR flushed;
+#    TEST SYNCHRONIZE wait_for_lock SIGNAL locked EXECUTE 2;
+#    TEST SYNCHRONIZE after_insert SIGNAL locked;
+#    send INSERT INTO t1 VALUES (1);
+#--echo connection default;
+#connection default;
+#TEST SYNCHRONIZE NOW WAIT_FOR opened;
+#TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed;
+#FLUSH TABLES;
+#TEST SYNCHRONIZE NOW WAIT_FOR locked;
+#UNLOCK TABLES;
+#    --echo connection con1
+#    connection con1;
+#    reap;
+#    disconnect con1;
+#--echo connection default;
+#connection default;
+# Clear test_sync signal.
+#TEST SYNCHRONIZE RESET;
+#DROP TABLE t1;
+#
+# Coverage test for mysql_lock_retry_limit().
+# Similar test as for Bug#26379, Problem #3.
+# But mysql_lock_retry limit set to 2 and FLUSH repeated
+# so that the INSERT results in ER_LOCK_WAIT_TIMEOUT.
+#
+CREATE TABLE t1 (c1 INT) ENGINE= MyISAM;
+LOCK TABLE t1 WRITE;
+#
+    --echo connection con1
+    connect (con1,localhost,root,,);
+    TEST SYNCHRONIZE mysql_lock_retry HIT_LIMIT 2;
+    # After open, wait for flush.
+    TEST SYNCHRONIZE before_lock_tables_takes_lock
+      SIGNAL opened WAIT_FOR flushed EXECUTE 2;
+    # If bug is fixed, INSERT will go into wait_for_lock.
+    # Retain action after use. First used by general_log.
+    TEST SYNCHRONIZE wait_for_lock SIGNAL locked EXECUTE 4;
+    # Alternatively INSERT can wait for refresh in open_table().
+    TEST SYNCHRONIZE before_open_table_wait_refresh SIGNAL refresh EXECUTE 2;
+    # If bug is not fixed, INSERT will succeed. Pretend locked.
+    TEST SYNCHRONIZE after_insert SIGNAL locked EXECUTE 2;
+    #SET debug='+d,test_sync_point,test_sync_exec:+i';
+    send INSERT INTO t1 VALUES (1);
+#
+--echo connection default;
+connection default;
+#SET debug='+d,test_sync_point,test_sync_exec:+i';
+#
+# Wait until INSERT opened the table.
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+#
+# Let INSERT exploit the gap when flush waits wthout lock
+# for other threads to close the tables.
+TEST SYNCHRONIZE after_flush_unlock SIGNAL flushed EXECUTE 2;
+FLUSH TABLES;
+#
+# Wait until INSERT waits for refresh.
+# Then we need to close and reopen the table to let it succed another open.
+TEST SYNCHRONIZE NOW WAIT_FOR refresh;
+UNLOCK TABLES;
+LOCK TABLE t1 WRITE;
+#
+# Wait until INSERT opened the table the second time.
+# Then flush the second time.
+TEST SYNCHRONIZE NOW WAIT_FOR opened;
+FLUSH TABLES;
+#
+# Wait until INSERT is locked (bug fixed) or finished (bug not fixed).
+TEST SYNCHRONIZE NOW WAIT_FOR locked;
+UNLOCK TABLES;
+#
+    --echo connection con1
+    connection con1;
+    # Succeeds if TEST SYNCHRONIZE is disabled
+    --error 0, ER_LOCK_WAIT_TIMEOUT
+    reap;
+    disconnect con1;
+#
+--echo connection default;
+connection default;
+#
+# Clear test_sync signal.
+TEST SYNCHRONIZE RESET;
+DROP TABLE t1;
 
diff -Nrup a/mysys/thr_lock.c b/mysys/thr_lock.c
--- a/mysys/thr_lock.c	2008-01-28 13:52:34 +01:00
+++ b/mysys/thr_lock.c	2008-02-13 23:37:41 +01:00
@@ -386,6 +386,12 @@ static inline my_bool have_specific_lock
 
 static void wake_up_waiters(THR_LOCK *lock);
 
+/**
+  Global pointer to be set if callback function is defined
+  (e.g. in mysqld). See mysql_test_sync.cc.
+*/
+void (*test_sync_wait_for_lock_callback_ptr)(void);
+
 
 static enum enum_thr_lock_result
 wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
@@ -397,6 +403,13 @@ wait_for_lock(struct st_lock_list *wait,
   enum enum_thr_lock_result result= THR_LOCK_ABORTED;
   my_bool can_deadlock= test(data->owner->info->n_cursors);
   DBUG_ENTER("wait_for_lock");
+
+  /*
+    One can use this to signal when a thread is going to wait for a lock.
+    See mysql_test_sync.cc.
+  */
+  if (test_sync_wait_for_lock_callback_ptr)
+    (*test_sync_wait_for_lock_callback_ptr)();
 
   if (!in_wait_list)
   {
diff -Nrup a/sql/CMakeLists.txt b/sql/CMakeLists.txt
--- a/sql/CMakeLists.txt	2008-02-08 21:44:29 +01:00
+++ b/sql/CMakeLists.txt	2008-02-13 23:37:41 +01:00
@@ -78,6 +78,7 @@ ADD_EXECUTABLE(mysqld
                sql_connect.cc scheduler.cc 
                ddl_blocker.cc si_objects.cc
                sql_profile.cc
+               mysql_test_sync.cc mysql_test_sync.h
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
                ${PROJECT_SOURCE_DIR}/include/mysqld_error.h
diff -Nrup a/sql/Makefile.am b/sql/Makefile.am
--- a/sql/Makefile.am	2008-02-08 21:44:55 +01:00
+++ b/sql/Makefile.am	2008-02-13 23:37:41 +01:00
@@ -87,6 +87,7 @@ noinst_HEADERS =	item.h item_func.h item
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
 			probes.h \
+			mysql_test_sync.h \
 			contributors.h sql_servers.h ddl_blocker.h si_objects.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
@@ -132,6 +133,7 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_plugin.cc sql_binlog.cc \
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
 			sql_servers.cc sha2.cc \
+			mysql_test_sync.cc \
 			ddl_blocker.cc si_objects.cc
 
 if HAVE_DTRACE
diff -Nrup a/sql/backup/data_backup.cc b/sql/backup/data_backup.cc
--- a/sql/backup/data_backup.cc	2007-12-13 15:08:42 +01:00
+++ b/sql/backup/data_backup.cc	2008-02-13 23:37:42 +01:00
@@ -653,10 +653,12 @@ int write_table_data(THD* thd, Backup_in
       timing of the validity point.
     */
     BACKUP_BREAKPOINT("bp_vp_state");
+    TEST_SYNCHRONIZE(thd, after_backup_validated);
     info.save_vp_time(vp_time);
     report_ob_vp_time(info.backup_prog_id, vp_time);
     report_ob_state(info.backup_prog_id, BUP_RUNNING);
     BACKUP_BREAKPOINT("bp_running_state");
+    TEST_SYNCHRONIZE(thd, before_backup_binlog);
 
     if (mysql_bin_log.is_open())
       report_ob_binlog_info(info.backup_prog_id, 
diff -Nrup a/sql/backup/kernel.cc b/sql/backup/kernel.cc
--- a/sql/backup/kernel.cc	2008-02-12 01:17:51 +01:00
+++ b/sql/backup/kernel.cc	2008-02-13 23:37:42 +01:00
@@ -168,6 +168,7 @@ execute_backup_command(THD *thd, LEX *le
                                      0, "", lex->backup_dir.str, thd->query);
       report_ob_time(backup_prog_id, start, 0);
       BACKUP_BREAKPOINT("bp_starting_state");
+      TEST_SYNCHRONIZE(thd, before_backup_start_restore);
 
       Restore_info info(thd,*stream);
 
@@ -184,6 +185,7 @@ execute_backup_command(THD *thd, LEX *le
 
       report_ob_state(backup_prog_id, BUP_RUNNING);
       BACKUP_BREAKPOINT("bp_running_state");
+      TEST_SYNCHRONIZE(thd, after_backup_start_restore);
 
       /*
         Freeze all DDL operations by turning on DDL blocker.
@@ -287,6 +289,7 @@ execute_backup_command(THD *thd, LEX *le
                                      0, "", lex->backup_dir.str, thd->query);
       report_ob_time(backup_prog_id, start, 0);
       BACKUP_BREAKPOINT("bp_starting_state");
+      TEST_SYNCHRONIZE(thd, before_backup_start_backup);
 
       info.backup_prog_id= backup_prog_id;
 
@@ -297,6 +300,7 @@ execute_backup_command(THD *thd, LEX *le
       info.save_start_time(start);
       report_ob_state(backup_prog_id, BUP_RUNNING);
       BACKUP_BREAKPOINT("bp_running_state");
+      TEST_SYNCHRONIZE(thd, after_backup_start_backup);
 
       info.save_errors();
 
diff -Nrup a/sql/item_func.cc b/sql/item_func.cc
--- a/sql/item_func.cc	2008-02-08 21:45:30 +01:00
+++ b/sql/item_func.cc	2008-02-13 23:37:42 +01:00
@@ -1689,6 +1689,8 @@ double Item_func_pow::val_real()
 double Item_func_acos::val_real()
 {
   DBUG_ASSERT(fixed == 1);
+  /* One can use this to defer SELECT processing. */
+  TEST_SYNCHRONIZE(current_thd, before_acos_function);
   // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
   volatile double value= args[0]->val_real();
   if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
diff -Nrup a/sql/lex.h b/sql/lex.h
--- a/sql/lex.h	2008-02-08 21:22:28 +01:00
+++ b/sql/lex.h	2008-02-13 23:37:42 +01:00
@@ -105,6 +105,7 @@ static SYMBOL symbols[] = {
   { "CHECK",		SYM(CHECK_SYM)},
   { "CHECKSUM",		SYM(CHECKSUM_SYM)},
   { "CIPHER",		SYM(CIPHER_SYM)},
+  { "CLEAR",            SYM(CLEAR_SYM)},
   { "CLIENT",		SYM(CLIENT_SYM)},
   { "CLOSE",		SYM(CLOSE_SYM)},
   { "COALESCE",		SYM(COALESCE)},
@@ -234,6 +235,7 @@ static SYMBOL symbols[] = {
   { "HAVING",		SYM(HAVING)},
   { "HELP",		SYM(HELP_SYM)},
   { "HIGH_PRIORITY",	SYM(HIGH_PRIORITY)},
+  { "HIT_LIMIT",        SYM(HIT_LIMIT_SYM)},
   { "HOST",		SYM(HOST_SYM)},
   { "HOSTS",		SYM(HOSTS_SYM)},
   { "HOUR",		SYM(HOUR_SYM)},
@@ -478,6 +480,7 @@ static SYMBOL symbols[] = {
   { "SHARE",		SYM(SHARE_SYM)},
   { "SHOW",		SYM(SHOW)},
   { "SHUTDOWN",		SYM(SHUTDOWN)},
+  { "SIGNAL",           SYM(SIGNAL_SYM)},
   { "SIGNED",		SYM(SIGNED_SYM)},
   { "SIMPLE",		SYM(SIMPLE_SYM)},
   { "SLAVE",            SYM(SLAVE)},
@@ -526,16 +529,19 @@ static SYMBOL symbols[] = {
   { "SUSPEND",          SYM(SUSPEND_SYM)},
   { "SWAPS",      SYM(SWAPS_SYM)},
   { "SWITCHES",   SYM(SWITCHES_SYM)},
+  { "SYNCHRONIZE",      SYM(SYNCHRONIZE_SYM)},
   { "TABLE",		SYM(TABLE_SYM)},
   { "TABLES",		SYM(TABLES)},
   { "TABLESPACE",	SYM(TABLESPACE)},
   { "TEMPORARY",	SYM(TEMPORARY)},
   { "TEMPTABLE",	SYM(TEMPTABLE_SYM)},
   { "TERMINATED",	SYM(TERMINATED)},
+  { "TEST",             SYM(TEST_SYM)},
   { "TEXT",		SYM(TEXT_SYM)},
   { "THAN",             SYM(THAN_SYM)},
   { "THEN",		SYM(THEN_SYM)},
   { "TIME",		SYM(TIME_SYM)},
+  { "TIMEOUT",          SYM(TIMEOUT_SYM)},
   { "TIMESTAMP",	SYM(TIMESTAMP)},
   { "TIMESTAMPADD",     SYM(TIMESTAMP_ADD)},
   { "TIMESTAMPDIFF",    SYM(TIMESTAMP_DIFF)},
@@ -582,6 +588,7 @@ static SYMBOL symbols[] = {
   { "VARCHARACTER",	SYM(VARCHAR)},
   { "VARIABLES",	SYM(VARIABLES)},
   { "VARYING",		SYM(VARYING)},
+  { "WAIT_FOR",         SYM(WAIT_FOR_SYM)},
   { "WAIT",		SYM(WAIT_SYM)},
   { "WARNINGS",		SYM(WARNINGS)},
   { "WEEK",		SYM(WEEK_SYM)},
diff -Nrup a/sql/lock.cc b/sql/lock.cc
--- a/sql/lock.cc	2007-12-21 20:27:43 +01:00
+++ b/sql/lock.cc	2008-02-13 23:37:42 +01:00
@@ -351,6 +351,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, 
     */
     reset_lock_data_and_free(&sql_lock);
 retry:
+    TEST_SYNCHRONIZE(thd, mysql_lock_retry);
     if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
     {
       *need_reopen= TRUE;
@@ -1112,6 +1113,7 @@ bool wait_for_locked_table_names(THD *th
       result=1;
       break;
     }
+    TEST_SYNCHRONIZE(thd, before_wait_locked_tname);
     wait_for_condition(thd, &LOCK_open, &COND_refresh);
     pthread_mutex_lock(&LOCK_open);
   }
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2008-02-12 01:17:49 +01:00
+++ b/sql/mysqld.cc	2008-02-13 23:37:42 +01:00
@@ -495,6 +495,7 @@ uint mysqld_port_timeout;
 uint delay_key_write_options, protocol_version;
 uint lower_case_table_names;
 uint tc_heuristic_recover= 0;
+uint opt_test_synchronize= 0;
 uint volatile thread_count, thread_running;
 ulonglong thd_startup_options;
 ulong back_log, connect_timeout, concurrency, server_id;
@@ -1336,6 +1337,8 @@ void clean_up(bool print_message)
 #ifdef USE_REGEX
   my_regex_end();
 #endif
+  /* End the test synchronization facility. See mysql_test_sync.cc */
+  test_sync_end();
 
 #if !defined(EMBEDDED_LIBRARY)
   if (!opt_bootstrap)
@@ -3015,6 +3018,7 @@ SHOW_VAR com_status_vars[]= {
   {"stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
   {"stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
   {"stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
+  {"test_synchronize",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TEST_SYNC]), SHOW_LONG_STATUS},
   {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
   {"uninstall_plugin",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS},
   {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
@@ -3310,6 +3314,10 @@ static int init_common_variables(const c
   sys_var_slow_log_path.value= my_strdup(s, MYF(0));
   sys_var_slow_log_path.value_length= strlen(s);
 
+  /* Initialize the test synchronization facility. See mysql_test_sync.cc */
+  if (opt_test_synchronize && test_sync_init())
+    return 1; /* purecov: tested */
+
   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
     return 1;
   if (my_database_names_init())
@@ -5427,7 +5435,8 @@ enum options_mysqld
 #if HAVE_POOL_OF_THREADS == 1
   OPT_POOL_OF_THREADS,
 #endif
-  OPT_SLAVE_EXEC_MODE
+  OPT_SLAVE_EXEC_MODE,
+  OPT_TEST_SYNCHRONIZE
 };
 
 
@@ -6170,6 +6179,12 @@ log and this option does nothing anymore
    "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.",
    (uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover,
    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"test-synchronize", OPT_TEST_SYNCHRONIZE,
+   "Enable the TEST SYNCHRONIZE facility "
+   "and optionally specify a default wait timeout in seconds. "
+   "A zero value keeps the facility disabled.",
+   (uchar**) &opt_test_synchronize, 0,
+   0, GET_INT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
   {"temp-pool", OPT_TEMP_POOL,
    "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
    (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
@@ -7326,6 +7341,7 @@ static void mysql_init_variables(void)
   bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
   bzero((char *) &global_status_var, sizeof(global_status_var));
   opt_large_pages= 0;
+  opt_test_synchronize= 0;
   key_map_full.set_all();
 
   /* Character sets */
@@ -7983,6 +7999,16 @@ mysqld_get_one_option(int optid,
   case OPT_LOWER_CASE_TABLE_NAMES:
     lower_case_table_names= argument ? atoi(argument) : 1;
     lower_case_table_names_used= 1;
+    break;
+  case OPT_TEST_SYNCHRONIZE:
+    /*
+      Test Synchronization Facility. See mysql_test_sync.cc.
+      Default value is zero (facility disabled).
+      If option is given without an argument, supply a non-zero value.
+      Default timeout for WAIT_FOR action.
+    */
+    if (!argument)
+      opt_test_synchronize= 300; /* purecov: tested */
     break;
   }
   return 0;
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2008-02-02 13:19:47 +01:00
+++ b/sql/sql_base.cc	2008-02-13 23:37:42 +01:00
@@ -1021,6 +1021,8 @@ bool close_cached_tables(THD *thd, TABLE
     close_old_data_files(thd,thd->open_tables,1,1);
     mysql_ha_flush(thd);
 
+    TEST_SYNCHRONIZE(thd, after_flush_unlock);
+
     bool found=1;
     /* Wait until all threads has closed all the tables we had locked */
     DBUG_PRINT("info",
@@ -2898,6 +2900,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *
       */
       if (table->in_use != thd)
       {
+        TEST_SYNCHRONIZE(thd, before_open_table_wait_refresh);
+
         /* wait_for_conditionwill unlock LOCK_open for us */
         wait_for_condition(thd, &LOCK_open, &COND_refresh);
       }
@@ -5170,6 +5174,8 @@ int lock_tables(THD *thd, TABLE_LIST *ta
         thd->set_current_stmt_binlog_row_based_if_mixed();
       }
     }
+
+    TEST_SYNCHRONIZE(thd, before_lock_tables_takes_lock);
 
     if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start),
                                         lock_flag, need_reopen)))
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2008-02-11 22:22:12 +01:00
+++ b/sql/sql_class.cc	2008-02-13 23:37:42 +01:00
@@ -507,7 +507,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),
+   test_sync_action(0)
 {
   ulong tmp;
 
@@ -734,6 +735,9 @@ void THD::init(void)
   update_charset();
   reset_current_stmt_binlog_row_based();
   bzero((char *) &status_var, sizeof(status_var));
+
+  /* Initialize the test synchronization facility. See mysql_test_sync.cc */
+  test_sync_init_thread(this);
 }
 
 
@@ -809,6 +813,10 @@ void THD::cleanup(void)
     lock=locked_tables; locked_tables=0;
     close_thread_tables(this);
   }
+
+  /* End the test synchronization facility. See mysql_test_sync.cc */
+  test_sync_end_thread(this);
+
   mysql_ha_cleanup(this);
   delete_dynamic(&user_var_events);
   hash_free(&user_vars);
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h	2008-02-08 21:22:30 +01:00
+++ b/sql/sql_class.h	2008-02-13 23:37:42 +01:00
@@ -242,6 +242,7 @@ struct Query_cache_tls
   Query_cache_tls() :first_query_block(NULL) {}
 };
 
+#include "mysql_test_sync.h"
 #include "sql_lex.h"				/* Must be here */
 
 class Delayed_insert;
@@ -1748,6 +1749,12 @@ public:
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   partition_info *work_part_info;
 #endif
+
+  /*
+    Pointer to array of TEST SYNCHRONIZE actions.
+    There is one array slot per synchronization point.
+  */
+  struct st_test_sync_action *test_sync_action;
 
   THD();
   ~THD();
diff -Nrup a/sql/sql_lex.h b/sql/sql_lex.h
--- a/sql/sql_lex.h	2008-02-12 01:17:50 +01:00
+++ b/sql/sql_lex.h	2008-02-13 23:37:42 +01:00
@@ -123,10 +123,11 @@ enum enum_sql_command {
   SQLCOM_BACKUP_TEST,
 #endif
   SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
+  SQLCOM_TEST_SYNC,
 
   /*
     When a command is added here, be sure it's also added in mysqld.cc
-    in "struct show_var_st status_vars[]= {" ...
+    in "struct show_var_st com_status_vars[]= {" ...
   */
   /* This should be the last !!! */
   SQLCOM_END
@@ -1733,6 +1734,8 @@ typedef struct st_lex : public Query_tab
   
   bool escape_used;
   bool is_lex_started; /* If lex_start() did run. For debugging. */
+
+  struct st_test_sync_request test_sync_req;
 
   st_lex();
 
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2008-02-11 22:22:13 +01:00
+++ b/sql/sql_parse.cc	2008-02-13 23:37:42 +01:00
@@ -2875,6 +2875,7 @@ end_with_restore_list:
       thd->first_successful_insert_id_in_cur_stmt=
         thd->first_successful_insert_id_in_prev_stmt;
 
+    TEST_SYNCHRONIZE(thd, after_insert);
     break;
   }
   case SQLCOM_REPLACE_SELECT:
@@ -4637,6 +4638,20 @@ create_sp_error:
       break;
     }
     send_ok(thd, 1);
+    break;
+  }
+  case SQLCOM_TEST_SYNC:
+  {
+    LEX *lex= thd->lex;
+    DBUG_PRINT("info", ("case SQLCOM_TEST_SYNC"));
+
+    if (check_global_access(thd, SUPER_ACL))
+      break;
+
+    if (lex->test_sync_req.command == action )
+      VOID(test_sync_set_action(thd, &lex->test_sync_req));
+    else
+      VOID(test_sync_do_command(thd, &lex->test_sync_req));
     break;
   }
   default:
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc	2008-02-02 13:19:48 +01:00
+++ b/sql/sql_table.cc	2008-02-13 23:37:42 +01:00
@@ -4170,6 +4170,7 @@ static bool mysql_admin_table(THD* thd, 
                               RTFC_WAIT_OTHER_THREAD_FLAG |
                               RTFC_CHECK_KILLED_FLAG);
       thd->exit_cond(old_message);
+      TEST_SYNCHRONIZE(thd, after_admin_flush);
       DBUG_EXECUTE_IF("wait_in_mysql_admin_table", wait_for_kill_signal(thd););
       if (thd->killed)
 	goto err;
diff -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy	2008-02-08 21:22:33 +01:00
+++ b/sql/sql_yacc.yy	2008-02-13 23:37:42 +01:00
@@ -593,6 +593,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  CHECKSUM_SYM
 %token  CHECK_SYM                     /* SQL-2003-R */
 %token  CIPHER_SYM
+%token  CLEAR_SYM
 %token  CLIENT_SYM
 %token  CLOSE_SYM                     /* SQL-2003-R */
 %token  COALESCE                      /* SQL-2003-N */
@@ -728,6 +729,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  HELP_SYM
 %token  HEX_NUM
 %token  HIGH_PRIORITY
+%token  HIT_LIMIT_SYM
 %token  HOST_SYM
 %token  HOSTS_SYM
 %token  HOUR_MICROSECOND_SYM
@@ -982,6 +984,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SHIFT_RIGHT                   /* OPERATOR */
 %token  SHOW
 %token  SHUTDOWN
+%token  SIGNAL_SYM
 %token  SIGNED_SYM
 %token  SIMPLE_SYM                    /* SQL-2003-N */
 %token  SLAVE
@@ -1025,6 +1028,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  SUSPEND_SYM
 %token  SWAPS_SYM
 %token  SWITCHES_SYM
+%token  SYNCHRONIZE_SYM
 %token  SYSDATE
 %token  TABLES
 %token  TABLESPACE
@@ -1033,10 +1037,12 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  TEMPORARY                     /* SQL-2003-N */
 %token  TEMPTABLE_SYM
 %token  TERMINATED
+%token  TEST_SYM
 %token  TEXT_STRING
 %token  TEXT_SYM
 %token  THAN_SYM
 %token  THEN_SYM                      /* SQL-2003-R */
+%token  TIMEOUT_SYM
 %token  TIMESTAMP                     /* SQL-2003-R */
 %token  TIMESTAMP_ADD
 %token  TIMESTAMP_DIFF
@@ -1090,6 +1096,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  VARYING                       /* SQL-2003-R */
 %token  VAR_SAMP_SYM
 %token  VIEW_SYM                      /* SQL-2003-N */
+%token  WAIT_FOR_SYM
 %token  WAIT_SYM
 %token  WARNINGS
 %token  WEEK_SYM
@@ -1316,6 +1323,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
         init_key_options key_options key_opts key_opt key_using_alg
         server_def server_options_list server_option
         definer_opt no_definer definer
+        test_stmt TEST_SYM test_statement SYNCHRONIZE_SYM
 END_OF_INPUT
 
 %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
@@ -1434,6 +1442,7 @@ statement:
         | show
         | slave
         | start
+        | test_stmt
         | truncate
         | uninstall
         | unlock
@@ -10588,6 +10597,7 @@ keyword:
         | SONAME_SYM            {}
         | START_SYM             {}
         | STOP_SYM              {}
+        | TEST_SYM              {}
         | TRUNCATE_SYM          {}
         | UNICODE_SYM           {}
         | UNINSTALL_SYM         {}
@@ -10626,6 +10636,7 @@ keyword_sp:
         | CHAIN_SYM                {}
         | CHANGED                  {}
         | CIPHER_SYM               {}
+        | CLEAR_SYM                {}
         | CLIENT_SYM               {}
         | COALESCE                 {}
         | CODE_SYM                 {}
@@ -10686,6 +10697,7 @@ keyword_sp:
         | GRANTS                   {}
         | GLOBAL_SYM               {}
         | HASH_SYM                 {}
+        | HIT_LIMIT_SYM            {}
         | HOSTS_SYM                {}
         | HOUR_SYM                 {}
         | IDENTIFIED_SYM           {}
@@ -10814,6 +10826,7 @@ keyword_sp:
         | SIMPLE_SYM               {}
         | SHARE_SYM                {}
         | SHUTDOWN                 {}
+        | SIGNAL_SYM               {}
         | SNAPSHOT_SYM             {}
         | SOUNDS_SYM               {}
         | SOURCE_SYM               {}
@@ -10833,6 +10846,7 @@ keyword_sp:
         | SUSPEND_SYM              {}
         | SWAPS_SYM                {}
         | SWITCHES_SYM             {}
+        | SYNCHRONIZE_SYM          {}
         | TABLES                   {}
         | TABLESPACE               {}
         | TEMPORARY                {}
@@ -10842,6 +10856,7 @@ keyword_sp:
         | TRANSACTION_SYM          {}
         | TRANSACTIONAL_SYM        {}
         | TRIGGERS_SYM             {}
+        | TIMEOUT_SYM              {}
         | TIMESTAMP                {}
         | TIMESTAMP_ADD            {}
         | TIMESTAMP_DIFF           {}
@@ -10862,6 +10877,7 @@ keyword_sp:
         | VIEW_SYM                 {}
         | VALUE_SYM                {}
         | WARNINGS                 {}
+        | WAIT_FOR_SYM             {}
         | WAIT_SYM                 {}
         | WEEK_SYM                 {}
         | WEIGHT_STRING_SYM        {}
@@ -12779,6 +12795,97 @@ uninstall:
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;
             lex->comment= $3;
+          }
+        ;
+
+test_stmt:
+          TEST_SYM test_statement
+        ;
+
+test_statement:
+          SYNCHRONIZE_SYM
+          {
+            Lex->sql_command= SQLCOM_TEST_SYNC;
+            Lex->test_sync_req.command= action;
+            Lex->test_sync_req.hit_limit= 0;
+            Lex->test_sync_req.execute= 0;
+            Lex->test_sync_req.timeout= opt_test_synchronize;
+            Lex->test_sync_req.signal.length= 0;
+            Lex->test_sync_req.wait_for.length= 0;
+            Lex->test_sync_req.sync_point.length= 0;
+          }
+          test_sync_stmt
+        ;
+
+test_sync_stmt:
+          ident_or_text test_sync_action
+          {
+            Lex->test_sync_req.sync_point= $1;
+          }
+        | RESET_SYM
+          {
+            Lex->test_sync_req.command= reset;
+          }
+        | SHOW STATUS_SYM
+          {
+            Lex->test_sync_req.command= show_status;
+          }
+        | SHOW ACTION
+          {
+            Lex->test_sync_req.command= show_action;
+          }
+        ;
+
+test_sync_action:
+          test_sync_signal_wait test_sync_execute
+        | test_sync_signal_wait test_sync_execute test_sync_limit
+        | test_sync_limit
+        | CLEAR_SYM /* hit_limit= 0 and execute= 0 */
+        | TEST_SYM
+          {
+            Lex->test_sync_req.command= test;
+          }
+        ;
+
+test_sync_signal_wait:
+          SIGNAL_SYM ident_or_text
+          {
+            Lex->test_sync_req.signal= $2;
+          }
+        | SIGNAL_SYM ident_or_text WAIT_FOR_SYM ident_or_text test_sync_timeout
+          {
+            Lex->test_sync_req.signal= $2;
+            Lex->test_sync_req.wait_for= $4;
+          }
+        | WAIT_FOR_SYM ident_or_text test_sync_timeout
+          {
+            Lex->test_sync_req.wait_for= $2;
+          }
+        ;        
+
+test_sync_timeout:
+          /* empty */
+        | TIMEOUT_SYM opt_equal real_ulong_num
+          {
+            Lex->test_sync_req.timeout= $3;
+          }
+        ;        
+
+test_sync_execute:
+          /* empty */
+          {
+            Lex->test_sync_req.execute= 1;
+          }
+        | EXECUTE_SYM opt_equal real_ulong_num
+          {
+            Lex->test_sync_req.execute= $3;
+          }
+        ;        
+
+test_sync_limit:
+          HIT_LIMIT_SYM opt_equal real_ulong_num
+          {
+            Lex->test_sync_req.hit_limit= $3;
           }
         ;
 
diff -Nrup a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
--- a/storage/myisammrg/ha_myisammrg.cc	2007-12-21 20:27:49 +01:00
+++ b/storage/myisammrg/ha_myisammrg.cc	2008-02-13 23:37:42 +01:00
@@ -456,6 +456,8 @@ int ha_myisammrg::attach_children(void)
   DBUG_PRINT("myrg", ("test_if_locked: %u", this->test_if_locked));
   DBUG_ASSERT(!this->file->children_attached);
 
+  TEST_SYNCHRONIZE(current_thd, before_myisammrg_attach);
+
   /*
     Initialize variables that are used, modified, and/or set by
     myisammrg_attach_children_callback().
@@ -925,6 +927,8 @@ THR_LOCK_DATA **ha_myisammrg::store_lock
 					 enum thr_lock_type lock_type)
 {
   MYRG_TABLE *open_table;
+
+  TEST_SYNCHRONIZE(thd, before_myisammrg_store_lock);
 
   /*
     This method can be called while another thread is attaching the
Thread
bk commit into 6.0 tree (istruewing:1.2553)Ingo Struewing13 Feb