summaryrefslogtreecommitdiff
path: root/mysql-test/include
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/include')
-rw-r--r--mysql-test/include/analyze-sync_with_master.test13
-rw-r--r--mysql-test/include/assert.inc175
-rw-r--r--mysql-test/include/begin_include_file.inc82
-rw-r--r--mysql-test/include/check-testcase.test6
-rw-r--r--mysql-test/include/check_slave_is_running.inc30
-rw-r--r--mysql-test/include/check_slave_no_error.inc22
-rw-r--r--mysql-test/include/check_slave_param.inc26
-rw-r--r--mysql-test/include/circular_rpl_for_4_hosts_init.inc130
-rw-r--r--mysql-test/include/circular_rpl_for_4_hosts_sync.inc23
-rw-r--r--mysql-test/include/cleanup_fake_relay_log.inc24
-rw-r--r--mysql-test/include/diff_master_slave.inc21
-rw-r--r--mysql-test/include/diff_tables.inc208
-rw-r--r--mysql-test/include/end_include_file.inc79
-rw-r--r--mysql-test/include/file_does_not_exist.inc17
-rw-r--r--mysql-test/include/force_restart.inc17
-rw-r--r--mysql-test/include/force_restart_if_skipped.inc17
-rw-r--r--mysql-test/include/have_innodb.inc8
-rw-r--r--mysql-test/include/io_thd_fault_injection.inc4
-rw-r--r--mysql-test/include/kill_query_and_diff_master_slave.inc8
-rw-r--r--mysql-test/include/master-slave-end.inc6
-rw-r--r--mysql-test/include/master-slave-reset.inc36
-rw-r--r--mysql-test/include/master-slave.inc69
-rw-r--r--mysql-test/include/mtr_check.sql10
-rw-r--r--mysql-test/include/mysqldump.inc3
-rw-r--r--mysql-test/include/ndb_master-slave.inc10
-rw-r--r--mysql-test/include/ndb_master-slave_2ch.inc165
-rw-r--r--mysql-test/include/ndb_not_readonly.inc6
-rw-r--r--mysql-test/include/report-features.test2
-rw-r--r--mysql-test/include/reset_master_and_slave.inc8
-rw-r--r--mysql-test/include/restart_mysqld.inc8
-rw-r--r--mysql-test/include/rpl_change_topology.inc248
-rw-r--r--mysql-test/include/rpl_connect.inc58
-rw-r--r--mysql-test/include/rpl_connection.inc47
-rw-r--r--mysql-test/include/rpl_diff.inc118
-rw-r--r--mysql-test/include/rpl_diff_tables.inc36
-rw-r--r--mysql-test/include/rpl_end.inc103
-rw-r--r--mysql-test/include/rpl_for_each_slave.inc39
-rw-r--r--mysql-test/include/rpl_generate_sync_chain.inc122
-rw-r--r--mysql-test/include/rpl_init.inc242
-rw-r--r--mysql-test/include/rpl_reconnect.inc132
-rw-r--r--mysql-test/include/rpl_reset.inc81
-rw-r--r--mysql-test/include/rpl_restart_server.inc39
-rw-r--r--mysql-test/include/rpl_start_server.inc54
-rw-r--r--mysql-test/include/rpl_start_slaves.inc32
-rw-r--r--mysql-test/include/rpl_stop_server.inc63
-rw-r--r--mysql-test/include/rpl_stop_slaves.inc33
-rw-r--r--mysql-test/include/rpl_sync.inc153
-rw-r--r--mysql-test/include/save_master_pos.inc33
-rw-r--r--mysql-test/include/setup_fake_relay_log.inc50
-rw-r--r--mysql-test/include/show_rpl_debug_info.inc131
-rw-r--r--mysql-test/include/show_slave_status.inc82
-rw-r--r--mysql-test/include/start_slave.inc32
-rw-r--r--mysql-test/include/stop_slave.inc89
-rw-r--r--mysql-test/include/stop_slave_io.inc43
-rw-r--r--mysql-test/include/stop_slave_sql.inc41
-rw-r--r--mysql-test/include/sync_io_with_master.inc46
-rw-r--r--mysql-test/include/sync_slave_io_with_master.inc50
-rw-r--r--mysql-test/include/sync_slave_sql_with_io.inc50
-rw-r--r--mysql-test/include/wait_for_query_to_fail.inc25
-rw-r--r--mysql-test/include/wait_for_slave_io_error.inc88
-rw-r--r--mysql-test/include/wait_for_slave_io_to_start.inc27
-rw-r--r--mysql-test/include/wait_for_slave_io_to_stop.inc50
-rw-r--r--mysql-test/include/wait_for_slave_param.inc117
-rw-r--r--mysql-test/include/wait_for_slave_sql_error.inc66
-rw-r--r--mysql-test/include/wait_for_slave_sql_error_and_skip.inc64
-rw-r--r--mysql-test/include/wait_for_slave_sql_to_start.inc30
-rw-r--r--mysql-test/include/wait_for_slave_sql_to_stop.inc50
-rw-r--r--mysql-test/include/wait_for_slave_to_start.inc30
-rw-r--r--mysql-test/include/wait_for_slave_to_stop.inc46
-rw-r--r--mysql-test/include/write_var_to_file.inc57
70 files changed, 3288 insertions, 842 deletions
diff --git a/mysql-test/include/analyze-sync_with_master.test b/mysql-test/include/analyze-sync_with_master.test
index 684c0dbbab7..27b5a56c6b1 100644
--- a/mysql-test/include/analyze-sync_with_master.test
+++ b/mysql-test/include/analyze-sync_with_master.test
@@ -1,6 +1,9 @@
-SHOW PROCESSLIST;
+# ==== Purpose ====
+#
+# This is an auxiliary file that mysqltest executes when
+# sync_slave_with_master or sync_with_master fails. The purpose is to
+# print debug information.
-let $binlog_name= query_get_value("SHOW MASTER STATUS", File, 1);
-eval SHOW BINLOG EVENTS IN '$binlog_name';
-
-exit; \ No newline at end of file
+--let $rpl_server_count= 0
+--let $rpl_only_current_connection= 1
+--source include/show_rpl_debug_info.inc
diff --git a/mysql-test/include/assert.inc b/mysql-test/include/assert.inc
new file mode 100644
index 00000000000..34cc71e7c25
--- /dev/null
+++ b/mysql-test/include/assert.inc
@@ -0,0 +1,175 @@
+# ==== Purpose ====
+#
+# Check if a condition holds, fail with debug info if not.
+#
+# The condition is parsed before executed. The following constructs
+# are supported:
+#
+# [SQL_STATEMENT, COLUMN, ROW]
+# The square bracket is replaced by the result from SQL_STATEMENT,
+# in the given COLUMN and ROW.
+#
+# Optionally, SQL_STATEMENT may have the form:
+# connection:SQL_STATEMENT
+# In this case, SQL_STATEMENT is executed on the named connection.
+# All other queries executed by this script will be executed on
+# the connection that was in use when this script was started.
+# The current connection will also be restored at the end of this
+# script.
+#
+# Nested sub-statements on this form are not allowed.
+#
+# <1>
+# This is a shorthand for the result of the first executed square
+# bracket. <2> is a shorthand for the second executed square
+# bracket, and so on.
+#
+# ==== Usage ====
+#
+# --let $assert_text= Relay_Log_Pos must be between min_pos and max_pos
+# --let $assert_cond= [SHOW SLAVE STATUS, Relay_Log_Pos, 1] >= $min_pos AND <1> <= $max_pos
+# [--let $assert_quiet= 1]
+# [--let $rpl_debug= 1]
+# --source include/assert.inc
+#
+# Parameters:
+#
+# $assert_text
+# Text that describes what is being checked. This text is written to
+# the query log so it should not contain non-deterministic elements.
+#
+# $assert_cond
+# Condition to check. See above for details about the format. The
+# condition will be executed as `SELECT $assert_cond`.
+#
+# Both $assert_cond and the result from any substatement on the
+# form [SQL_STATEMENT, COLUMN, ROW] will be used in SQL statements,
+# inside single quotes (as in '$assert_text'). So any single quotes
+# in these texts must be escaped or replaced by double quotes.
+#
+# $rpl_debug
+# Print extra debug info.
+
+
+--let $include_filename= assert.inc [$assert_text]
+--source include/begin_include_file.inc
+
+if ($rpl_debug)
+{
+ --echo # debug: assert_text='$assert_text' assert_cond='$assert_cond'
+}
+
+# Sanity-check input
+if (!$assert_text)
+{
+ --die ERROR IN TEST: the mysqltest variable rpl_test must be set
+}
+
+--let $_assert_old_connection= $CURRENT_CONNECTION
+
+# Evaluate square brackets in cond.
+--let $_assert_substmt_number= 1
+--let $_assert_cond_interp= '$assert_cond'
+--let $_assert_lbracket= `SELECT LOCATE('[', $_assert_cond_interp)`
+while ($_assert_lbracket)
+{
+ # Get position of right bracket
+ --let $_assert_rbracket= `SELECT LOCATE(']', $_assert_cond_interp)`
+ if (!$_assert_rbracket)
+ {
+ --echo BUG IN TEST: Mismatching square brackets in assert_cond.
+ --echo Original assert_cond='$assert_cond'
+ --echo Interpolated assert_cond=$_assert_cond_interp
+ --die BUG IN TEST: Mismatching square brackets in $assert_cond
+ }
+
+ # Get sub-statement from statement. Preserve escapes for single quotes.
+ --let $_assert_full_substmt= `SELECT QUOTE(SUBSTRING($_assert_cond_interp, $_assert_lbracket + 1, $_assert_rbracket - $_assert_lbracket - 1))`
+
+ # Get connection from sub-statement
+ --let $_assert_colon= `SELECT IF($_assert_full_substmt REGEXP '^[a-zA-Z_][a-zA-Z_0-9]*:', LOCATE(':', $_assert_full_substmt), 0)`
+ --let $_assert_connection=
+ --let $_assert_substmt= $_assert_full_substmt
+ if ($_assert_colon)
+ {
+ --let $_assert_connection= `SELECT SUBSTRING($_assert_substmt, 1, $_assert_colon - 1)`
+ # Preserve escapes for single quotes.
+ --let $_assert_substmt= `SELECT QUOTE(SUBSTRING($_assert_substmt, $_assert_colon + 1))`
+ }
+
+ # Interpolate escapes before using condition outside string context.
+ --let $_assert_substmt_interp= `SELECT $_assert_substmt`
+
+ # Execute and get result from sub-statement
+ if ($_assert_connection)
+ {
+ if ($rpl_debug)
+ {
+ --echo # debug: connection='$_assert_connection' sub-statement=$_assert_substmt
+ }
+ --let $rpl_connection_name= $_assert_connection
+ --source include/rpl_connection.inc
+ --let $_assert_substmt_result= query_get_value($_assert_substmt_interp)
+ --let $rpl_connection_name= $_assert_old_connection
+ --source include/rpl_connection.inc
+ }
+ if (!$_assert_connection)
+ {
+ if ($rpl_debug)
+ {
+ --echo # debug: old connection, sub-statement=$_assert_substmt
+ }
+ --let $_assert_substmt_result= query_get_value($_assert_substmt_interp)
+ }
+ if ($rpl_debug)
+ {
+ --echo # debug: result of sub-statement='$_assert_substmt_result'
+ }
+
+ # Replace sub-statement by its result
+ --let $_assert_cond_interp= `SELECT QUOTE(REPLACE($_assert_cond_interp, CONCAT('[', $_assert_full_substmt, ']'), '$_assert_substmt_result'))`
+ # Replace result references by result
+ --let $_assert_cond_interp= `SELECT QUOTE(REPLACE($_assert_cond_interp, '<$_assert_substmt_number>', '$_assert_substmt_result'))`
+
+ --let $_assert_lbracket= `SELECT LOCATE('[', $_assert_cond_interp)`
+
+ --inc $_assert_substmt_number
+}
+
+# Interpolate escapes before using condition outside string context.
+--let $_assert_cond_interp= `SELECT $_assert_cond_interp`
+
+if ($rpl_debug)
+{
+ --echo # debug: interpolated_cond='$_assert_cond_interp'
+}
+
+# Execute.
+--let $_assert_result= `SELECT $_assert_cond_interp`
+
+if ($rpl_debug)
+{
+ --echo # debug: result='$_assert_result'
+}
+
+# Check.
+if (!$_assert_result)
+{
+ --echo ######## Test assertion failed: $assert_text ########
+ --echo Dumping debug info:
+ if ($rpl_inited)
+ {
+ --source include/show_rpl_debug_info.inc
+ }
+ --echo Assertion text: '$assert_text'
+ --echo Assertion condition: '$assert_cond'
+ --echo Assertion condition, interpolated: '$_assert_cond_interp'
+ --echo Assertion result: '$_assert_result'
+ --die Test assertion failed in assertion.inc
+}
+
+--let $include_filename= assert.inc [$assert_text]
+--source include/end_include_file.inc
+
+--let $assert_text=
+--let $assert_cond=
diff --git a/mysql-test/include/begin_include_file.inc b/mysql-test/include/begin_include_file.inc
new file mode 100644
index 00000000000..98d3a1743ee
--- /dev/null
+++ b/mysql-test/include/begin_include_file.inc
@@ -0,0 +1,82 @@
+# ==== Purpose ====
+#
+# This is an auxiliary file that facilitates writing include/*.inc
+# files. It has three purposes:
+#
+# 1. Store mtr's state at the beginning of the .inc file and restore
+# the state at the end. The following status is restored:
+#
+# disable_warnings
+# disable_query_log
+# disable_result_log
+# disable_abort_on_errors
+# Current connection
+#
+# 2. This file also prints the name of the .inc file that sources
+# it. Only the name of the top-level .inc file is printed: if
+# file_1.inc sources file_2.inc, then this file only prints
+# file_1.inc.
+#
+# 3. If the mysqltest variable $rpl_debug is set, then
+# this file will print:
+#
+# ==== BEGIN include/<filename> ====
+#
+# and end_include_file.inc will print
+#
+# ==== END include/<filename> ====
+#
+# These printouts are indented to make it easier to read the
+# result log.
+#
+#
+# ==== Usage ====
+#
+# # At the beginning of include/my_file.inc:
+# --let $include_filename= my_file.inc
+# [--let $rpl_debug= 1]
+# --source include/begin_include_file.inc
+#
+# # At the end of include/my_file.inc:
+# --let $include_filename= my_file.inc
+# --source include/end_include_file.inc
+#
+# Parameters:
+# $include_filename
+# The basename of the file: a file named /path/to/my_file.inc
+# should set $include_filename=my_file.inc. This parameter
+# must be provided both for begin_include_file.inc and
+# end_include_file.inc.
+#
+# $rpl_debug
+# If set, this script will print the following text:
+# ==== BEGIN include/$include_filename.inc ====
+
+
+# Print 'include/$include_filename', but only when invoked from
+# the top-level. We don't want to print
+# 'include/$include_filename' from all files included
+# recursively.
+if (!$_include_file_depth)
+{
+ --echo include/$include_filename
+}
+--inc $_include_file_depth
+if ($rpl_debug)
+{
+ --echo $_include_file_indent==== BEGIN include/$include_filename ====
+}
+
+--let $_include_file_enabled_warnings= $ENABLED_WARNINGS$_include_file_enabled_warnings
+--let $_include_file_enabled_query_log= $ENABLED_QUERY_LOG$_include_file_enabled_query_log
+--let $_include_file_enabled_result_log= $ENABLED_RESULT_LOG$_include_file_enabled_result_log
+--let $_include_file_enabled_abort_on_error= $ENABLED_ABORT_ON_ERROR$_include_file_enabled_abort_on_error
+--let $_include_file_connection= $CURRENT_CONNECTION,$_include_file_connection
+
+if ($rpl_debug)
+{
+ --echo $_include_file_indent con='$CURRENT_CONNECTION' warn='$ENABLED_WARNINGS' qlog='$ENABLED_QUERY_LOG' rlog='$ENABLED_RESULT_LOG' aborterr='$ENABLED_ABORT_ON_ERROR'
+}
+
+--let $include_filename=
+--let $_include_file_indent= .$_include_file_indent
diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test
index 6dcb01c13cf..88b56c95cec 100644
--- a/mysql-test/include/check-testcase.test
+++ b/mysql-test/include/check-testcase.test
@@ -8,8 +8,10 @@
# any unwanted side affects.
#
--disable_query_log
+--replace_column 5 # 6 # 7 # 8 # 9 # 10 # 22 # 23 # 24 # 25 # 26 #
+query_vertical
+SHOW SLAVE STATUS;
+
call mtr.check_testcase();
--enable_query_log
-
-
diff --git a/mysql-test/include/check_slave_is_running.inc b/mysql-test/include/check_slave_is_running.inc
index 5fbbe0d684c..88664da7fa7 100644
--- a/mysql-test/include/check_slave_is_running.inc
+++ b/mysql-test/include/check_slave_is_running.inc
@@ -2,17 +2,29 @@
#
# Assert that the slave threads are running and don't have any errors.
#
+#
# ==== Usage ====
#
-# --source include/check_slave_running.inc
+# [--let $rpl_debug= 1]
+# --source include/check_slave_is_running.inc
+#
+# Parameters:
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= check_slave_is_running.inc
+--source include/begin_include_file.inc
+
+
+--let $slave_param= Slave_IO_Running
+--let $slave_param_value= Yes
+--source include/check_slave_param.inc
---echo Checking that both slave threads are running.
+--let $slave_param= Slave_SQL_Running
+--let $slave_param_value= Yes
+--source include/check_slave_param.inc
---let $slave_sql_running = query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1)
---let $slave_io_running = query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1)
-if (`SELECT '$slave_sql_running' != 'Yes' OR '$slave_io_running' != 'Yes'`) {
- --echo Slave not running: Slave_SQL_Running = $slave_sql_running Slave_IO_Running = $slave_io_running
- --source include/show_rpl_debug_info.inc
- --die Expected slave to be running, but it was not running.
-}
+--let $include_filename= check_slave_is_running.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/check_slave_no_error.inc b/mysql-test/include/check_slave_no_error.inc
index 371db5ed6a0..9922b426ed6 100644
--- a/mysql-test/include/check_slave_no_error.inc
+++ b/mysql-test/include/check_slave_no_error.inc
@@ -1,12 +1,22 @@
# ==== Purpose ====
#
-# Assert that Slave_SQL_Error and Slave_IO_Error are empty.
+# Assert that Slave_SQL_Errno = Slave_IO_Errno = 0 in the output from
+# SHOW SLAVE STATUS.
+#
#
# ==== Usage ====
#
-# --let $slave_param= Exec_Master_Log_Pos
-# --let $slave_param_value= 4711
-# --source include/check_slave_running.inc
+# [--let $rpl_debug= 1]
+# --source include/check_slave_no_error.inc
+#
+# Parameters:
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= check_slave_no_error.inc
+--source include/begin_include_file.inc
+
--let $slave_param= Last_SQL_Errno
--let $slave_param_value= 0
@@ -15,3 +25,7 @@
--let $slave_param= Last_IO_Errno
--let $slave_param_value= 0
--source include/check_slave_param.inc
+
+
+--let $include_filename= check_slave_no_error.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/check_slave_param.inc b/mysql-test/include/check_slave_param.inc
index d82c26851ea..1e0e81308f2 100644
--- a/mysql-test/include/check_slave_param.inc
+++ b/mysql-test/include/check_slave_param.inc
@@ -4,13 +4,33 @@
#
# ==== Usage ====
#
-# --let $slave_param= Exec_Master_Log_Pos
-# --let $slave_param_value= 4711
+# --let $slave_param= COLUMN_NAME
+# --let $slave_param_value= VALUE
+# [--let $rpl_debug= 1]
# --source include/check_slave_param.inc
+#
+# Parameters:
+# $slave_param, $slave_param_value
+# Column name in output of SHOW SLAVE STATUS that should be checked,
+# and the expected value. Example:
+# --let $slave_param= Exec_Master_Log_Pos
+# --let $slave_param_value= 4711
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= check_slave_param.inc [$slave_param]
+--source include/begin_include_file.inc
+
--let $_param_value= query_get_value(SHOW SLAVE STATUS, $slave_param, 1)
if (`SELECT '$_param_value' != '$slave_param_value'`) {
- --echo Wrong value for $slave_param. Expected '$slave_param_value', got '$_param_value'
--source include/show_rpl_debug_info.inc
+ --echo Wrong value for $slave_param. Expected '$slave_param_value', got '$_param_value'
--die Wrong value for slave parameter
}
+
+
+--let $include_filename= check_slave_param.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/circular_rpl_for_4_hosts_init.inc b/mysql-test/include/circular_rpl_for_4_hosts_init.inc
deleted file mode 100644
index ac6654777db..00000000000
--- a/mysql-test/include/circular_rpl_for_4_hosts_init.inc
+++ /dev/null
@@ -1,130 +0,0 @@
-#############################################################
-#
-# Author: Serge Kozlov <skozlov@mysql.com>
-# Date: 03/11/2008
-# Purpose: Set up circular replication based on schema
-# A->B->C->D->A
-#
-# Notes:
-# 1. --slave-num=3 must be added to *-master.opt file
-# 2. Even the test uses new names for servers but file names
-# of log files are still old:
-# master_a -> master.[log|err]
-# master_b -> slave.[log|err]
-# master_c -> slave1.[log|err]
-# master_d -> slave2.[log|err]
-#
-#############################################################
---source include/master-slave.inc
-
-#
-# Set up circular ring by schema A->B->C->D->A
-#
-
---connection slave
-STOP SLAVE;
-RESET SLAVE;
-
-# master a
---connection master
---disconnect master
-connect (master_a,127.0.0.1,root,,test,$MASTER_MYPORT,);
-RESET MASTER;
---disable_warnings
-STOP SLAVE;
---enable_warnings
-RESET SLAVE;
-SET auto_increment_increment = 4;
-SET auto_increment_offset = 1;
-let $_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
-
-# master b
---connection slave
---disconnect slave
-connect (master_b,127.0.0.1,root,,test,$SLAVE_MYPORT,);
-RESET MASTER;
-RESET SLAVE;
---replace_result $MASTER_MYPORT MASTER_A_PORT $_binlog_file MASTER_A_LOG_FILE
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root',MASTER_LOG_FILE='$_binlog_file'
-SET auto_increment_increment = 4;
-SET auto_increment_offset = 2;
-let $_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
-
-# master c
---connection slave1
---disconnect slave1
-connect (master_c,127.0.0.1,root,,test,$SLAVE_MYPORT1,);
-RESET MASTER;
---disable_warnings
-STOP SLAVE;
---enable_warnings
-RESET SLAVE;
---replace_result $SLAVE_MYPORT MASTER_B_PORT $_binlog_file MASTER_B_LOG_FILE
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SLAVE_MYPORT,master_user='root',MASTER_LOG_FILE='$_binlog_file'
-SET auto_increment_increment = 4;
-SET auto_increment_offset = 3;
-let $_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
-
-# master d
-connect (master_d,127.0.0.1,root,,test,$SLAVE_MYPORT2,);
-RESET MASTER;
---disable_warnings
-STOP SLAVE;
---enable_warnings
-RESET SLAVE;
---replace_result $SLAVE_MYPORT1 MASTER_C_PORT $_binlog_file MASTER_C_LOG_FILE
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SLAVE_MYPORT1,master_user='root',MASTER_LOG_FILE='$_binlog_file'
-SET auto_increment_increment = 4;
-SET auto_increment_offset = 4;
-let $_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
-
-# master a
---connection master_a
---replace_result $SLAVE_MYPORT2 MASTER_D_PORT $_binlog_file MASTER_D_LOG_FILE
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SLAVE_MYPORT2,master_user='root',MASTER_LOG_FILE='$_binlog_file'
-
-
-
-# Check server_ids: they should be different
---connection master_a
-let $_id_a= query_get_value(SHOW VARIABLES LIKE 'server_id', Value, 1);
-SHOW VARIABLES LIKE 'auto_increment_%';
---connection master_b
-let $_id_b= query_get_value(SHOW VARIABLES LIKE 'server_id', Value, 1);
-SHOW VARIABLES LIKE 'auto_increment_%';
---connection master_c
-let $_id_c= query_get_value(SHOW VARIABLES LIKE 'server_id', Value, 1);
-SHOW VARIABLES LIKE 'auto_increment_%';
---connection master_d
-let $_id_d= query_get_value(SHOW VARIABLES LIKE 'server_id', Value, 1);
-SHOW VARIABLES LIKE 'auto_increment_%';
---connection master_a
-let $_compared_ids= (($_id_a <> $_id_b) AND ($_id_a <> $_id_c) AND ($_id_a <> $_id_d) AND ($_id_b <> $_id_c) AND ($_id_b <> $_id_d) AND ($_id_c <> $_id_d)) AS a;
-let $_compared_ids_result= query_get_value(SELECT $_compared_ids, a, 1);
---echo $_compared_ids_result
-
-# Start ring
---connection master_a
-connect(slave,127.0.0.1,root,,test,$MASTER_MYPORT);
-START SLAVE;
---source include/wait_for_slave_to_start.inc
---disconnect slave
-
---connection master_b
-connect(slave,127.0.0.1,root,,test,$SLAVE_MYPORT1);
-START SLAVE;
---source include/wait_for_slave_to_start.inc
---disconnect slave
-
---connection master_c
-connect(slave,127.0.0.1,root,,test,$SLAVE_MYPORT);
-START SLAVE;
---source include/wait_for_slave_to_start.inc
---disconnect slave
-
---connection master_d
-connect(slave,127.0.0.1,root,,test,$SLAVE_MYPORT2);
-START SLAVE;
---source include/wait_for_slave_to_start.inc
---disconnect slave
-
diff --git a/mysql-test/include/circular_rpl_for_4_hosts_sync.inc b/mysql-test/include/circular_rpl_for_4_hosts_sync.inc
deleted file mode 100644
index 68aede76913..00000000000
--- a/mysql-test/include/circular_rpl_for_4_hosts_sync.inc
+++ /dev/null
@@ -1,23 +0,0 @@
-#############################################################
-#
-# Author: Serge Kozlov <skozlov@mysql.com>
-# Date: 03/11/2008
-# Purpose: Sync all hosts for circular replication based on
-# schema A->B->C->D->A
-#
-# Notes: see include/circular_rpl_for_4_hosts_init.inc
-#
-#############################################################
-
-# Make the full loop of sync
---connection master_a
---disable_query_log
---sync_slave_with_master master_b
---sync_slave_with_master master_c
---sync_slave_with_master master_d
---sync_slave_with_master master_a
---sync_slave_with_master master_b
---sync_slave_with_master master_c
---save_master_pos
---connection master_a
---enable_query_log
diff --git a/mysql-test/include/cleanup_fake_relay_log.inc b/mysql-test/include/cleanup_fake_relay_log.inc
index 43aa46cb657..921484ec695 100644
--- a/mysql-test/include/cleanup_fake_relay_log.inc
+++ b/mysql-test/include/cleanup_fake_relay_log.inc
@@ -1,16 +1,28 @@
# ==== Purpose ====
#
-# Clean up files create by setup_fake_relay_log.inc.
+# Clean up files created by setup_fake_relay_log.inc.
#
# ==== Usage ====
#
# See setup_fake_relay_log.inc
---echo Cleaning up after setup_fake_relay_log.inc
+--let $include_filename= cleanup_fake_relay_log.inc
+--source include/begin_include_file.inc
+
-# Remove files.
-remove_file $_fake_relay_log;
-remove_file $_fake_relay_index;
--disable_query_log
+RESET SLAVE;
+
+# Assert that the fake relay log files are gone (RESET SLAVE should
+# have removed them).
+--let $file_does_not_exist= $_fake_relay_log
+--source include/file_does_not_exist.inc
+
+# Revert variables.
eval SET @@global.relay_log_purge= $_fake_relay_log_purge;
---enable_query_log
+
+eval CHANGE MASTER TO MASTER_HOST = '$_fake_old_master_host';
+
+
+--let $include_filename= cleanup_fake_relay_log.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/diff_master_slave.inc b/mysql-test/include/diff_master_slave.inc
deleted file mode 100644
index b6d79190671..00000000000
--- a/mysql-test/include/diff_master_slave.inc
+++ /dev/null
@@ -1,21 +0,0 @@
-# ==== Purpose ====
-#
-# Diff the output of a statement on master and slave
-#
-# ==== Usage =====
-#
-# let $diff_statement= SELECT * FROM t1 WHERE a < 100;
-# source include/diff_master_slave.inc;
-
---echo source include/diff_master_slave.inc;
-disable_query_log;
-disable_result_log;
-
-exec $MYSQL test -e "$diff_statement" > $MYSQLTEST_VARDIR/tmp/diff_master.out;
-sync_slave_with_master;
-exec $MYSQL_SLAVE test -e "$diff_statement" > $MYSQLTEST_VARDIR/tmp/diff_slave.out;
-
-diff_files $MYSQLTEST_VARDIR/tmp/diff_master.out $MYSQLTEST_VARDIR/tmp/diff_slave.out;
-
-enable_result_log;
-enable_query_log;
diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc
index 81362e8643b..94921b02f13 100644
--- a/mysql-test/include/diff_tables.inc
+++ b/mysql-test/include/diff_tables.inc
@@ -1,35 +1,41 @@
# ==== Purpose ====
#
-# Check if the two given tables (possibly residing on different
-# master/slave servers) are equal.
+# Check if all tables in the given list are equal. The tables may have
+# different names, exist in different connections, and/or reside in
+# different databases.
+#
#
# ==== Usage ====
#
-# The tables to check are given by the test language variables
-# $diff_table_1 and $diff_table_2. They must be of the
-# following form:
+# --let $diff_tables= [con1:][db1.]t1, [con2:][db2.]t2, ... , [conN:][dbN.]tN
+# [--let $rpl_debug= 1]
+# --source include/diff_tables.inc
+#
+# Parameters:
+# $diff_tables
+# Comma-separated list of tables to compare. Each table has the form
+#
+# [CONNECTION:][DATABASE.]table
#
-# [master:|slave:]database.table
+# If CONNECTION is given, then that connection is used. If
+# CONNECTION is not given, then the connection of the previous
+# table is used (or the current connection, if this is the first
+# table). If DATABASE is given, the table is read in that
+# database. If DATABASE is not given, the table is read in the
+# connection's current database.
+#
+# $rpl_debug
+# See include/rpl_init.inc
#
-# I.e., both database and table must be speicified. Optionally, you
-# can prefix the name with 'master:' (to read the table on master) or
-# with 'slave:' (to read the table on slave). If no prefix is given,
-# reads the table from the current connection. If one of these
-# variables has a prefix, both should have a prefix.
#
# ==== Side effects ====
#
-# - Prints "Comparing tables $diff_table_1 and $diff_tables_2".
+# - Prints "include/diff_tables.inc [$diff_tables]".
#
# - If the tables are different, prints the difference in a
# system-specific format (unified diff if supported) and generates
# an error.
#
-# - If $diff_table_1 or $diff_table_2 begins with 'master:' or
-# 'slave:', it will stay connected to one of those hosts after
-# execution. The host is only guaranteed to remain unchanged if
-# none of $diff_table_1 or $diff_table_2 begins with 'master:' or
-# 'slave:'.
#
# ==== Bugs ====
#
@@ -50,69 +56,135 @@
# by character case.
+--let $include_filename= diff_tables.inc [$diff_tables]
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+# Check sanity
+if (`SELECT LOCATE(',', '$diff_tables') = 0`)
+{
+ --die ERROR IN TEST: $diff_tables must contain at least two tables (separated by comma)
+}
+
+
# ==== Save both tables to file ====
---echo Comparing tables $diff_table_1 and $diff_table_2
-disable_query_log;
-
---error 0,1
---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1
---error 0,1
---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2
-
-let $_diff_table=$diff_table_2;
-let $_diff_i=2;
-while ($_diff_i) {
-
- # Parse out any leading "master:" or "slave:" from the table specification
-# and connect the appropriate server.
- let $_pos= `SELECT LOCATE(':', '$_diff_table')`;
- let $_diff_conn=`SELECT SUBSTR('$_diff_table', 1, $_pos-1)`;
- if (`SELECT 'XX$_diff_conn' <> 'XX'`) {
- let $_diff_table=`SELECT SUBSTR('$_diff_table', $_pos+1)`;
- connection $_diff_conn;
+# Trim off whitespace
+--let $_dt_tables= `SELECT REPLACE('$diff_tables', ' ', '')`
+
+# Iterate over all tables
+--let $_dt_outfile=
+--let $_dt_prev_outfile=
+while (`SELECT '$_dt_tables' != ''`)
+{
+ --let $_dt_table= `SELECT SUBSTRING_INDEX('$_dt_tables', ',', 1)`
+ --let $_dt_tables= `SELECT SUBSTRING('$_dt_tables', LENGTH('$_dt_table') + 2)`
+
+ # Parse connection, if any
+ --let $_dt_colon_index= `SELECT LOCATE(':', '$_dt_table')`
+ if ($_dt_colon_index)
+ {
+ --let $_dt_connection= `SELECT SUBSTRING('$_dt_table', 1, $_dt_colon_index - 1)`
+ --let $_dt_table= `SELECT SUBSTRING('$_dt_table', $_dt_colon_index + 1)`
+ --let $rpl_connection_name= $_dt_connection
+ --source include/rpl_connection.inc
+ }
+
+ # Parse database name, if any
+ --let $_dt_database_index= `SELECT LOCATE('.', '$_dt_table')`
+ if ($_dt_database_index)
+ {
+ --let $_dt_database= `SELECT SUBSTRING('$_dt_table', 1, $_dt_database_index - 1)`
+ --let $_dt_table= `SELECT SUBSTRING('$_dt_table', $_dt_database_index + 1)`
+ }
+ if (!$_dt_database_index)
+ {
+ --let $_dt_database= `SELECT DATABASE()`
}
- # Sanity-check the input.
- let $_diff_error= `SELECT '$_diff_table' NOT LIKE '_%._%'`;
- if ($_diff_error) {
- --echo !!!ERROR IN TEST: \$diff_table_$_diff_i='$_diff_table' is not in the form database.table
- exit;
+ if ($rpl_debug)
+ {
+ --echo con='$_dt_connection' db='$_dt_database' table='$_dt_table'
+ --echo rest of tables='$_dt_tables'
}
- # We need the output files to be sorted (so that diff_files does not
- # think the files are different just because they are differently
- # ordered). To this end, we first generate a query that sorts the
- # table by all columns. Since ORDER BY accept column indices, we
- # just generate a comma-separated list of all numbers from 1 to the
- # number of columns in the table.
- let $_diff_column_index=`SELECT MAX(ordinal_position)
- FROM information_schema.columns
- WHERE CONCAT(table_schema, '.', table_name) =
- '$_diff_table'`;
- let $_diff_column_list=$_diff_column_index;
- dec $_diff_column_index;
- while ($_diff_column_index) {
- let $_diff_column_list=$_diff_column_index, $_diff_column_list;
- dec $_diff_column_index;
+ # We need to sort the output files so that diff_files does not think
+ # the tables are different just because the rows are differently
+ # ordered. To this end, we first generate a string containing a
+ # comma-separated list of all column names. This is used in the
+ # ORDER BY clause of the following SELECT statement. We get the
+ # column names from INFORMATION_SCHEMA.COLUMNS, and we concatenate
+ # them with GROUP_CONCAT. Since GROUP_CONCAT is limited by the
+ # @@SESSION.group_concat_max_len, which is only 1024 by default, we
+ # first compute the total size of all columns and then increase this
+ # limit if needed. We restore the limit afterwards so as not to
+ # interfere with the test case.
+
+ # Compute length of ORDER BY clause.
+ let $_dt_order_by_length=
+ `SELECT SUM(LENGTH(column_name) + 3) FROM information_schema.columns
+ WHERE table_schema = '$_dt_database' AND table_name = '$_dt_table'`;
+ if (!$_dt_order_by_length)
+ {
+ --echo ERROR IN TEST: table $_dt_database.$_dt_table not found in INFORMATION_SCHEMA.COLUMNS. Did you misspell it?
+ --die ERROR IN TEST: table not found in INFORMATION_SCHEMA. Did you misspell it?
+ }
+ --let $_dt_old_group_concat_max_len=
+ # Increase group_concat_max_len if needed.
+ if (`SELECT $_dt_order_by_length > @@SESSION.group_concat_max_len`)
+ {
+ --let $_dt_old_group_concat_max_len= `SELECT @@SESSION.group_concat_max_len`
+ --eval SET SESSION group_concat_max_len = $_dt_order_by_length;
+ if ($rpl_debug)
+ {
+ --echo # increasing group_concat_max_len from $_dt_old_group_concat_max_len to $_dt_order_by_length
+ }
+ }
+ # Generate ORDER BY clause.
+ # It would be better to do GROUP_CONCAT(CONCAT('`', column_name, '`')) but
+ # BUG#58087 prevents us from returning strings that begin with backticks.
+ let $_dt_column_list=
+ `SELECT GROUP_CONCAT(column_name ORDER BY ORDINAL_POSITION SEPARATOR '`,`')
+ FROM information_schema.columns
+ WHERE table_schema = '$_dt_database' AND table_name = '$_dt_table'`;
+ # Restore group_concat_max_len.
+ if ($_dt_old_group_concat_max_len)
+ {
+ --let $_dt_dummy= `SET SESSION group_concat_max_len = $_dt_old_group_concat_max_len
+ }
+ if ($rpl_debug)
+ {
+ --echo using ORDER BY clause '`$_dt_column_list`'
}
# Now that we have the comma-separated list of columns, we can write
# the table to a file.
- eval SELECT * FROM $_diff_table ORDER BY $_diff_column_list
- INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/diff_table_$_diff_i';
+ --let $_dt_outfile= `SELECT @@datadir`
+ --let $_dt_outfile= $_dt_outfile/diff_table-$_dt_connection-$_dt_database-$_dt_table
+ eval SELECT * FROM $_dt_database.$_dt_table ORDER BY `$_dt_column_list` INTO OUTFILE '$_dt_outfile';
- # Do the same for $diff_table_1.
- dec $_diff_i;
- let $_diff_table=$diff_table_1;
+ # Compare files.
+ if ($_dt_prev_outfile)
+ {
+ if ($rpl_debug)
+ {
+ --echo # diffing $_dt_prev_outfile vs $_dt_outfile
+ }
+ --diff_files $_dt_prev_outfile $_dt_outfile
+ # Remove previous outfile. Keep current file for comparison with next table.
+ --remove_file $_dt_prev_outfile
+ }
+ --let $_dt_prev_outfile= $_dt_outfile
}
+--remove_file $_dt_prev_outfile
-# ==== Compare the generated files ====
-
-diff_files $MYSQLTEST_VARDIR/tmp/diff_table_1 $MYSQLTEST_VARDIR/tmp/diff_table_2;
-
---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1
---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2
-enable_query_log;
+--let $include_filename= diff_tables.inc [$diff_tables]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/end_include_file.inc b/mysql-test/include/end_include_file.inc
new file mode 100644
index 00000000000..1e546c1215b
--- /dev/null
+++ b/mysql-test/include/end_include_file.inc
@@ -0,0 +1,79 @@
+# ==== Purpose ====
+#
+# See include/begin_include_file.inc
+#
+#
+# ==== Usage ====
+#
+# # At the end of include/my_file.inc:
+# --let $include_filename= my_file.inc
+# [--let $skip_restore_connection= 1]
+# [--let $rpl_debug= 1]
+# --source include/begin_include_file.inc
+#
+# Parameters:
+# $include_filename
+# Name of file that sources this file.
+#
+# $skip_restore_connection
+# By default, this script restores the connection that was active
+# when begin_include_file.inc was sourced. If
+# $skip_restore_connection is set, then this step is skipped and
+# end_include_file.inc leaves the connection as it was before
+# end_include_file.inc was sourced.
+
+--let $_tmp= `SELECT SUBSTRING('$_include_file_enabled_warnings', 1, 1)`
+--let $_include_file_enabled_warnings= `SELECT SUBSTRING('$_include_file_enabled_warnings', 2)`
+if ($_tmp) {
+ --enable_warnings
+}
+if (!$_tmp) {
+ --disable_warnings
+}
+
+--let $_tmp= `SELECT SUBSTRING('$_include_file_enabled_query_log', 1, 1)`
+--let $_include_file_enabled_query_log= `SELECT SUBSTRING('$_include_file_enabled_query_log', 2)`
+if ($_tmp) {
+ --enable_query_log
+}
+if (!$_tmp) {
+ --disable_query_log
+}
+
+--let $_tmp= `SELECT SUBSTRING('$_include_file_enabled_result_log', 1, 1)`
+--let $_include_file_enabled_result_log= `SELECT SUBSTRING('$_include_file_enabled_result_log', 2)`
+if ($_tmp) {
+ --enable_result_log
+}
+if (!$_tmp) {
+ --disable_result_log
+}
+
+--let $_tmp= `SELECT SUBSTRING('$_include_file_enabled_abort_on_error', 1, 1)`
+--let $_include_file_enabled_abort_on_error= `SELECT SUBSTRING('$_include_file_enabled_abort_on_error', 2)`
+if ($_tmp) {
+ --enable_abort_on_error
+}
+if (!$_tmp) {
+ --disable_abort_on_error
+}
+
+--let $_include_file_rpl_connection_name= `SELECT SUBSTRING_INDEX('$_include_file_connection', ',', 1)`
+--let $_include_file_connection= `SELECT SUBSTRING('$_include_file_connection', LENGTH('$_include_file_rpl_connection_name') + 2)`
+if (!$skip_restore_connection)
+{
+ --let $rpl_connection_name= $_include_file_rpl_connection_name
+ --source include/rpl_connection.inc
+}
+--let $skip_restore_connection= 0
+
+
+--dec $_include_file_depth
+--let $_include_file_indent= `SELECT REPEAT('.', $_include_file_depth)`
+
+if ($rpl_debug)
+{
+ --echo $_include_file_indent==== END include/$include_filename ====
+ --echo $_include_file_indent con='$CURRENT_CONNECTION' warn='$ENABLED_WARNINGS' qlog='$ENABLED_QUERY_LOG' rlog='$ENABLED_RESULT_LOG' aborterr='$ENABLED_ABORT_ON_ERROR'
+}
+--let $include_filename=
diff --git a/mysql-test/include/file_does_not_exist.inc b/mysql-test/include/file_does_not_exist.inc
new file mode 100644
index 00000000000..0b02c63a0a9
--- /dev/null
+++ b/mysql-test/include/file_does_not_exist.inc
@@ -0,0 +1,17 @@
+# ==== Purpose ====
+#
+# Checks that a given file does not exist. If the file exists, the
+# test fails.
+#
+# ==== Usage ====
+#
+# --let $file_does_not_exist= /path/to/file
+# --source include/file_does_not_exist.inc
+
+# Will fail if file exists.
+--write_file $file_does_not_exist
+tmp
+EOF
+
+# Remove file again.
+--remove_file $file_does_not_exist
diff --git a/mysql-test/include/force_restart.inc b/mysql-test/include/force_restart.inc
new file mode 100644
index 00000000000..d058e85df45
--- /dev/null
+++ b/mysql-test/include/force_restart.inc
@@ -0,0 +1,17 @@
+# ==== Purpose ====
+#
+# Tell mtr that all servers must be restarted after the test has
+# finished.
+#
+# ==== Usage ====
+#
+# --source include/force_restart.inc
+#
+# ==== See also ====
+#
+# include/force_restart_if_skipped.inc
+
+--let $_force_restart_datadir= `SELECT @@datadir`
+--append_file $_force_restart_datadir/mtr/force_restart
+1
+EOF
diff --git a/mysql-test/include/force_restart_if_skipped.inc b/mysql-test/include/force_restart_if_skipped.inc
new file mode 100644
index 00000000000..228e094e932
--- /dev/null
+++ b/mysql-test/include/force_restart_if_skipped.inc
@@ -0,0 +1,17 @@
+# ==== Purpose ====
+#
+# Tell mtr that all servers must be restarted in case the test is
+# skipped.
+#
+# ==== Usage ====
+#
+# --source include/force_restart_if_skipped.inc
+#
+# ==== See also ====
+#
+# include/force_restart.inc
+
+--let $_force_restart_datadir= `SELECT @@datadir`
+--append_file $_force_restart_datadir/mtr/force_restart_if_skipped
+1
+EOF
diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc
index 8944cc46f3e..fa3e586834c 100644
--- a/mysql-test/include/have_innodb.inc
+++ b/mysql-test/include/have_innodb.inc
@@ -1,4 +1,4 @@
-disable_query_log;
---require r/true.require
-select (support = 'YES' or support = 'DEFAULT' or support = 'ENABLED') as `TRUE` from information_schema.engines where engine = 'innodb';
-enable_query_log;
+if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED')`)
+{
+ --skip Test requires InnoDB.
+}
diff --git a/mysql-test/include/io_thd_fault_injection.inc b/mysql-test/include/io_thd_fault_injection.inc
index a76e46d772a..7cbe055dbf6 100644
--- a/mysql-test/include/io_thd_fault_injection.inc
+++ b/mysql-test/include/io_thd_fault_injection.inc
@@ -11,11 +11,11 @@ SET @old_debug=@@global.debug;
-- eval SET GLOBAL debug="+d,$io_thd_injection_fault_flag"
START SLAVE io_thread;
--- source include/wait_for_slave_io_to_stop.inc
-- source include/wait_for_slave_io_error.inc
-- eval SET GLOBAL debug="-d,$io_thd_injection_fault_flag"
SET GLOBAL debug=@old_debug;
# restart because slave is in bad shape
--- source include/restart_mysqld.inc
+--let $rpl_server_number= 2
+--source include/rpl_restart_server.inc
diff --git a/mysql-test/include/kill_query_and_diff_master_slave.inc b/mysql-test/include/kill_query_and_diff_master_slave.inc
index b3846d12df1..59588551af5 100644
--- a/mysql-test/include/kill_query_and_diff_master_slave.inc
+++ b/mysql-test/include/kill_query_and_diff_master_slave.inc
@@ -9,19 +9,19 @@
# connection <CONNECTION>;
# let $connection_name=<CONNECTION>
# let $connection_id=`SELECT CONNECTION_ID()`;
-# let $diff_statement=<SQL COMMAND>;
+# let $rpl_diff_statement=<SQL COMMAND>;
# send <SQL COMMAND>;
# source include/kill_query_and_diff_master_slave.inc;
#
# Note: <CONNECTION> must not be 'master'.
#
-# See also kill_query.inc and diff_master_slave.inc for more
+# See also kill_query.inc and rpl_diff.inc for more
# information
source include/kill_query.inc;
# Release the debug lock if used, so that the statements in
-# diff_master_slave.inc will not be blocked.
+# rpl_diff.inc will not be blocked.
connection master;
disable_query_log;
disable_result_log;
@@ -32,7 +32,7 @@ if ($debug_lock)
enable_result_log;
enable_query_log;
-source include/diff_master_slave.inc;
+--source include/rpl_diff.inc
# Acquire the debug lock again if used
connection master;
diff --git a/mysql-test/include/master-slave-end.inc b/mysql-test/include/master-slave-end.inc
deleted file mode 100644
index 74e4c7b608a..00000000000
--- a/mysql-test/include/master-slave-end.inc
+++ /dev/null
@@ -1,6 +0,0 @@
---connection master
---sync_slave_with_master
---connection slave
---disable_query_log
-STOP SLAVE;
---enable_query_log
diff --git a/mysql-test/include/master-slave-reset.inc b/mysql-test/include/master-slave-reset.inc
deleted file mode 100644
index 938eb2c074a..00000000000
--- a/mysql-test/include/master-slave-reset.inc
+++ /dev/null
@@ -1,36 +0,0 @@
-# Reset the master and the slave to start fresh.
-#
-# It is necessary to execute RESET MASTER and RESET SLAVE on both
-# master and slave since the replication setup might be circular.
-#
-# Since we expect STOP SLAVE to produce a warning as the slave is
-# stopped (the server was started with skip-slave-start), we disable
-# warnings when doing STOP SLAVE.
-
-connection slave;
---disable_warnings
-stop slave;
-source include/wait_for_slave_to_stop.inc;
---enable_warnings
-connection master;
---disable_warnings
---disable_query_log
-use test;
---enable_query_log
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
-reset master;
---disable_query_log
-reset slave;
---enable_query_log
-connection slave;
-reset slave;
-# Clean up old test tables
---disable_warnings
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
---disable_query_log
-reset master;
---enable_query_log
-start slave;
-source include/wait_for_slave_to_start.inc;
diff --git a/mysql-test/include/master-slave.inc b/mysql-test/include/master-slave.inc
index e0eb87f02f7..9ed206b2c22 100644
--- a/mysql-test/include/master-slave.inc
+++ b/mysql-test/include/master-slave.inc
@@ -1,12 +1,63 @@
-# Replication tests need binlog
-source include/have_log_bin.inc;
+# ==== Purpose ====
+#
+# Configure two servers to be replication master and slave.
+#
+# ==== Usage ====
+#
+# [--let $rpl_server_count= N]
+# [--let $rpl_check_server_ids= 1]
+# [--let $rpl_skip_reset_master_and_slave= 1]
+# [--let $rpl_skip_change_master= 1]
+# [--let $rpl_skip_start_slave= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/master-slave.inc
+#
+# Parameters:
+# $rpl_check_server_ids, $rpl_skip_reset_master_and_slave,
+# $rpl_skip_change_master, $rpl_skip_start_slave, $rpl_debug,
+# $slave_timeout
+# See include/rpl_init.inc
+#
+# $rpl_server_count
+# By default, two servers are configured. You can configure more
+# servers (servers 3, 4, etc are neither masters nor slaves) by
+# setting this variable. See also include/rpl_init.inc
-connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
-connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,);
--- source include/master-slave-reset.inc
+--let $include_filename= master-slave.inc
+if ($rpl_server_count)
+{
+ --let $include_filename= master-slave.inc [rpl_server_count=$rpl_server_count]
+}
+--source include/begin_include_file.inc
-# Set the default connection to 'master'
-connection master;
+
+--let $rpl_topology= 1->2
+--source include/rpl_init.inc
+
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= master1
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+--let $rpl_connection_name= slave1
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
+
+
+--let $include_filename= master-slave.inc
+--source include/end_include_file.inc
+
+
+# Set the default connection to 'master'. Do this after
+# end_include_file.inc, so that it gets printed to the query log.
+--let $rpl_connection_name= master
+--source include/rpl_connection.inc
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index 9db631a2615..12cb2c870a2 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -57,13 +57,3 @@ BEGIN
mysql.user;
END||
-
---
--- Procedure used by test case used to force all
--- servers to restart after testcase and thus skipping
--- check test case after test
---
-CREATE DEFINER=root@localhost PROCEDURE force_restart()
-BEGIN
- SELECT 1 INTO OUTFILE 'force_restart';
-END||
diff --git a/mysql-test/include/mysqldump.inc b/mysql-test/include/mysqldump.inc
index 6227138b012..3a53bf8e3bd 100644
--- a/mysql-test/include/mysqldump.inc
+++ b/mysql-test/include/mysqldump.inc
@@ -41,8 +41,7 @@ eval ALTER TABLE $table_name RENAME to $orig_table_name;
--echo # Compare original and recreated tables
--echo # Recreated table: $table_name
--echo # Original table: $orig_table_name
-let $diff_table_1 = $table_name;
-let $diff_table_2 = $orig_table_name;
+let $diff_tables = $table_name, $orig_table_name;
--source include/diff_tables.inc
--echo # Cleanup
--remove_file $mysqldumpfile
diff --git a/mysql-test/include/ndb_master-slave.inc b/mysql-test/include/ndb_master-slave.inc
index 0bf4b701f0c..8305a310953 100644
--- a/mysql-test/include/ndb_master-slave.inc
+++ b/mysql-test/include/ndb_master-slave.inc
@@ -1,10 +1,4 @@
-# Replication tests need binlog
-source include/have_log_bin.inc;
-
-connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
-connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,);
+--source include/master-slave.inc
connection slave;
# Check that server is compiled and started with support for NDB
@@ -14,7 +8,5 @@ select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schem
--source include/ndb_not_readonly.inc
enable_query_log;
--- source include/master-slave-reset.inc
-
# Set the default connection to 'master'
connection master;
diff --git a/mysql-test/include/ndb_master-slave_2ch.inc b/mysql-test/include/ndb_master-slave_2ch.inc
index 52a06c01d86..17017d2b801 100644
--- a/mysql-test/include/ndb_master-slave_2ch.inc
+++ b/mysql-test/include/ndb_master-slave_2ch.inc
@@ -1,7 +1,6 @@
-#############################################################
-# Author: Serge Kozlov <skozlov@mysql.com>
-# Date: 03/17/2008
-# Purpose: Set up circular cluster replication where each
+# ==== Purpose ====
+#
+# Set up circular cluster replication where each
# cluster has two mysqlds and replication directions are
# following:
# master ---> slave
@@ -9,128 +8,60 @@
# cluster A cluster B
# \ /
# master1 <--- slave1
-#############################################################
-
---source include/have_log_bin.inc
+#
+# ==== Usage ====
+#
+# [--let $rpl_server_count= N]
+# [--let $rpl_skip_check_server_ids= 1]
+# [--let $rpl_skip_reset_master_and_slave= 1]
+# [--let $rpl_skip_change_master= 1]
+# [--let $rpl_skip_start_slave= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/ndb_master-slave_2ch.inc
+#
+# Parameters:
+# $rpl_server_count, $rpl_skip_check_server_ids,
+# $rpl_skip_reset_master_and_slave, $rpl_skip_change_master,
+# $rpl_skip_start_slave, $rpl_debug, $slave_timeout
+# See include/master-slave.inc
+
+--let $rpl_topology= 1->2,4->3
+--let $rpl_skip_check_server_ids= 1
+--source include/rpl_init.inc
# Make connections to mysqlds
-connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,);
-connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT1,);
-connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,);
-connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT1,);
-
-# Check that all mysqld compiled with ndb support
-
---connection master
---disable_query_log
---require r/true.require
-SELECT (support = 'YES' or support = 'DEFAULT') AS `TRUE` FROM information_schema.engines WHERE engine = 'ndbcluster';
---source include/ndb_not_readonly.inc
---enable_query_log
-
---connection master1
---disable_query_log
---require r/true.require
-SELECT (support = 'YES' or support = 'DEFAULT') AS `TRUE` FROM information_schema.engines WHERE engine = 'ndbcluster';
---source include/ndb_not_readonly.inc
---enable_query_log
-
---connection slave
---disable_query_log
---require r/true.require
-SELECT (support = 'YES' or support = 'DEFAULT') AS `TRUE` FROM information_schema.engines WHERE engine = 'ndbcluster';
---source include/ndb_not_readonly.inc
---enable_query_log
-
---connection slave1
---disable_query_log
---require r/true.require
-SELECT (support = 'YES' or support = 'DEFAULT') AS `TRUE` FROM information_schema.engines WHERE engine = 'ndbcluster';
---source include/ndb_not_readonly.inc
---enable_query_log
-
-# Stop slaves
-
---connection master
---disable_warnings
-STOP SLAVE;
---wait_for_slave_to_stop
---enable_warnings
+--let $rpl_connection_name= master
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
---connection master1
---disable_warnings
-STOP SLAVE;
---wait_for_slave_to_stop
---enable_warnings
+--let $rpl_connection_name= master1
+--let $rpl_server_number= 1
+--source include/rpl_connect.inc
---connection slave
---disable_warnings
-STOP SLAVE;
---wait_for_slave_to_stop
---enable_warnings
+--let $rpl_connection_name= slave
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
---connection slave1
---disable_warnings
-STOP SLAVE;
---wait_for_slave_to_stop
---enable_warnings
+--let $rpl_connection_name= slave1
+--let $rpl_server_number= 2
+--source include/rpl_connect.inc
-# Reset masters
---connection master
---disable_warnings
---disable_query_log
-USE test;
---enable_query_log
-DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
-RESET MASTER;
-
---connection master1
---disable_warnings
---disable_query_log
-USE test;
---enable_query_log
-DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
-RESET MASTER;
-
---connection slave
---disable_warnings
---disable_query_log
-USE test;
---enable_query_log
-DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
-RESET MASTER;
-
---connection slave1
---disable_warnings
---disable_query_log
-USE test;
---enable_query_log
-DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
---enable_warnings
-RESET MASTER;
-
-# Start slaves
-
---connection slave
-RESET SLAVE;
---replace_result $MASTER_MYPORT MASTER_MYPORT
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$MASTER_MYPORT,master_user='root'
-START SLAVE;
---source include/wait_for_slave_to_start.inc
-
---connection master1
-RESET SLAVE;
---replace_result $SLAVE_MYPORT1 SLAVE_MYPORT1
---eval CHANGE MASTER TO master_host='127.0.0.1',master_port=$SLAVE_MYPORT1,master_user='root'
-START SLAVE;
---source include/wait_for_slave_to_start.inc
+# Check that all mysqld are compiled with ndb support
+--let $_rpl_server= 4
+while ($_rpl_server)
+{
+ --connection server_$_rpl_server
+ if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'ndbcluster' AND (support = 'YES' OR support = 'DEFAULT')`)
+ {
+ --skip Test requires NDB.
+ }
+ --source include/ndb_not_readonly.inc
+ --dec $_rpl_server
+}
# Set the default connection to 'master' (cluster A)
connection master;
-
diff --git a/mysql-test/include/ndb_not_readonly.inc b/mysql-test/include/ndb_not_readonly.inc
index f50ca0cab66..ebb343bb18d 100644
--- a/mysql-test/include/ndb_not_readonly.inc
+++ b/mysql-test/include/ndb_not_readonly.inc
@@ -2,6 +2,9 @@
#
# wait for server to connect properly to cluster
#
+
+--disable_query_log
+
set @saved_log = @@sql_log_bin;
set sql_log_bin = 0;
--error 0,ER_NO_SUCH_TABLE,ER_OPEN_AS_READONLY,ER_GET_ERRMSG,ER_KEY_NOT_FOUND
@@ -25,6 +28,9 @@ while ($mysql_errno)
}
delete from mysql.ndb_apply_status where server_id=0;
set sql_log_bin = @saved_log;
+
+--enable_query_log
+
#
# connected
#
diff --git a/mysql-test/include/report-features.test b/mysql-test/include/report-features.test
index 1e4ab232490..75879f67165 100644
--- a/mysql-test/include/report-features.test
+++ b/mysql-test/include/report-features.test
@@ -9,4 +9,4 @@ show engines;
show variables;
--echo ===== STOP =====
--enable_query_log
-exit; \ No newline at end of file
+exit;
diff --git a/mysql-test/include/reset_master_and_slave.inc b/mysql-test/include/reset_master_and_slave.inc
deleted file mode 100644
index 30ba1f07a40..00000000000
--- a/mysql-test/include/reset_master_and_slave.inc
+++ /dev/null
@@ -1,8 +0,0 @@
---echo **** Resetting master and slave ****
-connection slave;
-source include/stop_slave.inc;
-RESET SLAVE;
-connection master;
-RESET MASTER;
-connection slave;
-source include/start_slave.inc;
diff --git a/mysql-test/include/restart_mysqld.inc b/mysql-test/include/restart_mysqld.inc
index f750385e300..7cb9c7994d8 100644
--- a/mysql-test/include/restart_mysqld.inc
+++ b/mysql-test/include/restart_mysqld.inc
@@ -1,4 +1,12 @@
+if ($rpl_inited)
+{
+ if (!$allow_rpl_inited)
+ {
+ --die ERROR IN TEST: When using the replication test framework (master-slave.inc, rpl_init.inc etc), use rpl_restart_server.inc instead of restart_mysqld.inc. If you know what you are doing and you really have to use restart_mysqld.inc, set allow_rpl_inited=1 before you source restart_mysqld.inc
+ }
+}
+
# Write file to make mysql-test-run.pl expect the "crash", but don't start
# it until it's told to
--let $_server_id= `SELECT @@server_id`
diff --git a/mysql-test/include/rpl_change_topology.inc b/mysql-test/include/rpl_change_topology.inc
new file mode 100644
index 00000000000..d25ebfbf25c
--- /dev/null
+++ b/mysql-test/include/rpl_change_topology.inc
@@ -0,0 +1,248 @@
+# ==== Purpose ====
+#
+# Changes replication topology. This file is normally sourced from
+# include/rpl_init.inc, but test cases can also source it if they
+# need to change topology after they have sourced include/rpl_init.inc
+#
+# This file sets up variables needed by include/rpl_sync.inc and many
+# other replication scripts in the include/ directory. It also issues
+# CHANGE MASTER on all servers where the configuration changes from
+# what it was before. It does not issue START SLAVE (use
+# include/rpl_start_slaves.inc for that).
+#
+# Note: it is not currently possible to change the number of servers
+# after the rpl_init.inc, without first calling rpl_end.inc. So the
+# test has to set $rpl_server_count to the total number of servers
+# that the test uses, before it sources include/rpl_init.inc. After
+# that, $rpl_server_count must not change until after next time the
+# test sources include/rpl_end.inc.
+#
+# Note: Since this script issues CHANGE MASTER, the test case must
+# ensure that all slaves where the configuration changes have stopped
+# both the IO thread and the SQL thread before this script is sourced.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_server_count= 7]
+# --let $rpl_topology= 1->2->3->1->4, 2->5, 6->7
+# [--let $rpl_skip_change_master= 1]
+# [--let $rpl_master_log_file= 1:master-bin.000001,3:master-bin.000003]
+# [--let $rpl_master_log_pos= 1:4711,3:107]
+# [--let $rpl_debug= 1]
+# --source include/rpl_change_topology.inc
+#
+# Parameters:
+# $rpl_master_log_file
+# By default, CHANGE MASTER is executed with MASTER_LOG_FILE set
+# to the name of the last binlog file on the master (retrieved by
+# executing SHOW MASTER STATUS). This variable can be set to
+# specify another filename. This variable should be a
+# comma-separated list of the following form:
+#
+# SERVER_NUMBER_1:FILE_NAME_1,SERVER_NUMBER_2:FILE_NAME_2,...
+#
+# Before CHANGE MASTER is executed on server N, this script checks
+# if $rpl_master_log_file contains the text N:FILE_NAME. If it
+# does, then MASTER_LOG_FILE is set to FILE_NAME. Otherwise,
+# MASTER_LOG_FILE is set to the last binlog on the master. For
+# example, to specify that server_1 should start replicate from
+# master-bin.000007 and server_5 should start replicate from
+# master-bin.012345, do:
+# --let $rpl_master_log_file= 1:master-bin.000007,5:master-bin.012345
+#
+# $rpl_master_log_pos
+# By default, CHANGE MASTER is executed without specifying the
+# MASTER_LOG_POS parameter. This variable can be set to set a
+# specific position. It has the same form as $rpl_master_log_file
+# (see above). For example, to specify that server_3 should start
+# replicate from position 4711 of its master, do:
+# --let $rpl_master_log_pos= 3:4711
+#
+# $rpl_server_count, $rpl_topology, $rpl_debug, $rpl_skip_change_master
+# See include/rpl_init.inc
+#
+#
+# ==== Internal variables configured by this file ====
+#
+# This file sets up the following variables, which are used by other
+# low-level replication files such as:
+# include/rpl_sync.inc
+# include/rpl_start_slaves.inc
+# include/rpl_stop_slaves.inc
+# include/rpl_end.inc
+#
+# $rpl_server_count_length:
+# Set to LENGTH($rpl_server_count). So if $rpl_server_count < 10,
+# then $rpl_server_count_length = 1; if 10 <= $rpl_server_count <
+# 100, then $rpl_server_count_length = 2, etc.
+#
+# $rpl_master_list
+# Set to a string consisting of $rpl_server_count numbers, each one
+# whitespace-padded to $rpl_server_count_length characters. If
+# server N is a slave, then the N'th number is the master of server
+# N. If server N is not a slave, then the N'th number is just spaces
+# (so in fact it is not a number). For example, if $rpl_topology is
+# '1->2,2->3,3->1,2->4,5->6', then $rpl_master_list is '3122 6'.
+#
+# $rpl_sync_chain_dirty
+# This variable is set to 1. This tells include/rpl_sync.inc to
+# compute a new value for $rpl_sync_chain next time that
+# include/rpl_sync.inc is sourced. See
+# include/rpl_generate_sync_chain.inc and include/rpl_sync.inc for
+# details.
+
+
+# Remove whitespace from $rpl_topology
+--let $rpl_topology= `SELECT REPLACE('$rpl_topology', ' ', '')`
+
+--let $include_filename= rpl_change_topology.inc [new topology=$rpl_topology]
+--source include/begin_include_file.inc
+
+
+if ($rpl_debug)
+{
+ --echo ---- Check input ----
+}
+
+
+if (`SELECT '$rpl_topology' = '' OR '$rpl_server_count' = ''`)
+{
+ --die You must set $rpl_topology and $rpl_server_count before you source rpl_change_topology.inc. If you really want to change to the empty topology, set $rpl_topology= none
+}
+--let $_rpl_topology= $rpl_topology
+if (`SELECT '$_rpl_topology' = 'none'`)
+{
+ --let $_rpl_topology=
+}
+if (`SELECT '!$rpl_master_list!' = '!!'`)
+{
+ --die You must source include/rpl_init.inc before you source include/rpl_change_topology.inc
+}
+--let $_rpl_old_master_list= $rpl_master_list
+
+if ($rpl_debug)
+{
+ --echo \$rpl_server_count='$rpl_server_count'
+ --echo \$rpl_server_count_length='$rpl_server_count_length'
+ --echo new \$rpl_topology='$_rpl_topology'
+ --echo old \$rpl_master_list='$rpl_master_list'
+ --echo old \$rpl_sync_chain='$rpl_sync_chain'
+}
+
+
+if ($rpl_debug)
+{
+ --echo ---- Generate \$rpl_server_count_length and \$rpl_master_list ----
+}
+
+--let $rpl_server_count_length= `SELECT LENGTH('$rpl_server_count')`
+--let $rpl_master_list=
+--let $_rpl_no_server= `SELECT REPEAT(' ', $rpl_server_count_length)`
+--let $rpl_master_list= `SELECT REPEAT('$_rpl_no_server', $rpl_server_count)`
+while ($_rpl_topology)
+{
+ # Get 's1->s2' from 's1->s2->s3->...' or from 's1->s2,s3->s4,...'
+ --let $_rpl_master_slave= `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('$_rpl_topology', ',', 1), '->', 2)`
+ # Modify $_rpl_topology as follows:
+ # - If it starts with 's1->s2,', remove 's1->s2,'
+ # - If it starts with 's1->s2->', remove 's1->'
+ # - If it is equal to 's1->s2', remove 's1->s2'
+ --let $_rpl_topology= `SELECT SUBSTR('$_rpl_topology', IF(SUBSTR('$_rpl_topology', LENGTH('$_rpl_master_slave') + 1, 2) != '->', LENGTH('$_rpl_master_slave'), LOCATE('->', '$_rpl_master_slave')) + 2)`
+ # Get 's1' from 's1->s2'
+ --let $_rpl_master= `SELECT SUBSTRING_INDEX('$_rpl_master_slave', '->', 1)`
+ # Get 's2' from 's1->s2'
+ --let $_rpl_slave= `SELECT SUBSTRING('$_rpl_master_slave', LENGTH('$_rpl_master') + 3)`
+ # Check that s2 does not have another master.
+ if (`SELECT SUBSTR('$rpl_master_list', 1 + ($_rpl_slave - 1) * $rpl_server_count_length, $rpl_server_count_length) != '$_rpl_no_server'`)
+ {
+ --echo ERROR IN TEST: Server '$_rpl_slave' has more than one master in topology '$rpl_topology'
+ --die ERROR IN TEST: found a server with more than one master in the $rpl_topology variable
+ }
+ # Save 's1' at position 's2' in $rpl_master_list
+ --let $rpl_master_list= `SELECT INSERT('$rpl_master_list', 1 + ($_rpl_slave - 1) * $rpl_server_count_length, $rpl_server_count_length, RPAD('$_rpl_master', $rpl_server_count_length, ' '))`
+}
+
+if ($rpl_debug)
+{
+ --echo new \$rpl_server_count_length = '$rpl_server_count_length'
+ --echo new \$rpl_master_list = '$rpl_master_list'
+}
+
+if (!$rpl_skip_change_master)
+{
+ if ($rpl_debug)
+ {
+ --echo ---- Execute CHANGE MASTER on all servers ----
+ }
+
+ if (!$rpl_debug)
+ {
+ --disable_query_log
+ }
+
+ --let $_rpl_server= $rpl_server_count
+ while ($_rpl_server)
+ {
+ # The following statement evaluates to:
+ # 0, if server_$_rpl_server has the same master as before.
+ # The master's server, if server_$_rpl_server is a slave.
+ # The empty string, if server_$_rpl_server is not a slave.
+ --let $_rpl_master= `SELECT TRIM(IFNULL(NULLIF(SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length), SUBSTRING('$_rpl_old_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length)), 0))`
+ if ($rpl_debug)
+ {
+ --echo \$_rpl_server='$_rpl_server' \$_rpl_master='$_rpl_master'
+ }
+ if ($_rpl_master)
+ {
+ # Get port number
+ --let $_rpl_port= \$SERVER_MYPORT_$_rpl_master
+ # Get MASTER_LOG_FILE
+ --let $_rpl_master_log_file_index= `SELECT LOCATE('$_rpl_server:', '$rpl_master_log_file')`
+ if ($_rpl_master_log_file_index)
+ {
+ # Get text from after ':' and before ',', starting at
+ # $_rpl_master_log_file
+ --let $_rpl_master_log_file= `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING('$rpl_master_log_file', $_rpl_master_log_file_index), ',', 1), ':', -1)`
+ }
+ if (!$_rpl_master_log_file_index)
+ {
+ --let $rpl_connection_name= server_$_rpl_master
+ --source include/rpl_connection.inc
+ --let $_rpl_master_log_file= query_get_value(SHOW MASTER STATUS, File, 1)
+ }
+ # Change connection.
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+ # Get MASTER_LOG_POS
+ --let $_rpl_master_log_pos_index= `SELECT LOCATE('$_rpl_server:', '$rpl_master_log_pos')`
+ if ($_rpl_master_log_pos_index)
+ {
+ --let $_rpl_master_log_pos= `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING('$rpl_master_log_pos', $_rpl_master_log_pos_index), ',', 1), ':', -1)`
+ --let $_rpl_master_log_pos= , MASTER_LOG_POS = $_rpl_master_log_pos
+ }
+ if (!$_rpl_master_log_pos_index)
+ {
+ --let $_rpl_master_log_pos=
+ }
+ eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $_rpl_port, MASTER_USER = 'root', MASTER_LOG_FILE = '$_rpl_master_log_file'$_rpl_master_log_pos, MASTER_CONNECT_RETRY = 1;
+ }
+ if (!$_rpl_master)
+ {
+ if (`SELECT '$_rpl_master' = ''`)
+ {
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+ CHANGE MASTER TO MASTER_HOST = '';
+ }
+ }
+ --dec $_rpl_server
+ }
+}
+
+
+--let $rpl_sync_chain_dirty= 1
+
+
+--let $include_filename= rpl_change_topology.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_connect.inc b/mysql-test/include/rpl_connect.inc
new file mode 100644
index 00000000000..a4d18dd5f9c
--- /dev/null
+++ b/mysql-test/include/rpl_connect.inc
@@ -0,0 +1,58 @@
+# ==== Purpose ====
+#
+# Create a connection to a given numbered server.
+#
+# This script is normally used internally by rpl_init.inc and
+# master-slave.inc, but it can also be used in test cases that need to
+# create more connections or re-create connections after disconnect.
+#
+#
+# ==== Usage ====
+#
+# --let $rpl_connection_name= <connection_name>
+# --let $rpl_server_number= <server_number>
+# [--let $rpl_debug= 1]
+# --source include/rpl_connect.inc
+#
+# Parameters:
+# $rpl_connection_name
+# The name of the connection to create.
+#
+# $rpl_server_number
+# The number of the server to connect to.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= rpl_connect.inc [creating $rpl_connection_name]
+--source include/begin_include_file.inc
+
+
+if (!$rpl_server_number)
+{
+ --die ERROR IN TEST: You must set $rpl_server_number before sourcing include/rpl_connect.inc
+}
+if (`SELECT '$rpl_connection_name' = ''`)
+{
+ --die ERROR IN TEST: You must set $rpl_connection_name before sourcing include/rpl_connect.inc
+}
+
+# Get port number
+--let $_rpl_port= \$SERVER_MYPORT_$rpl_server_number
+if (!$_rpl_port)
+{
+ --echo Bug in test case: '\$SERVER_MYPORT_$rpl_server_number' not initialized. Check the test's .cfg file.
+ --die Not all SERVER_MYPORT_* environment variables are setup correctly.
+}
+
+# Create connection.
+if ($rpl_debug)
+{
+ --echo connect ($rpl_connection_name,127.0.0.1,root,,test,$_rpl_port,)
+}
+--connect ($rpl_connection_name,127.0.0.1,root,,test,$_rpl_port,)
+
+
+--let $include_filename= rpl_connect.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_connection.inc b/mysql-test/include/rpl_connection.inc
new file mode 100644
index 00000000000..1988568a4d2
--- /dev/null
+++ b/mysql-test/include/rpl_connection.inc
@@ -0,0 +1,47 @@
+# ==== Purpose ====
+#
+# The same as 'connection $rpl_connection_name', but it can also
+# prints the connection name. The connection is printed if $rpl_debug
+# is set, or if rpl_connection.inc is not called between two
+# invocations of begin_include_file.inc/end_include_file.inc.
+# Otherwise the connection name is not printed.
+#
+#
+# ==== Usage ====
+#
+# --let $rpl_connection_name= master
+# [--let $rpl_debug= 1]
+# --source include/rpl_connection.inc
+#
+# Parameters:
+# $rpl_connection_name
+# Name of the connection to connect to.
+#
+# $rpl_debug
+# By default, the connection name is printed only when this file
+# is sourced from a top-level test script. If $rpl_debug is set,
+# the connection name is also printed whenever auxiliary files
+# like rpl_init.inc change connection.
+
+
+if (!$rpl_connection_name)
+{
+ --die ERROR IN TEST: you must set $rpl_connection_name before sourcing rpl_connection.inc
+}
+
+# This is the same as "if (!$_rpl_include_file_depth || $rpl_debug)",
+# but the mysqltest language doesn't have boolean operations.
+
+if (!$_include_file_depth)
+{
+ --echo [connection $rpl_connection_name]
+}
+if ($_include_file_depth)
+{
+ if ($rpl_debug)
+ {
+ --echo [connection $rpl_connection_name]
+ }
+}
+--connection $rpl_connection_name
+--let $rpl_connection_name=
diff --git a/mysql-test/include/rpl_diff.inc b/mysql-test/include/rpl_diff.inc
new file mode 100644
index 00000000000..bf24b4f2a13
--- /dev/null
+++ b/mysql-test/include/rpl_diff.inc
@@ -0,0 +1,118 @@
+# ==== Purpose ====
+#
+# Diff the output of a statement on all configured servers (usually
+# master and slave).
+#
+#
+# ==== Usage =====
+#
+# --let $rpl_diff_statement= SELECT * FROM t1 WHERE a < 100
+# [--let $rpl_diff_servers= <server1>,<server2>,...<serverN>]
+# --source include/rpl_diff.inc
+#
+# Parameters:
+# $rpl_diff_statement
+# Statement to check. For each compared server, this script will
+# start a new client and pass this statement to the client.
+# Note: This string will be evaluated as a single-quote-escaped
+# SQL string and hence must be quoted as such. In particular, any
+# single quotes in this string must be escaped.
+#
+# $rpl_diff_servers
+# By default, this file compares all servers configured by
+# rpl_init.inc. You can set $diff_servers to a comma-separated
+# list of numbers: only the servers identified by these numbers
+# will be compared.
+#
+# $rpl_diff_database
+# By default, the statement will be executed on the database
+# 'test'. If $rpl_diff_database is set, the statement will be
+# executed on the database named $rpl_diff_database instead.
+
+
+--let $include_filename= rpl_diff.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_diff_statement)
+{
+ --die ERROR IN TEST: you must set $rpl_diff_statement before you source include/rpl_diff.inc
+}
+
+
+# Sync.
+--source include/rpl_sync.inc
+
+
+# Get database name.
+--let $_rpl_diff_database= $rpl_diff_database
+if (`SELECT '$_rpl_diff_database' = ''`)
+{
+ --let $_rpl_diff_database= test
+}
+
+
+# Generate list of servers.
+--let $_rpl_diff_servers= $rpl_diff_servers
+if (!$_rpl_diff_servers)
+{
+ --let $_rpl_server_i= $rpl_server_count
+ --let $_rpl_diff_servers=
+ while ($_rpl_server_i)
+ {
+ --let $_rpl_diff_servers= $_rpl_server_i,$_rpl_diff_servers
+ --dec $_rpl_server_i
+ }
+}
+if ($rpl_debug)
+{
+ --echo \$rpl_diff_servers= '$_rpl_diff_servers'
+}
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+# Generate file containing $rpl_diff_statement. We don't pass the
+# statement on the command line, because it would be subject to shell
+# substitutions.
+--let $write_to_file= GENERATE
+--let $write_var= $rpl_diff_statement
+--source include/write_var_to_file.inc
+--let $_rpl_diff_statement_file= $write_to_file
+
+
+# Compare all servers.
+--let $_rpl_diff_first= 1
+while ($_rpl_diff_servers)
+{
+ # Set $_rpl_diff_server_i to the first number in the list
+ --let $_rpl_diff_server_i= `SELECT SUBSTRING_INDEX('$_rpl_diff_servers', ',', 1)`
+ # Remove $_rpl_diff_server_i from the list
+ --let $_rpl_diff_servers= `SELECT SUBSTRING('$_rpl_diff_servers', LENGTH('$_rpl_diff_server_i') + 2)`
+
+ # Execute statement
+ --let $_rpl_diff_file= $MYSQLTEST_VARDIR/tmp/_rpl_diff_server-$_rpl_diff_server_i.tmp
+ --exec $MYSQL --defaults-group-suffix=.$_rpl_diff_server_i $_rpl_diff_database < $_rpl_diff_statement_file > $_rpl_diff_file
+
+ # Compare
+ if (!$_rpl_diff_first)
+ {
+ if ($rpl_debug)
+ {
+ --echo diffing $_rpl_diff_file and $_rpl_diff_prev_file
+ }
+ --diff_files $_rpl_diff_file $_rpl_diff_prev_file
+ --remove_file $_rpl_diff_prev_file
+ }
+ --let $_rpl_diff_prev_file= $_rpl_diff_file
+ --let $_rpl_diff_first= 0
+}
+--remove_file $_rpl_diff_prev_file
+
+
+--let $include_filename= rpl_diff.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_diff_tables.inc b/mysql-test/include/rpl_diff_tables.inc
deleted file mode 100644
index 7fc68422c40..00000000000
--- a/mysql-test/include/rpl_diff_tables.inc
+++ /dev/null
@@ -1,36 +0,0 @@
-# #############################################################################
-# Check whether the given table is consistent between different master and
-# slaves
-#
-# Usage:
-# --let $diff_table= test.t1
-# --let $diff_server_list= master, slave, slave2
-# --source include/rpl_diff_tables.inc
-# #############################################################################
-
-if (`SELECT "XX$diff_table" = "XX"`)
-{
- --die diff_table is null.
-}
-
---let $_servers= master, slave
-if (`SELECT "XX$diff_server_list" <> "XX"`)
-{
- --let $_servers= $diff_server_list
-}
-
---let $_master= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)`
---let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_master') + 2))`
-connection $_master;
-while (`SELECT "XX$_servers" <> "XX"`)
-{
- --let $_slave= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)`
- --let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_slave') + 2))`
-
- --sync_slave_with_master $_slave
- --let $diff_table_1= $_master:$diff_table
- --let $diff_table_2= $_slave:$diff_table
- --source include/diff_tables.inc
- connection $_slave;
-}
-connection $_master;
diff --git a/mysql-test/include/rpl_end.inc b/mysql-test/include/rpl_end.inc
new file mode 100644
index 00000000000..8f1d7f695fc
--- /dev/null
+++ b/mysql-test/include/rpl_end.inc
@@ -0,0 +1,103 @@
+# ==== Purpose ====
+#
+# Shut down replication initialized by include/rpl_init.inc.
+#
+# This syncs all servers, executes STOP SLAVE on all servers, executes
+# CHANGE MASTER on all servers, and disconnects all connections
+# configured by rpl_init.inc.
+#
+# It does not execute RESET MASTER or RESET SLAVE, because that would
+# remove binlogs which are possibly useful debug information in case
+# the test case later fails with a result mismatch. If you need that,
+# source include/rpl_reset.inc before you source this file.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_only_running_threads= 1]
+# [--let $rpl_debug= 1]
+# --source include/rpl_end.inc
+#
+# Parameters:
+# $rpl_only_running_threads
+# If one or both of the IO and SQL threads is stopped, sync and
+# stop only the threads that are running. See
+# include/rpl_sync.inc and include/stop_slave.inc for details.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# Note:
+# This script will fail if Last_SQL_Error or Last_IO_Error is
+# nonempty. If you expect an error in the SQL thread, you should
+# normally call this script as follows:
+#
+# --source include/wait_for_slave_sql_error.inc
+# --source include/stop_slave_io.inc
+# RESET SLAVE;
+# --let $rpl_only_running_threads= 1
+# --source include/rpl_end.inc
+#
+#
+# ==== Side effects ====
+#
+# Changes the current connection to 'default'.
+
+
+--let $include_filename= rpl_end.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_inited)
+{
+ --die ERROR IN TEST: rpl_end.inc was sourced when replication was not configured. Most likely, rpl_end.inc was sourced twice or rpl_init.inc has not been sourced.
+}
+
+
+if ($rpl_debug)
+{
+ --echo ---- Check that no slave thread has an error ----
+}
+
+--let $_rpl_server= $rpl_server_count
+while ($_rpl_server)
+{
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+
+ # Only check slave threads for error on hosts that were at some
+ # point configured as slave.
+ --let $_tmp= query_get_value(SHOW SLAVE STATUS, Master_Host, 1)
+ if (`SELECT '$_tmp' != 'No such row'`)
+ {
+ --source include/check_slave_no_error.inc
+ }
+
+ --dec $_rpl_server
+}
+
+--source include/rpl_sync.inc
+--source include/rpl_stop_slaves.inc
+
+# mtr configures server 2 to be a slave before it runs the test. We
+# have to restore that state now, so we change topology to 1->2.
+--let $rpl_topology= 1->2
+--source include/rpl_change_topology.inc
+
+
+--connection default
+--let $_rpl_server= $rpl_server_count
+--let $_rpl_one= _1
+while ($_rpl_server)
+{
+ --disconnect server_$_rpl_server
+ --disconnect server_$_rpl_server$_rpl_one
+ --dec $_rpl_server
+}
+
+--let $rpl_inited= 0
+
+# Do not restore connection, because we have disconnected it.
+--let $skip_restore_connection= 1
+--let $include_filename= rpl_end.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_for_each_slave.inc b/mysql-test/include/rpl_for_each_slave.inc
new file mode 100644
index 00000000000..65d242cf894
--- /dev/null
+++ b/mysql-test/include/rpl_for_each_slave.inc
@@ -0,0 +1,39 @@
+# ==== Purpose ====
+#
+# Execute a .inc file once for each server that was configured as a
+# slave by rpl_init.inc
+#
+#
+# ==== Usage ====
+#
+# --let $rpl_source_file
+# [--let $rpl_debug= 1]
+# --source include/rpl_for_each_slave.inc
+#
+# Parameters:
+# $rpl_source_file
+# The file that will be sourced.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= rpl_for_each_file.inc [$rpl_source_file]
+--source include/begin_include_file.inc
+
+--let $_rpl_server= $rpl_server_count
+while ($_rpl_server)
+{
+ --let $_rpl_has_master= `SELECT SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length) != ''`
+ if ($_rpl_has_master)
+ {
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+ --source $rpl_source_file
+ }
+ --dec $_rpl_server
+}
+
+
+--let $include_filename= rpl_for_each_file.inc [$rpl_source_file]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_generate_sync_chain.inc b/mysql-test/include/rpl_generate_sync_chain.inc
new file mode 100644
index 00000000000..9104c21c3b8
--- /dev/null
+++ b/mysql-test/include/rpl_generate_sync_chain.inc
@@ -0,0 +1,122 @@
+# ==== Purpose ====
+#
+# Setup $rpl_sync_chain, which is used by rpl_sync.inc. You normally
+# don't need to source this file, it should only be sourced by
+# rpl_sync.inc.
+#
+# $rpl_sync_chain is set to a string that specifies in what order
+# servers should be synchronized in include/rpl_sync.inc. This has the
+# form of a sequence of "chains" (with no separator between two
+# chains). Each chain begins with $rpl_server_count_length space
+# characters, followed by a sequence of numbers, each number
+# whitespace-padded to $rpl_server_count_length characters. Each
+# number in the sequence denotes a server, and the N'th server is a
+# master of the (N+1)'th server. For example, if $rpl_topology is
+# '1->2,2->3,3->1,2->4,5->6', then $rpl_sync_chain is ' 56 123124'.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_debug= 1]
+# --source include/rpl_generate_sync_chain.inc
+#
+# Parameters:
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= rpl_generate_sync_chain.inc
+--source include/begin_include_file.inc
+
+
+# Algorithm:
+# 0. Mark all servers as unseen and unsynced.
+# 1. Let S be a server that is marked unseen.
+# 2. Append S to the list of seen servers.
+# 3. Check how S is marked:
+# 3.1. If S has no master: append the list of seen servers (in
+# order from grand-master to grand-slave) to the end of
+# $rpl_sync_chain. Go to 3.
+# 3.2. Elseif S is marked as synced: append the list of seen
+# servers (in order from grand-master to grand-slave) to the
+# end of $rpl_sync_chain. Go to 3.
+# 3.3. Elseif S is marked as unsynced but seen: This means that the
+# graph of visited servers has a "6-shape": it is a loop with
+# a tail, such as 1->2->3->1->4->5. We should first sync the
+# loop, and then the tail. To ensure all servers in the loop
+# are synced, we must sync the loop two turns minus two
+# servers. For example, the loop 1->2->3->4->5->1 is fully
+# synced by this sequence of 1-step synchronizations:
+# 1->2->3->4->5->1->2->3->4. Hence we do this: in the list of
+# traversed servers (in order from grand-master to
+# grand-slave), find the first occurrence of S. Take the
+# sub-list starting at the 3rd server and ending at the first
+# occurrence of S. Append this sub-list it to the end of
+# $rpl_sync_chain. Then append the entire list of traversed
+# servers (in order from grand-master to grand-slave) to
+# $rpl_sync_chain. Go to 3.
+# 3.4. Else (i.e., S has a master and is not marked as seen or
+# synced): Mark S as seen. Set S=master(S) and go back to 2.
+# 4. For each server that is marked as seen, mark it as synced.
+# 5. If there are unseen servers, go back to 1.
+
+# $_rpl_server_marks holds the marks of all servers. The i'th character
+# corresponds to the mark of server i:
+# '0' = unseen & unmarked, '1' = seen & unsynced, '2' = seen & synced.
+--let $_rpl_server_marks= `SELECT REPEAT('0', $rpl_server_count)`
+--let $_rpl_start_server= $rpl_server_count
+--let $rpl_sync_chain=
+while ($_rpl_start_server)
+{
+ --let $_rpl_server= `SELECT RPAD('$_rpl_start_server', $rpl_server_count_length, ' ')`
+ --let $_rpl_seen_list=
+ --let $_rpl_continue_loop= 1
+ while ($_rpl_continue_loop)
+ {
+ --let $_rpl_master= `SELECT SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length)`
+ # We need to delimit elements of $_rpl_seen_list with commas, so
+ # that LOCATE() below will not find spurious matches that begin in
+ # the middle of one element and end in the middle of next element.
+ --let $_rpl_seen_list= $_rpl_server,$_rpl_seen_list
+ # If server is marked seen or synced, or has no master
+ if (`SELECT SUBSTRING('$_rpl_server_marks', $_rpl_server, 1) != 0 OR '$_rpl_master' = ''`)
+ {
+ # If server is marked seen but not synced.
+ if (`SELECT SUBSTRING('$_rpl_server_marks', $_rpl_server, 1) = 1`)
+ {
+ # Get sub-list of servers to prepend to server list.
+ # E.g., if topology is 1->2->3->4->1->5, then at this point
+ # $_rpl_seen_list='1,2,3,4,1,5,' and we have to prepend '4,3,'
+ # to it. Hence, the sub-list starts at position
+ # 1+2*($rpl_server_count_length+1) and ends at the first
+ # occurrence of ',1,' in the list.
+ --let $_rpl_extra_list= `SELECT SUBSTRING('$_rpl_seen_list', 1 + 2 * ($rpl_server_count_length + 1), LOCATE(',$_rpl_server,', '$_rpl_seen_list') - 2 * ($rpl_server_count_length + 1))`
+ --let $_rpl_seen_list= $_rpl_extra_list$_rpl_seen_list
+ }
+ # Append the seen servers. Only need to append if the list
+ # contains at least two elements.
+ if (`SELECT LENGTH('$_rpl_seen_list') > $rpl_server_count_length + 1`)
+ {
+ --let $rpl_sync_chain= $rpl_sync_chain$_rpl_no_server$_rpl_seen_list
+ }
+ --let $_rpl_continue_loop= 0
+ }
+ --let $_rpl_server_marks= `SELECT INSERT('$_rpl_server_marks', $_rpl_server, 1, '1')`
+ --let $_rpl_server= $_rpl_master
+ }
+ # Mark seen servers as synced
+ --let $_rpl_server_marks= `SELECT REPLACE('$_rpl_server_marks', '1', '2')`
+ # Get highest-numbered unmarked server.
+ --let $_rpl_start_server= `SELECT IFNULL(NULLIF($rpl_server_count + 1 - LOCATE('0', REVERSE('$_rpl_server_marks')), $rpl_server_count + 1), 0)`
+}
+# Strip commas: they were only needed temporarily.
+--let $rpl_sync_chain= `SELECT REPLACE('$rpl_sync_chain', ',', '')`
+
+if ($rpl_debug)
+{
+ --echo Generated \$rpl_sync_chain = '$rpl_sync_chain'
+}
+
+
+--let $include_filename= rpl_generate_sync_chain.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_init.inc b/mysql-test/include/rpl_init.inc
new file mode 100644
index 00000000000..3cf78dc2979
--- /dev/null
+++ b/mysql-test/include/rpl_init.inc
@@ -0,0 +1,242 @@
+# ==== Purpose ====
+#
+# Set up replication on several servers in a specified topology.
+#
+# By default, this script does the following:
+# - Creates the connections server_1, server_2, ..., server_N, as
+# well as extra connections server_1_1, server_2_1, ...,
+# server_N_1. server_I and server_I_1 are connections to the same
+# server.
+# - Sets up @@auto_increment_increment and @@auto_increment_increment.
+# - Verifies that @@server_id of all servers are different.
+# - Calls RESET MASTER, RESET SLAVE, USE test, CHANGE MASTER, START SLAVE.
+# - Sets the connection to server_1 before exiting.
+#
+# ==== Usage ====
+#
+# 1. If you are going to use more than two servers, create
+# rpl_test.cfg with the following contents:
+#
+# !include ../my.cnf
+# [mysqld.1]
+# log-slave-updates
+# [mysqld.2]
+# log-slave-updates
+# ...
+# [mysqld.N]
+# log-slave-updates
+#
+# [ENV]
+# SERVER_MYPORT_3= @mysqld.3.port
+# SERVER_MYPORT_4= @mysqld.4.port
+# SERVER_MYPORT_5= @mysqld.5.port
+# ...
+# SERVER_MYPORT_N= @mysqld.N.port
+#
+# (It is allowed, but not required, to configure SERVER_MYPORT_1
+# and SERVER_MYPORT_2 too. If these variables are not set, the
+# variables MASTER_MYPORT and SLAVE_MYPORT, configured in the
+# default my.cnf used by the rpl and rpl_ndb suites, are used
+# instead. In addition, in the rpl_ndb suite, SERVER_MYPORT_3 is
+# not needed since MASTER_MYPORT1 can be used instead.)
+#
+# 2. Execute the following near the top of the test:
+#
+# [--let $rpl_server_count= 7]
+# --let $rpl_topology= 1->2->3->1->4, 2->5, 6->7
+# [--let $rpl_check_server_ids= 1]
+# [--let $rpl_skip_change_master= 1]
+# [--let $rpl_skip_start_slave= 1]
+# [--let $rpl_skip_reset_master_and_slave= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/rpl_init.inc
+#
+# Parameters:
+#
+# $rpl_server_count
+# The number of servers to configure. If this is not set, the largest
+# number in $rpl_topology will be used.
+#
+# $rpl_topology
+# A comma-separated list of replication chain
+# specifications. Each replication chain specification has the
+# form S1->S2->...->Sn, where 1 <= S1,...Sn <= $rpl_server_count.
+# This file will configure S(i+1) to be a slave of S(i). If you
+# want to specify the empty topology (no server replicates at
+# all), you have to set $rpl_topology=none.
+#
+# $rpl_check_server_ids
+# If $rpl_check_server_ids is set, this script checks that the
+# @@server_id of all servers are different. This is normally
+# guaranteed by mtr, so it is only useful for debugging.
+#
+# $rpl_skip_reset_master_and_slave
+# By default, this script issues RESET MASTER and RESET SLAVE
+# before CHANGE MASTER and START SLAVE. RESET MASTER and RESET
+# SLAVE are suppressed if $rpl_skip_reset_master_and_slave is
+# set.
+#
+# $rpl_skip_change_master
+# By default, this script issues CHANGE MASTER so that all slaves
+# are ready to run as specified by $rpl_topology. CHANGE MASTER
+# is suppressed if $rpl_skip_change_master is set.
+#
+# $rpl_skip_start_slave
+# By default, this script issues START SLAVE on all slaves
+# specified by $rpl_topology. START SLAVE is suppressed if
+# $rpl_skip_change_master is set.
+#
+# $rpl_debug
+# By default, this script only outputs a static text that says
+# that rpl_init.inc was invoked. If $rpl_debug is set, additional
+# debug info is printed. The debug info may be nondeterministic,
+# so no test case should be checked in with $rpl_debug set.
+#
+# $slave_timeout
+# Timeout used when waiting for the slave threads to start.
+# See include/wait_for_slave_param.inc
+#
+#
+# ==== Side effects ====
+#
+# Changes current connection to server_1.
+
+--source include/have_log_bin.inc
+
+
+--let $include_filename= rpl_init.inc [topology=$rpl_topology]
+--source include/begin_include_file.inc
+
+
+if ($rpl_debug)
+{
+ --echo ---- Check input ----
+ --echo MASTER_MYPORT='$MASTER_MYPORT' SLAVE_MYPORT='$SLAVE_MYPORT' MASTER_MYPORT1='$MASTER_MYPORT1' SLAVE_MYPORT1='$SLAVE_MYPORT1'
+}
+
+# Allow $MASTER_MYPORT as alias for $SERVER_MYPORT_1
+if (`SELECT '$SERVER_MYPORT_1' = ''`)
+{
+ --let SERVER_MYPORT_1= $MASTER_MYPORT
+}
+# Allow $SLAVE_MYPORT as alias for $SERVER_MYPORT_2
+if (`SELECT '$SERVER_MYPORT_2' = ''`)
+{
+ --let SERVER_MYPORT_2= $SLAVE_MYPORT
+}
+# Allow $MASTER_MYPORT1 as alias for $SERVER_MYPORT_3
+# (this alias is used by rpl_ndb tests)
+if (`SELECT '$SERVER_MYPORT_3' = ''`)
+{
+ --let SERVER_MYPORT_3= $MASTER_MYPORT1
+}
+# Allow $SLAVE_MYPORT1 as alias for $SERVER_MYPORT_4
+# (this alias is used by rpl_ndb tests)
+if (`SELECT '$SERVER_MYPORT_4' = ''`)
+{
+ --let SERVER_MYPORT_4= $SLAVE_MYPORT1
+}
+# Check that $rpl_server_count is set
+if (!$rpl_server_count)
+{
+ --let $_compute_rpl_server_count= `SELECT REPLACE('$rpl_topology', '->', ',')`
+ --let $rpl_server_count= `SELECT GREATEST($_compute_rpl_server_count)`
+}
+
+
+if ($rpl_debug)
+{
+ --echo ---- Setup connections and reset each server ----
+}
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+# Create two connections to each server; reset master/slave, select
+# database, set autoinc variables.
+--let $_rpl_server= $rpl_server_count
+--let $_rpl_one= _1
+while ($_rpl_server)
+{
+ # Connect.
+ --let $rpl_server_number= $_rpl_server
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connect.inc
+ --let $rpl_connection_name= server_$_rpl_server$_rpl_one
+ --source include/rpl_connect.inc
+
+ # Configure server.
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+ USE test;
+ if (!$rpl_skip_reset_master_and_slave)
+ {
+ RESET MASTER;
+ RESET SLAVE;
+ }
+ eval SET auto_increment_increment= $rpl_server_count;
+ eval SET auto_increment_offset= $_rpl_server;
+
+ --dec $_rpl_server
+}
+
+
+# Signal that initialization is done and all connections created.
+--let $rpl_inited= 1
+
+# Signal that the server is in a dirty state and needs to be restarted
+# if the test is skipped. If the test is not skipped, it will continue
+# to the end and execute its cleanup section (and check-testcase will
+# report if you forget to clean up).
+--source include/force_restart_if_skipped.inc
+
+
+# Assert that all hosts have different server_ids
+if ($rpl_check_server_ids)
+{
+ if ($rpl_debug)
+ {
+ --echo ---- Check that @@server_id is distinct for all servers ----
+ }
+
+ --let $_rpl_server= $rpl_server_count
+ while ($_rpl_server)
+ {
+ --let $_rpl_server2= $_rpl_server
+ --dec $_rpl_server2
+ while ($_rpl_server2)
+ {
+ --let $assert_text= Servers $_rpl_server and $_rpl_server2 should have different @@server_id
+ --let $assert_condition= [$_rpl_server:SELECT @@server_id AS i, i, 1] != [$_rpl_server2:SELECT @@server_id AS i, i, 1]
+
+ --source include/assert.inc
+ --dec $_rpl_server2
+ }
+ --dec $_rpl_server
+ }
+}
+
+# $rpl_master_list must be set so that include/rpl_change_topology.inc
+# knows which servers are initialized and not.
+--let $rpl_master_list= `SELECT REPEAT('x', $rpl_server_count * LENGTH($rpl_server_count))`
+--source include/rpl_change_topology.inc
+
+
+if (!$rpl_skip_start_slave)
+{
+ --source include/rpl_start_slaves.inc
+}
+
+
+--let $rpl_connection_name= server_1
+--source include/rpl_connection.inc
+
+
+--let $skip_restore_connection= 1
+--let $include_filename= rpl_init.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_reconnect.inc b/mysql-test/include/rpl_reconnect.inc
new file mode 100644
index 00000000000..cdbbd0a1bf1
--- /dev/null
+++ b/mysql-test/include/rpl_reconnect.inc
@@ -0,0 +1,132 @@
+# ==== Purpose ====
+#
+# After a server has restarted, this waits for all clients configured
+# by rpl_init.inc and/or master-slave.inc to reconnect again.
+#
+# For each connection, it issues this:
+# --enable_reconnect
+# --source include/wait_until_connected_again.inc
+# --disable_reconnect
+#
+#
+# ==== Usage ====
+#
+# --let $rpl_server_number= N
+# [--let $rpl_debug= 1]
+# --source include/rpl_reconnect.inc
+#
+# Parameters:
+# $rpl_server_number
+# Number to identify the server that needs to reconnect. 1 is the
+# master server, 2 the slave server, 3 the 3rd server, and so on.
+# Cf. include/rpl_init.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+--let $include_filename= rpl_reconnect.inc
+--source include/begin_include_file.inc
+
+if (!$rpl_server_number)
+{
+ --die ERROR IN TEST: you must set $rpl_server_number before you source rpl_connect.inc
+}
+
+
+if ($rpl_debug)
+{
+ --echo ---- Enable reconnect ----
+}
+
+--let $_rpl_server_number= $rpl_server_number
+
+--dec $_rpl_server_number
+if (!$_rpl_server_number)
+{
+ --let $rpl_connection_name= default
+ --source include/rpl_connection.inc
+ --enable_reconnect
+
+ --let $rpl_connection_name= master
+ --source include/rpl_connection.inc
+ --enable_reconnect
+
+ --let $rpl_connection_name= master1
+ --source include/rpl_connection.inc
+ --enable_reconnect
+}
+
+--dec $_rpl_server_number
+if (!$_rpl_server_number)
+{
+ --let $rpl_connection_name= slave
+ --source include/rpl_connection.inc
+ --enable_reconnect
+
+ --let $rpl_connection_name= slave1
+ --source include/rpl_connection.inc
+ --enable_reconnect
+}
+
+--let $rpl_connection_name= server_$rpl_server_number
+--source include/rpl_connection.inc
+--enable_reconnect
+
+--let $_rpl_one= _1
+--let $rpl_connection_name= server_$rpl_server_number$_rpl_one
+--source include/rpl_connection.inc
+--enable_reconnect
+
+if ($rpl_debug)
+{
+ --echo ---- Wait for reconnect and disable reconnect on all connections ----
+}
+
+--let $_rpl_server_number= $rpl_server_number
+
+--dec $_rpl_server_number
+if (!$_rpl_server_number)
+{
+ --let $rpl_connection_name= default
+ --source include/rpl_connection.inc
+ --source include/wait_until_connected_again.inc
+ --disable_reconnect
+
+ --let $rpl_connection_name= master
+ --source include/rpl_connection.inc
+ --source include/wait_until_connected_again.inc
+ --disable_reconnect
+
+ --let $rpl_connection_name= master1
+ --source include/rpl_connection.inc
+ --source include/wait_until_connected_again.inc
+ --disable_reconnect
+}
+
+--dec $_rpl_server_number
+if (!$_rpl_server_number)
+{
+ --let $rpl_connection_name= slave
+ --source include/rpl_connection.inc
+ --source include/wait_until_connected_again.inc
+ --disable_reconnect
+
+ --let $rpl_connection_name= slave1
+ --source include/rpl_connection.inc
+ --source include/wait_until_connected_again.inc
+ --disable_reconnect
+}
+
+--let $rpl_connection_name= server_$rpl_server_number
+--source include/rpl_connection.inc
+--source include/wait_until_connected_again.inc
+--disable_reconnect
+
+--let $rpl_connection_name= server_$rpl_server_number$_rpl_one
+--source include/rpl_connection.inc
+--source include/wait_until_connected_again.inc
+--disable_reconnect
+
+
+--let $include_filename= rpl_reconnect.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_reset.inc b/mysql-test/include/rpl_reset.inc
new file mode 100644
index 00000000000..a94371c38fc
--- /dev/null
+++ b/mysql-test/include/rpl_reset.inc
@@ -0,0 +1,81 @@
+# ==== Purpose ====
+#
+# Reset all replication servers to a clean state:
+#
+# - sync all slaves,
+# - stop all slaves (STOP SLAVE),
+# - remove all binlogs and relay logs (RESET MASTER and RESET SLAVE),
+# - start all slaves again (START SLAVE).
+#
+# It does not execute CHANGE MASTER, so the replication topology is
+# kept intact.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_only_running_threads= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/rpl_end.inc
+#
+# Parameters:
+# $rpl_only_running_threads
+# If one or both of the IO and SQL threads is stopped, sync and
+# stop only the threads that are running. See
+# include/rpl_sync.inc and include/stop_slave.inc for details.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# $slave_timeout
+# Set the timeout when waiting for slave threads to stop and
+# start, respectively. See include/wait_for_slave_param.inc
+#
+# Note:
+# This script will fail if Last_SQL_Error or Last_IO_Error is
+# nonempty. If you expect an error in the SQL thread, you should
+# normally do this before you source include/rpl_reset.inc:
+#
+# --source include/wait_for_slave_sql_error.inc
+# --source include/stop_slave_io.inc
+# RESET SLAVE;
+
+--let $include_filename= rpl_reset.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+--source include/rpl_sync.inc
+
+
+if ($rpl_debug)
+{
+ --echo ---- Stop and reset all servers ----
+}
+--let $_rpl_server= $rpl_server_count
+while ($_rpl_server)
+{
+ --let $rpl_connection_name= server_$_rpl_server
+ --source include/rpl_connection.inc
+
+ # Check if this server is configured to have a master
+ if (`SELECT SUBSTRING('$rpl_master_list', 1 + ($_rpl_server - 1) * $rpl_server_count_length, $rpl_server_count_length) != ''`)
+ {
+ --source include/stop_slave.inc
+ RESET SLAVE;
+ }
+ RESET MASTER;
+ --dec $_rpl_server
+}
+
+
+--source include/rpl_start_slaves.inc
+
+
+--let $include_filename= rpl_reset.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_restart_server.inc b/mysql-test/include/rpl_restart_server.inc
new file mode 100644
index 00000000000..5df2c67d3da
--- /dev/null
+++ b/mysql-test/include/rpl_restart_server.inc
@@ -0,0 +1,39 @@
+# ==== Purpose ====
+#
+# Shut down and shut up the server given by $rpl_server_number. This
+# is equivalent to rpl_stop_server.inc followed by rpl_start_server.inc
+#
+# ==== Usage ====
+#
+# --let $rpl_server_number= N
+# [--let $rpl_server_parameters= --flag1 --flag2 ...]
+# [--let $rpl_debug= 1]
+# --source include/rpl_restart_server.inc
+#
+# Parameters:
+#
+# $rpl_server_number, $rpl_server_parameters
+# See include/rpl_start_server.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# ==== See also ====
+#
+# rpl_start_server.inc
+# rpl_stop_server.inc
+
+
+--let $_rpl_restart_server_args= [server_number=$rpl_server_number]
+if ($rpl_server_parameters)
+{
+ --let $_rpl_restart_server_args= [server_number=$rpl_server_number parameters: $rpl_server_parameters]
+}
+--let $include_filename= rpl_restart_server.inc $_rpl_restart_server_args
+--source include/begin_include_file.inc
+
+--source include/rpl_stop_server.inc
+--source include/rpl_start_server.inc
+
+--let $include_filename= rpl_restart_server.inc $_rpl_restart_server_args
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_start_server.inc b/mysql-test/include/rpl_start_server.inc
new file mode 100644
index 00000000000..c59c7759910
--- /dev/null
+++ b/mysql-test/include/rpl_start_server.inc
@@ -0,0 +1,54 @@
+# ==== Purpose ====
+#
+# Start the server given by $rpl_server_number. This should normally
+# be invoked after rpl_stop_server.inc.
+#
+# ==== Usage ====
+#
+# --let $rpl_server_number= N
+# [--let $rpl_server_parameters= --flag1 --flag2 ...]
+# [--let $rpl_debug= 1]
+# --source include/rpl_start_server.inc
+#
+# Parameters:
+#
+# $rpl_server_number
+# Number to identify the server that needs to reconnect. 1 is the
+# master server, 2 the slave server, 3 the 3rd server, and so on.
+# Cf. include/rpl_init.inc
+#
+# $rpl_server_parameters
+# If set, extra parameters given by this variable are passed to
+# mysqld.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# ==== See also ====
+#
+# rpl_stop_server.inc
+# rpl_restart_server.inc
+
+
+--let $_rpl_start_server_command= restart
+--let $_rpl_start_server_args= [server_number=$rpl_server_number]
+if ($rpl_server_parameters)
+{
+ --let $_rpl_start_server_command= restart:$rpl_server_parameters
+ --let $_rpl_start_server_args= [server_number=$rpl_server_number parameters: $rpl_server_parameters]
+}
+
+--let $include_filename= rpl_start_server.inc $_rpl_start_server_args
+--source include/begin_include_file.inc
+
+--let $rpl_connection_name= server_$rpl_server_number
+--source include/rpl_connection.inc
+
+# Write file to make mysql-test-run.pl start up the server again
+--exec echo "$_rpl_start_server_command" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect
+
+--source include/rpl_reconnect.inc
+
+
+--let $include_filename= rpl_start_server.inc $_rpl_start_server_args
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_start_slaves.inc b/mysql-test/include/rpl_start_slaves.inc
new file mode 100644
index 00000000000..fdd90eb12c5
--- /dev/null
+++ b/mysql-test/include/rpl_start_slaves.inc
@@ -0,0 +1,32 @@
+# ==== Purpose ====
+#
+# Start all slaves configured by rpl_init.inc and wait for the slave
+# threads to start.
+#
+# Note that rpl_init.inc calls this file automatically, so you only
+# need to source this file if the slaves have stopped after that.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/rpl_start_slaves.inc
+#
+# Parameters:
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# $slave_timeout
+# Set the timeout when waiting for slave threads to stop and
+# start, respectively. See include/wait_for_slave_param.inc
+
+
+--let $include_filename= rpl_start_slaves.inc
+--source include/begin_include_file.inc
+
+--let $rpl_source_file= include/start_slave.inc
+--source include/rpl_for_each_slave.inc
+
+--let $include_filename= rpl_start_slaves.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc
new file mode 100644
index 00000000000..e1f8839dd69
--- /dev/null
+++ b/mysql-test/include/rpl_stop_server.inc
@@ -0,0 +1,63 @@
+# ==== Purpose ====
+#
+# Stop the server given by $rpl_server_number.
+#
+# ==== Usage ====
+#
+# --let $rpl_server_number= N
+# [--let $rpl_debug= 1]
+# --source include/rpl_stop_server.inc
+#
+# Parameters:
+#
+# $rpl_server_number
+# Number to identify the server that needs to reconnect. 1 is the
+# master server, 2 the slave server, 3 the 3rd server, and so on.
+# Cf. include/rpl_init.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+# ==== See also ====
+#
+# rpl_start_server.inc
+# rpl_restart_server.inc
+
+
+# Can't use begin_include_file / end_include_file because they require
+# executing on a server and the server will go down after this script.
+if (!$_include_file_depth)
+{
+ --echo include/rpl_stop_server.inc [server_number=$rpl_server_number]
+}
+--inc $_include_file_depth
+--let $_rpl_stop_server_old_connection= $CURRENT_CONNECTION
+if ($rpl_debug)
+{
+ --echo $_include_file_indent con='$CURRENT_CONNECTION' warn='$ENABLED_WARNINGS' qlog='$ENABLED_QUERY_LOG' rlog='$ENABLED_RESULT_LOG' aborterr='$ENABLED_ABORT_ON_ERROR'
+ --echo $_include_file_indent==== BEGIN include/$include_filename ====
+}
+
+
+--let $rpl_connection_name= server_$rpl_server_number
+--source include/rpl_connection.inc
+
+# Write file to make mysql-test-run.pl expect the "crash", but don't start
+# it until it's told to
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect
+
+# Send shutdown to the connected server and give
+# it 10 seconds to die before zapping it
+shutdown_server 10;
+
+--source include/wait_until_disconnected.inc
+
+
+--let $rpl_connection_name= $_rpl_stop_server_old_connection
+--source include/rpl_connection.inc
+--dec $_include_file_depth
+if ($rpl_debug)
+{
+ --echo $_include_file_indent==== END include/rpl_stop_server.inc [server_number=$rpl_server_number] ====
+ --echo $_include_file_indent con='$CURRENT_CONNECTION' warn='$ENABLED_WARNINGS' qlog='$ENABLED_QUERY_LOG' rlog='$ENABLED_RESULT_LOG' aborterr='$ENABLED_ABORT_ON_ERROR'
+}
diff --git a/mysql-test/include/rpl_stop_slaves.inc b/mysql-test/include/rpl_stop_slaves.inc
new file mode 100644
index 00000000000..2b9199739dd
--- /dev/null
+++ b/mysql-test/include/rpl_stop_slaves.inc
@@ -0,0 +1,33 @@
+# ==== Purpose ====
+#
+# Stop all slaves configured by rpl_init.inc and waits for the slave
+# threads to stop.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_only_running_threads= 1]
+# [--let $rpl_debug= 1]
+# [--let $rpl_timeout= NUMBER]
+# --source include/rpl_stop_slaves.inc
+#
+# Parameters:
+# $rpl_only_running_threads
+# See include/stop_slave.inc
+#
+# $slave_timeout
+# Set the timeout when waiting for slave threads to stop. See
+# include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= rpl_stop_slaves.inc
+--source include/begin_include_file.inc
+
+--let $rpl_source_file= include/stop_slave.inc
+--source include/rpl_for_each_slave.inc
+
+--let $include_filename= rpl_stop_slaves.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/rpl_sync.inc b/mysql-test/include/rpl_sync.inc
new file mode 100644
index 00000000000..a05bee23981
--- /dev/null
+++ b/mysql-test/include/rpl_sync.inc
@@ -0,0 +1,153 @@
+# ==== Purpose ====
+#
+# Sync all servers in an arbitrary replication topology. This works
+# only if the servers have been configured with rpl_init.inc (and
+# possibly rpl_change_topology.inc).
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_only_running_threads= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/rpl_sync.inc
+#
+# Parameters:
+# $rpl_only_running_threads
+# By default, this script assumes that both the IO thread and the
+# SQL thread are running and fails if one of them is stopped. If
+# $rpl_only_running_threads is set, this script first checks
+# which slave threads are running:
+# - If both threads are running, sync both threads with master.
+# - If only IO thread is running, sync IO thread with master.
+# - If only SQL thread is running, sync SQL thread with IO thread.
+# - If no thread is running, don't sync.
+#
+# $slave_timeout
+# Set the timeout when waiting for threads to sync. See
+# include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+#
+#
+# ==== Side effects ====
+#
+# Does not change the current connection (note that this is different
+# from mysqltest's built-in sync_slave_with_master command).
+
+
+--let $include_filename= rpl_sync.inc
+--source include/begin_include_file.inc
+
+
+# Compute $rpl_sync_chain if needed. We could have done this in
+# rpl_change_topology.inc, but instead we do it here because that
+# means we only compute $rpl_sync_chain when it is needed.
+if ($rpl_sync_chain_dirty)
+{
+ --source include/rpl_generate_sync_chain.inc
+ --let $rpl_sync_chain_dirty= 0
+}
+
+
+if ($rpl_debug)
+{
+ --echo \$rpl_sync_chain = '$rpl_sync_chain' \$rpl_only_running_threads= $rpl_only_running_threads
+}
+
+if (!$rpl_server_count_length)
+{
+ --die \$rpl_server_count_length is not set. Did you call rpl_init.inc?
+}
+
+
+--let $_rpl_i= 1
+--let $_rpl_connect= 0
+while ($_rpl_i) {
+ # $rpl_sync_chain consists of a sequence of sync chains. Each sync
+ # chain has the form:
+ #
+ # <space><server1_1><server1_2>...<server1_N>
+ #
+ # So the space character indicates that a new sync chain starts.
+ --let $_rpl_server= `SELECT TRIM(SUBSTR('$rpl_sync_chain', 1 + ($_rpl_i - 1) * $rpl_server_count_length, $rpl_server_count_length))`
+
+ if ($_rpl_server)
+ {
+ if ($rpl_debug)
+ {
+ --echo [sync server_$_rpl_prev_server -> server_$_rpl_server]
+ }
+ if ($rpl_only_running_threads)
+ {
+ --connection server_$_rpl_server
+ --let $_rpl_slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1)
+ --let $_rpl_slave_sql_running= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1)
+ if ($rpl_debug)
+ {
+ --echo Sync IO: $_rpl_slave_io_running; Sync SQL: $_rpl_slave_sql_running
+ }
+ --let $_rpl_slave_io_running= `SELECT IF('$_rpl_slave_io_running' = 'Yes', 1, '')`
+ --let $_rpl_slave_sql_running= `SELECT IF('$_rpl_slave_sql_running' = 'Yes', 1, '')`
+ if ($_rpl_slave_io_running)
+ {
+ --connection server_$_rpl_prev_server
+ if ($_rpl_slave_sql_running)
+ {
+ if ($rpl_debug)
+ {
+ --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
+ --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
+ --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ }
+ --sync_slave_with_master server_$_rpl_server
+ }
+ if (!$_rpl_slave_sql_running)
+ {
+ --let $sync_slave_connection= server_$_rpl_server
+ --source include/sync_slave_io_with_master.inc
+ }
+ }
+ if (!$_rpl_slave_io_running)
+ {
+ if ($_rpl_slave_sql_running)
+ {
+ --source include/sync_slave_sql_with_io.inc
+ }
+ }
+ }
+ if (!$rpl_only_running_threads)
+ {
+ --connection server_$_rpl_prev_server
+ if ($rpl_debug)
+ {
+ --let $_rpl_master_file= query_get_value("SHOW MASTER STATUS", File, 1)
+ --let $_rpl_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1)
+ --echo syncing master_file='$_rpl_master_file' master_pos='$_rpl_master_pos'
+ }
+ --sync_slave_with_master server_$_rpl_server
+ }
+ }
+
+ # This happens at the beginning of a new sync subchain and at the
+ # end of the full sync chain.
+ if (!$_rpl_server)
+ {
+ --inc $_rpl_i
+ --let $_rpl_server= `SELECT TRIM(SUBSTR('$rpl_sync_chain', 1 + ($_rpl_i - 1) * $rpl_server_count_length, $rpl_server_count_length))`
+
+ if (!$_rpl_server)
+ {
+ # terminate loop
+ --let $_rpl_i= -1
+ }
+ }
+
+ --let $_rpl_prev_server= $_rpl_server
+ --inc $_rpl_i
+}
+
+
+--let $include_filename= rpl_sync.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/save_master_pos.inc b/mysql-test/include/save_master_pos.inc
new file mode 100644
index 00000000000..2c176d160cc
--- /dev/null
+++ b/mysql-test/include/save_master_pos.inc
@@ -0,0 +1,33 @@
+# ==== Purpose ====
+#
+# Save the current binlog position on the master, just like the
+# built-in mysqltest command save_master_pos. The advantage of this
+# script is that the saved position is available to the test script.
+#
+#
+# ==== Usage ====
+#
+# [--let $rpl_debug= 1]
+# --source include/save_master_pos.inc
+#
+# Typically, you would use this script together with
+# include/sync_io_with_master.inc
+#
+# Parameters:
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= save_master_pos.inc
+--source include/begin_include_file.inc
+
+let $_master_file= query_get_value("SHOW MASTER STATUS", File, 1);
+let $_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1);
+
+if ($rpl_debug)
+{
+ --echo save_master_pos saved file='$_master_file', pos='$_master_pos'
+}
+
+--let $include_filename= save_master_pos.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/setup_fake_relay_log.inc b/mysql-test/include/setup_fake_relay_log.inc
index f881f3bf4e8..6c47752aabd 100644
--- a/mysql-test/include/setup_fake_relay_log.inc
+++ b/mysql-test/include/setup_fake_relay_log.inc
@@ -29,11 +29,15 @@
# Creates a binlog file and a binlog index file, and sets
# @@global.relay_log_purge=1. All this is restored when you call
# cleanup_fake_relay_log.inc.
-#
-# Enables the query log.
---disable_query_log
+--let $include_filename= setup_fake_relay_log.inc
+--source include/begin_include_file.inc
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
# Print message.
let $_fake_relay_log_printable= `SELECT REPLACE('$fake_relay_log', '$MYSQL_TEST_DIR', 'MYSQL_TEST_DIR')`;
@@ -46,22 +50,18 @@ if (`SELECT "$_sql_running" = "Yes" OR "$_io_running" = "Yes"`) {
--echo Error: Slave was running when test case sourced
--echo include/setup_fake_replication.inc
--echo Slave_IO_Running = $_io_running; Slave_SQL_Running = $_sql_running
- --echo Printing some debug info:
- SHOW SLAVE STATUS;
- SHOW MASTER STATUS;
- SHOW BINLOG EVENTS;
- SHOW PROCESSLIST;
+ --source include/show_rpl_debug_info.inc
+ --die
}
# Read server variables.
-let $MYSQLD_DATADIR= `SELECT @@datadir`;
+let $_fake_datadir= `SELECT @@datadir`;
let $_fake_filename= query_get_value(SHOW VARIABLES LIKE 'relay_log', Value, 1);
if (!$_fake_filename) {
- --echo Badly written test case: relay_log variable is empty. Please use the
- --echo server option --relay-log=FILE.
+ --die ERROR IN TEST: relay_log variable is empty. Please use the server option --relay-log=FILE.
}
-let $_fake_relay_log= $MYSQLD_DATADIR/$_fake_filename-fake.000001;
-let $_fake_relay_index= $MYSQLD_DATADIR/$_fake_filename.index;
+let $_fake_relay_log= $_fake_datadir/$_fake_filename-fake.000001;
+let $_fake_relay_index= $_fake_datadir/$_fake_filename.index;
# Need to restore relay_log_purge in cleanup_fake_relay_log.inc, since
# CHANGE MASTER modifies it (see the manual for CHANGE MASTER).
let $_fake_relay_log_purge= `SELECT @@global.relay_log_purge`;
@@ -69,24 +69,16 @@ let $_fake_relay_log_purge= `SELECT @@global.relay_log_purge`;
# Create relay log file.
copy_file $fake_relay_log $_fake_relay_log;
# Create relay log index.
+--let $write_var= $_fake_filename-fake.000001\n
+--let $write_to_file= $_fake_relay_index
+--source include/write_var_to_file.inc
-if (`SELECT LENGTH(@@secure_file_priv) > 0`)
-{
- -- let $_file_priv_dir= `SELECT @@secure_file_priv`
- -- let $_suffix= `SELECT UUID()`
- -- let $_tmp_file= $_file_priv_dir/fake-index.$_suffix
-
- -- eval select '$_fake_filename-fake.000001\n' into dumpfile '$_tmp_file'
- -- copy_file $_tmp_file $_fake_relay_index
- -- remove_file $_tmp_file
-}
-
-if (`SELECT LENGTH(@@secure_file_priv) = 0`)
-{
- -- eval select '$_fake_filename-fake.000001\n' into dumpfile '$_fake_relay_index'
-}
+# Remember old settings.
+--let $_fake_old_master_host= query_get_value(SHOW SLAVE STATUS, Master_Host, 1)
# Setup replication from existing relay log.
eval CHANGE MASTER TO MASTER_HOST='dummy.localdomain', RELAY_LOG_FILE='$_fake_filename-fake.000001', RELAY_LOG_POS=4;
---enable_query_log
+
+--let $include_filename= setup_fake_relay_log.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/show_rpl_debug_info.inc b/mysql-test/include/show_rpl_debug_info.inc
index 9944e6cd25f..0faae59d8d3 100644
--- a/mysql-test/include/show_rpl_debug_info.inc
+++ b/mysql-test/include/show_rpl_debug_info.inc
@@ -3,87 +3,104 @@
# Print status information for replication, typically used to debug
# test failures.
#
-# First, the following is printed on slave:
+# The following is printed on the current connection:
#
+# SELECT NOW()
# SHOW SLAVE STATUS
+# SHOW MASTER STATUS
# SHOW PROCESSLIST
# SHOW BINLOG EVENTS IN <binlog_name>
#
# Where <binlog_name> is the currently active binlog.
#
-# Then, the following is printed on master:
-#
-# SHOW MASTER STATUS
-# SHOW PROCESSLIST
-# SHOW BINLOG EVENTS IN <sql_binlog_name>
-# SHOW BINLOG EVENTS IN <io_binlog_name>
+# Then, the same is printed from all connections configured by
+# rpl_init.inc - i.e., on connection server_N, where
+# 1 <= N <= $rpl_server_count
#
-# Where <sql_binlog_name> is the binlog name that the slave sql thread
-# is currently reading from and <io_binlog_name> is the binlog that
-# the slave IO thread is currently reading from.
#
# ==== Usage ====
#
-# [let $master_connection= <connection>;]
-# source include/show_rpl_debug_info.inc;
+# [--let $rpl_only_current_connection= 1]
+# --source include/show_rpl_debug_info.inc
+#
+# Parameters:
+# $rpl_only_current_connection
+# By default, debug info is printed from all connections, starting
+# with the current connection. If this variable is set, debug
+# info is printed only for the current connection.
+#
+#
+# ==== Side effects ====
+#
+# Turns on enable_query_log, enable_result_log, enable_warnings,
+# horizontal_results, and enable_abort_on_error.
#
-# If $master_connection is set, debug info will be retrieved from the
-# connection named $master_connection. Otherwise, it will be
-# retrieved from the 'master' connection if the current connection is
-# 'slave'.
+# Prints non-deterministic output to the query log. This file should
+# never be called in a test that does not fail.
-let $_con= $CURRENT_CONNECTION;
---echo
---echo [on $_con]
---echo
-SELECT NOW();
---echo **** SHOW SLAVE STATUS on $_con ****
-query_vertical SHOW SLAVE STATUS;
---echo
---echo **** SHOW PROCESSLIST on $_con ****
-SHOW PROCESSLIST;
---echo
---echo **** SHOW BINLOG EVENTS on $_con ****
-let $binlog_name= query_get_value("SHOW MASTER STATUS", File, 1);
-eval SHOW BINLOG EVENTS IN '$binlog_name';
-let $_master_con= $master_connection;
-if (!$_master_con)
+--enable_query_log
+--enable_result_log
+--enable_warnings
+--disable_abort_on_error
+--horizontal_results
+
+
+--let $_rpl_old_con= $CURRENT_CONNECTION
+--let $_rpl_is_first_server= 1
+--let $_rpl_server= $rpl_server_count
+--inc $_rpl_server
+
+
+while ($_rpl_server)
{
- if (`SELECT '$_con' = 'slave'`)
- {
- let $_master_con= master;
- }
- if (!$_master_con)
+ if (!$_rpl_is_first_server)
{
- --echo Unable to determine master connection. No debug info printed for master.
- --echo Please fix the test case by setting $master_connection before sourcing
- --echo show_rpl_debug_info.inc.
+ --connection server_$_rpl_server
}
-}
-
-if ($_master_con)
-{
- let $master_binlog_name_io= query_get_value("SHOW SLAVE STATUS", Master_Log_File, 1);
- let $master_binlog_name_sql= query_get_value("SHOW SLAVE STATUS", Relay_Master_Log_File, 1);
--echo
- --echo [on $_master_con]
- connection $_master_con;
+ --echo ############################## $CURRENT_CONNECTION ##############################
+ --echo
+ --echo **** SHOW WARNINGS on $CURRENT_CONNECTION ****
+ SHOW WARNINGS;
+ --echo
+ --echo **** SELECT replication-related variables on $CURRENT_CONNECTION ****
+ SELECT NOW(), @@SERVER_ID;
+ --echo
+ --echo **** SHOW SLAVE STATUS on $CURRENT_CONNECTION ****
+ query_vertical SHOW SLAVE STATUS;
--echo
- SELECT NOW();
- --echo **** SHOW MASTER STATUS on $_master_con ****
+ --echo **** SHOW MASTER STATUS on $CURRENT_CONNECTION ****
query_vertical SHOW MASTER STATUS;
--echo
- --echo **** SHOW PROCESSLIST on $_master_con ****
+ --echo **** SHOW SLAVE HOSTS on $CURRENT_CONNECTION ****
+ query_vertical SHOW SLAVE HOSTS;
+ --echo
+ --echo **** SHOW PROCESSLIST on $CURRENT_CONNECTION ****
SHOW PROCESSLIST;
--echo
- --echo **** SHOW BINLOG EVENTS on $_master_con ****
- eval SHOW BINLOG EVENTS IN '$master_binlog_name_sql';
- if (`SELECT '$master_binlog_name_io' != '$master_binlog_name_sql'`)
+ --echo **** SHOW BINARY LOGS on $CURRENT_CONNECTION ****
+ SHOW BINARY LOGS;
+ --echo
+ --echo **** SHOW BINLOG EVENTS on $CURRENT_CONNECTION ****
+ let $binlog_name= query_get_value("SHOW MASTER STATUS", File, 1);
+ --echo binlog_name = '$binlog_name'
+ eval SHOW BINLOG EVENTS IN '$binlog_name';
+
+
+ --let $_rpl_is_first_server= 0
+ --dec $_rpl_server
+ # Don't use same connection twice.
+ if (`SELECT 'server_$_rpl_server' = '$_rpl_old_con'`)
{
- eval SHOW BINLOG EVENTS IN '$master_binlog_name_io';
+ --dec $_rpl_server
+ if ($rpl_only_current_connection)
+ {
+ --let $_rpl_server= 0
+ }
}
-
- connection $_con;
}
+
+--connection $_rpl_old_con
+--enable_abort_on_error
diff --git a/mysql-test/include/show_slave_status.inc b/mysql-test/include/show_slave_status.inc
index d66c068e19b..779de5a37f5 100644
--- a/mysql-test/include/show_slave_status.inc
+++ b/mysql-test/include/show_slave_status.inc
@@ -1,25 +1,75 @@
-# Include file to show the slave status, masking out some information
-# that varies depending on where the test is executed.
+# ==== Purpose ====
+#
+# Show selected columns of output from SHOW SLAVE STATUS.
+#
+# Note: test cases should never call SHOW SLAVE STATUS directly,
+# because that outputs more information to the query log than what is
+# needed for the property that is being tested. That would cause
+# maintenance problems, because (1) it is hard for a human to
+# understand what property is being tested; (2) the output of many of
+# the fields is non-deterministic (e.g., Slave_IO_State) or changes
+# frequently (e.g., binlog positions).
+#
+# Instead, what you want most of the time is to source one of the
+# following scripts:
+#
+# include/check_slave_no_error.inc
+# Assert that Slave_SQL_Errno = Slave_IO_Errno = 0.
+#
+# include/check_slave_is_running.inc
+# Assert that Slave_IO_Running = Slave_SQL_Running = 'Yes'.
+#
+# include/wait_for_slave_sql_error.inc
+# Wait for the SQL thread to get a given error (and assert that
+# it has this error).
+#
+# include/wait_for_slave_io_error.inc
+# Wait for the IO thread to get a given error (and assert that
+# it has this error).
+#
+# include/wait_for_slave_sql_to_stop.inc
+# include/wait_for_slave_io_to_stop.inc
+# include/wait_for_slave_to_stop.inc
+# Wait for the SQL thread, the IO thread, or both to stop (and
+# assert they stop).
+#
+# When none of the above applies, you may use this script instead.
+# However, take care so that the test never contains explicit binlog
+# coordinates. Usually you can read the binlog coordinates into a
+# variable and compare it to some other coordinates.
+#
+#
+# ==== Usage ====
+#
+# --let $status_items= Column_Name[, Column_Name[, ...]]
+# --source include/show_slave_status.inc
+#
+# Parameters:
+# $status_items
+# Set to the name of the column in the output of SHOW SLAVE STATUS
+# that you want to display. Example:
+#
+# --let $status_items= Master_SSL_Allowed
+#
+# You can show multiple columns by setting $status_items to a
+# comma-separated list. Example:
+#
+# --let $status_items= Master_Log_File, Relay_Master_Log_File
---let $_items=$status_items
+
+--let $_show_slave_status_items=$status_items
if (`SELECT "XX$status_items" = "XX"`)
{
- --die 'Variable status_items is NULL'
+ --die Bug in test case: The mysqltest variable $status_items is not set.
}
---disable_query_log
---vertical_results
-while (`SELECT "XX$_items" <> "XX"`)
+while (`SELECT "XX$_show_slave_status_items" <> "XX"`)
{
- --let $_name= `SELECT SUBSTRING_INDEX('$_items', ',', 1)`
- --let $_items= `SELECT LTRIM(SUBSTRING('$_items', LENGTH('$_name') + 2))`
-
- --let $_value= query_get_value(SHOW SLAVE STATUS, $_name, 1)
+ --let $_show_slave_status_name= `SELECT SUBSTRING_INDEX('$_show_slave_status_items', ',', 1)`
+ --let $_show_slave_status_items= `SELECT LTRIM(SUBSTRING('$_show_slave_status_items', LENGTH('$_show_slave_status_name') + 2))`
- --replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
- --eval SELECT "$_value" AS $_name
+ --let $_show_slave_status_value= query_get_value(SHOW SLAVE STATUS, $_show_slave_status_name, 1)
+ --let $_show_slave_status_value= `SELECT REPLACE("$_show_slave_status_value", '$MYSQL_TEST_DIR', 'MYSQL_TEST_DIR')`
+ --echo $_show_slave_status_name = '$_show_slave_status_value'
}
-
---horizontal_results
---enable_query_log
diff --git a/mysql-test/include/start_slave.inc b/mysql-test/include/start_slave.inc
index 78a02736de8..d01978037b4 100644
--- a/mysql-test/include/start_slave.inc
+++ b/mysql-test/include/start_slave.inc
@@ -6,16 +6,34 @@
# Please use this instead of 'START SLAVE', to reduce the risk of test
# case bugs.
#
+#
# ==== Usage ====
#
-# source include/wait_for_slave_to_start.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/start_slave.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= start_slave.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
---disable_query_log
START SLAVE;
---enable_query_log
---echo include/start_slave.inc
source include/wait_for_slave_to_start.inc;
+
+
+--let $include_filename= start_slave.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/stop_slave.inc b/mysql-test/include/stop_slave.inc
index 7161e6fe739..64cc0d5b322 100644
--- a/mysql-test/include/stop_slave.inc
+++ b/mysql-test/include/stop_slave.inc
@@ -3,19 +3,86 @@
# Issues STOP SLAVE on the current connection. Then waits until both
# the IO and SQL threads have stopped, or until a timeout is reached.
#
-# Please use this instead of 'STOP SLAVE', to reduce the risk of test
-# case bugs.
+# Please use this instead of 'STOP SLAVE', to reduce the risk of races
+# in test cases.
+#
+# This will fail if the slave IO or SQL thread has an error. If you
+# expect an error in the IO thread, use
+# include/wait_for_slave_io_error.inc and include/stop_slave_sql.inc.
+#
#
# ==== Usage ====
#
-# source include/wait_for_slave_to_start.inc;
+# [--let $rpl_only_running_threads= 1]
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/stop_slave.inc
+#
+# Parameters:
+# $rpl_only_running_threads
+# By default, this script executes STOP SLAVE unconditionally.
+# This generates a warnings if one or both slave threads are
+# already stopped. If $rpl_only_running_threads is set, this
+# script checks which slave threads are running, and issues either
+# STOP SLAVE, STOP SLAVE SQL_THREAD, STOP SLAVE IO_THREAD, or
+# nothing.
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= stop_slave.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+if ($rpl_only_running_threads)
+{
+ --let $_slave_sql_running= query_get_value(SHOW SLAVE STATUS, Slave_SQL_Running, 1)
+ --let $_slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1)
+ if ($rpl_debug)
+ {
+ --echo Stop SQL: $_slave_sql_running; Stop IO: $_slave_io_running
+ }
+
+ --let $_slave_running_bits= `SELECT IF('$_slave_io_running' = 'Yes', 1, 0) + IF('$_slave_sql_running' = 'Yes', 2, 0)`
+ if ($_slave_running_bits)
+ {
+ --dec $_slave_running_bits
+ # $_slave_running_bits=1: io thread running
+ if (!$_slave_running_bits)
+ {
+ --source include/stop_slave_io.inc
+ }
+ --dec $_slave_running_bits
+ # $_slave_running_bits=2: sql thread running
+ if (!$_slave_running_bits)
+ {
+ --source include/stop_slave_sql.inc
+ }
+ --dec $_slave_running_bits
+ # $_slave_running_bits=2: both threads running
+ if (!$_slave_running_bits)
+ {
+ STOP SLAVE;
+ --source include/wait_for_slave_to_stop.inc
+ }
+ }
+}
+if (!$rpl_only_running_threads)
+{
+ STOP SLAVE;
+ --source include/wait_for_slave_to_stop.inc
+}
+
---disable_query_log
-STOP SLAVE;
---enable_query_log
---echo include/stop_slave.inc
-source include/wait_for_slave_to_stop.inc;
+--let $include_filename= stop_slave.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/stop_slave_io.inc b/mysql-test/include/stop_slave_io.inc
new file mode 100644
index 00000000000..ddc83782311
--- /dev/null
+++ b/mysql-test/include/stop_slave_io.inc
@@ -0,0 +1,43 @@
+# ==== Purpose ====
+#
+# Issues STOP SLAVE IO_THREAD on the current connection. Then waits
+# until the IO thread has stopped, or until a timeout is reached.
+#
+# This will fail if the slave IO thread has an error. If you expect an
+# error in the IO thread, use include/wait_for_slave_io_error.inc
+# instead.
+#
+# Please use this instead of 'STOP SLAVE IO_THREAD', to reduce the
+# risk of races in test cases.
+#
+#
+# ==== Usage ====
+#
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/stop_slave_io.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= stop_slave_io.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+
+
+--let $include_filename= stop_slave_io.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/stop_slave_sql.inc b/mysql-test/include/stop_slave_sql.inc
new file mode 100644
index 00000000000..f5075b32fda
--- /dev/null
+++ b/mysql-test/include/stop_slave_sql.inc
@@ -0,0 +1,41 @@
+# ==== Purpose ====
+#
+# Issues STOP SLAVE SQL_THREAD on the current connection. Then waits
+# until the SQL thread has stopped, or until a timeout is reached.
+#
+# Please use this instead of 'STOP SLAVE SQL_THREAD', to reduce the
+# risk of races in test cases.
+#
+# This will fail if the SQL thread has an error.
+#
+#
+# ==== Usage ====
+#
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/stop_slave_sql.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= stop_slave_sql.inc
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
+
+STOP SLAVE SQL_THREAD;
+--source include/wait_for_slave_sql_to_stop.inc
+
+
+--let $include_filename= stop_slave_sql.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/sync_io_with_master.inc b/mysql-test/include/sync_io_with_master.inc
new file mode 100644
index 00000000000..34906c416f5
--- /dev/null
+++ b/mysql-test/include/sync_io_with_master.inc
@@ -0,0 +1,46 @@
+# ==== Purpose ====
+#
+# Waits until the slave IO thread on the current connection has been
+# synced up to the point saved by the last call to
+# include/save_master_pos.inc (i.e., until the IO thead has copied up
+# to the saved position). Does not wait for the SQL thread.
+#
+#
+# ==== Usage ====
+#
+# On master:
+# --source include/save_master_pos.inc
+#
+# On slave:
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/sync_slave_io_with_master.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= sync_io_with_master.inc
+--source include/begin_include_file.inc
+
+
+--let $_old_slave_error_param= $slave_error_param
+--let $slave_error_param= Last_IO_Errno
+
+--let $slave_param= Master_Log_File
+--let $slave_param_value= $_master_file
+source include/wait_for_slave_param.inc;
+
+let $slave_param= Read_Master_Log_Pos;
+let $slave_param_value= $_master_pos;
+source include/wait_for_slave_param.inc;
+
+--let $slave_error_param= $_old_slave_error_param
+
+
+--let $include_filename= sync_io_with_master.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/sync_slave_io_with_master.inc b/mysql-test/include/sync_slave_io_with_master.inc
index f7dd563039c..b1b81371c97 100644
--- a/mysql-test/include/sync_slave_io_with_master.inc
+++ b/mysql-test/include/sync_slave_io_with_master.inc
@@ -2,35 +2,49 @@
#
# Waits until the slave IO thread has been synced, i.e., all events
# have been copied over to slave. Does not care if the SQL thread is
-# in sync.
+# in sync (or even running).
#
#
# ==== Usage ====
#
-# source include/sync_slave_io_with_master.inc;
+# [--let $sync_slave_connection= <connection_name>]
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/sync_slave_io_with_master.inc
#
-# Syncs to the current position on master, as found by SHOW MASTER
-# STATUS.
+# Syncs slave to the current position on master, as found by SHOW
+# MASTER STATUS.
#
# Must be called on the master. Will change connection to the slave.
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# Parameters:
+# $sync_slave_connection
+# By default, this script switches connection to 'slave'. If
+# $sync_slave_connection is set, then '$sync_slave_connection' is
+# used instead of 'slave'.
+#
+# $slave_timeout
+# See include/wait_for_slave_param.inc.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+--let $include_filename= sync_slave_io_with_master.inc
+--source include/begin_include_file.inc
-let $_master_file= query_get_value("SHOW MASTER STATUS", File, 1);
-let $_master_pos= query_get_value("SHOW MASTER STATUS", Position, 1);
-connection slave;
+--source include/save_master_pos.inc
-let $slave_error_message= Failed while waiting for slave IO thread to sync;
+--let $rpl_connection_name= slave
+if (`SELECT '$sync_slave_connection' != ''`)
+{
+ --let $rpl_connection_name= $sync_slave_connection
+}
+--source include/rpl_connection.inc
-let $slave_param= Master_Log_File;
-let $slave_param_value= $_master_file;
-source include/wait_for_slave_param.inc;
+--source include/sync_io_with_master.inc
-let $slave_param= Read_Master_Log_Pos;
-let $slave_param_value= $_master_pos;
-source include/wait_for_slave_param.inc;
-let $slave_error_message= ;
+--let $include_filename= sync_slave_io_with_master.inc
+--let $skip_restore_connection= 1
+--source include/end_include_file.inc
diff --git a/mysql-test/include/sync_slave_sql_with_io.inc b/mysql-test/include/sync_slave_sql_with_io.inc
new file mode 100644
index 00000000000..8048f7a177c
--- /dev/null
+++ b/mysql-test/include/sync_slave_sql_with_io.inc
@@ -0,0 +1,50 @@
+# ==== Purpose ====
+#
+# Sync the slave SQL thread with the IO thread.
+#
+# ==== Usage ====
+#
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/sync_slave_sql_with_io.inc
+#
+# Parameters:
+# $slave_timeout
+# By default, the synchronization timeouts after 300 seconds. If
+# $slave_timeout is set, the synchronization timeouts after
+# $slave_timeout seconds.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= sync_slave_sql_with_io.inc
+--source include/begin_include_file.inc
+
+
+let $_slave_timeout= $slave_timeout;
+if (!$_slave_timeout)
+{
+ let $_slave_timeout= 300;
+}
+
+--let $_master_log_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1)
+--let $_master_log_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1)
+
+if ($rpl_debug)
+{
+ --echo Master_Log_File='$_master_log_file' Read_Master_Log_Pos='$_master_log_pos' \$slave_timeout='$_slave_timeout'
+}
+
+--let $_sync_slave_sql_with_io_errno= `SELECT MASTER_POS_WAIT('$_master_log_file', $_master_log_pos, $_slave_timeout)`
+if (`SELECT IFNULL($_sync_slave_sql_with_io_errno, -1) < 0`)
+{
+ --echo #### Failed to sync slave SQL thread with slave IO thread. ####
+ --echo MASTER_POS_WAIT('$_master_log_file', $_master_log_pos, $_slave_timeout) returned $_sync_slave_sql_with_io_errno
+ --source include/show_rpl_debug_info.inc
+ --die Failed to sync slave SQL thread with slave IO thread.
+}
+
+
+--let $include_filename= sync_slave_sql_with_io.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_query_to_fail.inc b/mysql-test/include/wait_for_query_to_fail.inc
new file mode 100644
index 00000000000..471813026ee
--- /dev/null
+++ b/mysql-test/include/wait_for_query_to_fail.inc
@@ -0,0 +1,25 @@
+#
+# Run a query over and over until it fails or timeout occurs
+#
+
+
+let $counter= 100;
+
+disable_abort_on_error;
+disable_query_log;
+disable_result_log;
+eval $query;
+while (!$mysql_errno)
+{
+ eval $query;
+ sleep 0.1;
+ dec $counter;
+
+ if (!$counter)
+ {
+ --die "Waited too long for query to fail";
+ }
+}
+enable_abort_on_error;
+enable_query_log;
+enable_result_log;
diff --git a/mysql-test/include/wait_for_slave_io_error.inc b/mysql-test/include/wait_for_slave_io_error.inc
index ffdcf752873..bd3468eebb6 100644
--- a/mysql-test/include/wait_for_slave_io_error.inc
+++ b/mysql-test/include/wait_for_slave_io_error.inc
@@ -4,56 +4,86 @@
# error, or until a timeout is reached. Also waits until the IO
# thread has completely stopped.
#
-# ==== Usage ====
#
-# # Wait several errors.
-# let $slave_io_errno= 1, 2, 3;
-# source include/wait_for_slave_io_error.inc;
+# ==== Usage ====
#
-# # Print error message
-# let $slave_io_errno= 1;
-# let $show_slave_io_error= 1;
-# source include/wait_for_slave_io_error.inc;
+# --let $slave_io_errno= NUMBER [, NUMBER ...]
+# [--let $show_slave_io_error= 1]
+# [--let $slave_io_error_is_nonfatal= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/wait_for_slave_io_error.inc
#
# Parameters:
+# $slave_io_errno
+# The expected IO error numbers. This can be either a single
+# number, or a comma-separated list of numbers. Examples:
+# --let $slave_io_errno= 1040, 1053, 2002, 2003, 2006, 2013
+# --let $slave_io_errno= 1045
+# (After BUG#41956 has been fixed, this will be required to be
+# symbolic names instead of numbers.)
#
-# $slave_io_errno
-# The expected IO error numbers. This is required.
-# (After BUG#41956 has been fixed, this will be required to be a
-# symbolic name instead of a numbers.)
+# $show_slave_io_error
+# If set, will print the error to the query log.
#
-# $show_slave_io_error
-# If set, will print the error to the query log.
+# $slave_io_error_is_nonfatal
+# By default, we wait for the slave IO thread to stop completely
+# (i.e., until Slave_IO_State is empty). If this variable is set,
+# then we don't wait. This is useful if the error is non-fatal
+# (e.g., temporary connection error) and does not cause the slave
+# IO thread to stop.
#
-# $slave_timeout
-# See wait_for_slave_param.inc for description.
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
-# $master_connection
-# See wait_for_slave_param.inc for description.
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_io_error.inc [errno=$slave_io_errno]
+--source include/begin_include_file.inc
-if (!$slave_io_errno) {
- --die !!!ERROR IN TEST: you must set \$slave_io_errno before sourcing wait_for_slave_io_error.inc
-}
let $old_slave_param_comparison= $slave_param_comparison;
let $slave_param= Last_IO_Errno;
let $slave_param_comparison= !=;
let $slave_param_value= 0;
-let $slave_error_message= Failed while waiting for slave to produce an error in its sql thread;
source include/wait_for_slave_param.inc;
-let $slave_error_message= ;
let $slave_param_comparison= $old_slave_param_comparison;
-let $_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Errno, 1);
-if (`SELECT $_error NOT IN ($slave_io_errno)`) {
- --echo **** Slave stopped with wrong error code: $_error (expected $slave_io_errno) ****
+let $_wfsie_errno= query_get_value(SHOW SLAVE STATUS, Last_IO_Errno, 1);
+
+if (!$slave_io_errno) {
+ --echo !!!ERROR IN TEST: you must set \$slave_io_errno before you source
+ --echo !!!wait_for_slave_sql_error.inc. The error we got this time was '$_wfsie_errno',
+ --echo !!!so you probably want to add the following line to your test case:
+ --echo !!! --let \$slave_io_errno= $_wfsie_errno
+ --die !!!ERROR IN TEST: you must set \$slave_io_errno before sourcing wait_for_slave_io_error.inc
+}
+
+if (`SELECT $_wfsie_errno NOT IN ($slave_io_errno)`) {
+ --echo **** Slave stopped with wrong error code: $_wfsie_errno (expected $slave_io_errno) ****
source include/show_rpl_debug_info.inc;
- --echo **** Slave stopped with wrong error code: $_error (expected $slave_io_errno) ****
+ --echo **** Slave stopped with wrong error code: $_wfsie_errno (expected $slave_io_errno) ****
--die Slave stopped with wrong error code
}
if ($show_slave_io_error)
{
- let $error= query_get_value("SHOW SLAVE STATUS", Last_IO_Error, 1);
- echo Last_IO_Error = $error;
+ --let $_wait_for_slave_io_error_old_status_items= $status_items
+ --let $status_items= Last_IO_Error
+ --source include/show_slave_status.inc
+ --let $status_items= $_wait_for_slave_io_error_old_status_items
+}
+
+if (!$slave_io_error_is_nonfatal)
+{
+ --let $slave_param= Slave_IO_State
+ --let $slave_param_value=
+ --source include/wait_for_slave_param.inc
}
+--let $slave_io_error_is_nonfatal= 0
+
+
+--let $include_filename= wait_for_slave_io_error.inc [errno=$slave_io_errno]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_io_to_start.inc b/mysql-test/include/wait_for_slave_io_to_start.inc
index abdc8339290..ab2ccb45007 100644
--- a/mysql-test/include/wait_for_slave_io_to_start.inc
+++ b/mysql-test/include/wait_for_slave_io_to_start.inc
@@ -4,16 +4,31 @@
# connected to the master (i.e., until SHOW SLAVE STATUS returns Yes
# in the Slave_IO_Running field), or until a timeout is reached.
#
+#
# ==== Usage ====
#
-# source include/wait_for_slave_io_to_start.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_io_to_start.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_io_to_start.inc
+--source include/begin_include_file.inc
+
let $slave_param= Slave_IO_Running;
let $slave_param_value= Yes;
-let $slave_error_message= Failed while waiting for slave IO thread to start;
+--let $slave_error_param= Last_IO_Errno
source include/wait_for_slave_param.inc;
-let $slave_error_message= ;
+--let $slave_error_param=
+
+
+--let $include_filename= wait_for_slave_io_to_start.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_io_to_stop.inc b/mysql-test/include/wait_for_slave_io_to_stop.inc
index f61b0db1ed7..d25c2ac071d 100644
--- a/mysql-test/include/wait_for_slave_io_to_stop.inc
+++ b/mysql-test/include/wait_for_slave_io_to_stop.inc
@@ -1,24 +1,40 @@
# ==== Purpose ====
#
-# Waits until the IO thread of the current connection has stopped, or
-# until a timeout is reached.
+# Waits until the IO thread of the current connection has stopped
+# gracefully.
+#
+# Note: this script will fail if the IO thread stops with an error.
+# If you expect an error in the IO thread, use
+# include/wait_for_slave_io_error.inc instead.
+#
+# This script also fails if a timeout is reached (default 300
+# seconds).
+#
#
# ==== Usage ====
#
-# source include/wait_for_slave_io_to_stop.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_io_to_stop.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc.
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_io_to_stop.inc
+--source include/begin_include_file.inc
+
+
+--let $slave_param= Slave_IO_Running
+--let $slave_param_value= No
+--let $slave_error_param= Last_IO_Errno
+--source include/wait_for_slave_param.inc
+--let $slave_error_param=
+
-# if server has not used CHANGE MASTER to initiate slave, SHOW SLAVE
-# STATUS will return an empty set.
-let $_slave_io_running= query_get_value("SHOW SLAVE STATUS", Slave_IO_Running, 1);
-if (`SELECT '$_slave_io_running' != 'No such row'`)
-{
- let $slave_param= Slave_IO_Running;
- let $slave_param_value= No;
- let $slave_error_message= Failed while waiting for slave IO thread to stop;
- source include/wait_for_slave_param.inc;
- let $slave_error_message= ;
-}
+--let $include_filename= wait_for_slave_io_to_stop.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc
index 98cd426fa11..c9660b0679d 100644
--- a/mysql-test/include/wait_for_slave_param.inc
+++ b/mysql-test/include/wait_for_slave_param.inc
@@ -3,11 +3,16 @@
# Waits until SHOW SLAVE STATUS has returned a specified value, or
# until a timeout is reached.
#
+#
# ==== Usage ====
#
-# let $slave_param= Slave_SQL_Running;
-# let $slave_param_value= No;
-# source include/slave_wait_param.inc;
+# --let $slave_param= Slave_SQL_Running
+# --let $slave_param_value= No
+# [--let $slave_param_comparison= [ < | <= | >= | > | = | != ]]
+# [--let $slave_timeout= NUMBER]
+# [--let $slave_error_param= [Slave_SQL_Errno | Slave_IO_Errno]]
+# [--let $rpl_debug= 1]
+# --source include/slave_wait_param.inc
#
# Parameters:
#
@@ -21,33 +26,35 @@
# $slave_param_value. If you want to wait until $slave_param
# becomes *unequal* to $slave_param_value, set this parameter to the
# string '!=', like this:
-# let $slave_param_comparison= !=;
+# --let $slave_param_comparison= !=
#
# $slave_timeout
# The default timeout is 5 minutes. You can change the timeout by
-# setting $slave_timeout. The unit is tenths of seconds.
+# setting $slave_timeout. The unit is seconds.
#
-# $master_connection
-# If the timeout is reached, debug info is given by calling SHOW
-# SLAVE STATUS, SHOW PROCESSLIST, and SHOW BINLOG EVENTS. Then, a
-# 'connection master' is then issued, and more debug info is given
-# by calling SHOW MASTER STATUS, SHOW PROCESSLIST, and SHOW BINLOG
-# EVENTS. If $master_connection is set, the latter three commands
-# will be issued on $master_connection instead of on the host named
-# 'master'. See also show_rpl_debug_info.inc
+# $slave_error_param
+# If set, this script will check if the column of the output from
+# SHOW SLAVE STATUS named $slave_error_param is nonzero. If it is,
+# this script will faile immediately. Typically, this should be set
+# to Last_IO_Errno or Last_SQL_Errno.
#
-# $slave_error_message
-# If set, this is printed when a timeout occurs. This is primarily
-# intended to be used by other wait_for_slave_* macros, to indicate
-# what the purpose of the wait was. (A very similar error message is
-# given by default, but the wait_for_slave_* macros use this to give
-# an error message identical to that in previous versions, so that
-# errors are easier searchable in the pushbuild history.)
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_param.inc [$slave_param]
+--source include/begin_include_file.inc
+
+
+let $_slave_timeout= $slave_timeout;
+if (!$_slave_timeout)
+{
+ let $_slave_timeout= 300;
+}
-let $_slave_timeout_counter= $slave_timeout;
-if (!$_slave_timeout_counter)
+if (`SELECT '$slave_error_param' = ''`)
{
- let $_slave_timeout_counter= 3000;
+ --let $slave_error_param= 1
}
let $_slave_param_comparison= $slave_param_comparison;
@@ -56,27 +63,57 @@ if (!$_slave_param_comparison)
let $_slave_param_comparison= =;
}
-let $_show_slave_status_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1);
-while (`SELECT NOT('$_show_slave_status_value' $_slave_param_comparison '$slave_param_value') AND $_slave_timeout_counter > 0`)
+if ($rpl_debug)
{
- dec $_slave_timeout_counter;
- if ($_slave_timeout_counter)
- {
- sleep 0.1;
- let $_show_slave_status_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1);
- }
+ --echo Waiting until '$slave_param' $_slave_param_comparison '$slave_param_value' [timeout='$_slave_timeout', \$slave_error_param='$slave_error_param']
+}
+
+--let $_slave_check_configured= query_get_value("SHOW SLAVE STATUS", Slave_IO_Running, 1)
+
+if (`SELECT '$_slave_check_configured' = 'No such row'`)
+{
+ --echo **** ERROR: SHOW SLAVE STATUS returned empty result set. Slave not configured. ****
+ --source include/show_rpl_debug_info.inc
+ --die SHOW SLAVE STATUS returned empty result set. Slave not configured.
}
-# This has to be outside the loop until BUG#41913 has been fixed
-if (!$_slave_timeout_counter)
+# mysqltest doesn't provide any better way to multiply by 10
+--let $_wait_for_slave_param_zero= 0
+--let $_slave_timeout_counter= $_slave_timeout$zero
+--let $_slave_continue= 1
+while ($_slave_continue)
{
- --echo **** ERROR: timeout after $slave_timeout seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
- if ($slave_error_message)
+ --let $_show_slave_status_value= query_get_value("SHOW SLAVE STATUS", $slave_param, 1)
+
+ # Check if an error condition is reached.
+ if (!$slave_error_param)
+ {
+ --let $_show_slave_status_error_value= query_get_value("SHOW SLAVE STATUS", $slave_error_param, 1)
+ if ($_show_slave_status_error_value)
+ {
+ --echo **** ERROR: $slave_error_param = '$_show_slave_status_error_value' while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
+ --source include/show_rpl_debug_info.inc
+ --die Error condition reached in include/wait_for_slave_param.inc
+ }
+ }
+
+ # Check if the termination condition is reached.
+ --let $_slave_continue= `SELECT NOT('$_show_slave_status_value' $_slave_param_comparison '$slave_param_value')`
+
+ # Decrease timer, and check if the timeout is reached.
+ if ($_slave_continue)
{
- --echo Message: $slave_error_message
+ --dec $_slave_timeout_counter
+ if (!$_slave_timeout_counter)
+ {
+ --echo **** ERROR: timeout after $_slave_timeout seconds while waiting for slave parameter $slave_param $_slave_param_comparison $slave_param_value ****
+ --source include/show_rpl_debug_info.inc
+ --die Timeout in include/wait_for_slave_param.inc
+ }
+ --sleep 0.1
}
- --echo Current connection is '$CURRENT_CONNECTION'
- echo Note: the following output may have changed since the failure was detected;
- source include/show_rpl_debug_info.inc;
- die;
}
+
+
+--let $include_filename= wait_for_slave_param.inc [$slave_param]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_sql_error.inc b/mysql-test/include/wait_for_slave_sql_error.inc
index 80836f908c6..80c532d6a20 100644
--- a/mysql-test/include/wait_for_slave_sql_error.inc
+++ b/mysql-test/include/wait_for_slave_sql_error.inc
@@ -6,43 +6,65 @@
#
# ==== Usage ====
#
-# source include/wait_for_slave_sql_error.inc;
+# --let $slave_sql_errno= NUMBER
+# [--let $show_slave_sql_error= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/wait_for_slave_sql_error.inc
#
# Parameters:
+# $slave_sql_errno
+# The expected SQL error number. This is required.
+# (After BUG#41956 has been fixed, this will be required to be a
+# symbolic name instead of a number.)
#
-# $slave_sql_errno
-# The expected SQL error number. This is required.
-# (After BUG#41956 has been fixed, this will be required to be a
-# symbolic name instead of a number.)
-#
-# $show_slave_sql_error
-# If set, will print the error to the query log.
+# $show_slave_sql_error
+# If set, will print the error to the query log.
#
-# $slave_timeout
-# See wait_for_slave_param.inc for description.
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
-# $master_connection
-# See wait_for_slave_param.inc for description.
+# $rpl_debug
+# See include/rpl_init.inc
-if (!$slave_sql_errno) {
- --die !!!ERROR IN TEST: you must set \$slave_sql_errno before sourcing wait_for_slave_sql_error.inc
-}
+--let $include_filename= wait_for_slave_sql_error.inc [errno=$slave_sql_errno]
+--source include/begin_include_file.inc
+
+
+# Note: here, we should not wait for Slave_SQL_Errno!=0.
+# Slave_SQL_Errno and Slave_SQL_Running are not set atomically.
+# Slave_SQL_Errno is set first, then Slave_SQL_Running. So we wait
+# until Slave_SQL_Running=No to be sure that both conditions hold.
let $slave_param= Slave_SQL_Running;
let $slave_param_value= No;
-let $slave_error_message= Failed while waiting for slave to stop the SQL thread (expecting error in the SQL thread);
source include/wait_for_slave_param.inc;
-let $_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
-if (`SELECT '$_error' != '$slave_sql_errno'`) {
- --echo **** Slave stopped with wrong error code: $_error (expected $slave_sql_errno) ****
+let $_wfsse_errno= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
+
+if (!$slave_sql_errno) {
+ --echo !!!ERROR IN TEST: you must set \$slave_sql_errno before you source
+ --echo !!!wait_for_slave_sql_error.inc. The error we got this time was '$_wfsse_errno',
+ --echo !!!so you probably want to add the following line to your test case:
+ --echo !!! --let \$slave_sql_errno= $_wfsse_errno
+ --die !!!ERROR IN TEST: you must set \$slave_sql_errno before sourcing wait_for_slave_sql_error.inc
+}
+
+if (`SELECT $_wfsse_errno NOT IN ($slave_sql_errno)`) {
+ --echo **** Slave stopped with wrong error code: $_wfsse_errno (expected $slave_sql_errno) ****
source include/show_rpl_debug_info.inc;
- --echo **** Slave stopped with wrong error code: $_error (expected $slave_sql_errno) ****
+ --echo **** Slave stopped with wrong error code: $_wfsse_errno (expected $slave_sql_errno) ****
--die Slave stopped with wrong error code
}
if ($show_slave_sql_error)
{
- let $error= query_get_value("SHOW SLAVE STATUS", Last_SQL_Error, 1);
- echo Last_SQL_Error = $error;
+ --let $_wait_for_slave_sql_error_old_status_items= $status_items
+ --let $status_items= Last_SQL_Error
+ --source include/show_slave_status.inc
+ --let $status_items= $_wait_for_slave_sql_error_old_status_items
}
+
+
+--let $include_filename= wait_for_slave_sql_error.inc [errno=$slave_sql_errno]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_sql_error_and_skip.inc b/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
index 11c02c0b490..9246c1839af 100644
--- a/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
+++ b/mysql-test/include/wait_for_slave_sql_error_and_skip.inc
@@ -5,38 +5,58 @@
#
# ==== Usage ====
#
-# let $slave_sql_error= <ERRNO>;
-# source include/wait_for_slave_sql_error_and_skip.inc;
+# --let $slave_sql_error= NUMBER
+# [--let $show_sql_error= 1]
+# [--let $slave_skip_counter= 1]
+# [--let $not_switch_connection= 1]
+# [--let $rpl_debug= 1]
+# [--let $slave_timeout= NUMBER]
+# --source include/wait_for_slave_sql_error_and_skip.inc
#
# Parameters:
#
-# $slave_sql_errno
-# The error number to wait for. This is required. (See
-# wait_for_slave_sql_error.inc)
+# $slave_sql_errno
+# The error number to wait for. This is required. (See
+# wait_for_slave_sql_error.inc)
#
-# $show_sql_error
-# If set, will print the error to the query log.
-#
-# $slave_timeout
-# See wait_for_slave_param.inc for description.
+# $show_sql_error
+# If set, will print the error to the query log.
#
-# $master_connection
-# See wait_for_slave_param.inc for description.
+# $slave_skip_counter
+# If set, skip this number of events. If not set, skip one event.
#
-# $slave_skip_counter
-# If set, skip this number of events. If not set, skip one event.
+# $not_switch_connection
+# By default, this script executes on the connection 'slave'. If
+# $not_switch_connection is set, this script executes on the current
+# connection. In any case, the original connection is restored.
#
-# $not_switch_connection If set, don't switch to slave and don't switch back
-# master.
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_sql_error_and_skip.inc [errno=$slave_sql_errno]
+--source include/begin_include_file.inc
+
+
+if (!$rpl_debug)
+{
+ --disable_query_log
+}
+
-echo --source include/wait_for_slave_sql_error_and_skip.inc;
if (!$not_switch_connection)
{
- connection slave;
+ --let $rpl_connection_name= slave
+ --source include/rpl_connection.inc
}
+
+
source include/wait_for_slave_sql_error.inc;
+
# skip the erroneous statement
if ($slave_skip_counter) {
eval SET GLOBAL SQL_SLAVE_SKIP_COUNTER= $slave_skip_counter;
@@ -45,7 +65,7 @@ if (!$slave_skip_counter) {
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
}
source include/start_slave.inc;
-if (!$not_switch_connection)
-{
- connection master;
-}
+
+
+--let $include_filename= wait_for_slave_sql_error_and_skip.inc [errno=$slave_sql_errno]
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_sql_to_start.inc b/mysql-test/include/wait_for_slave_sql_to_start.inc
index 48744f5dd13..4aea9fba569 100644
--- a/mysql-test/include/wait_for_slave_sql_to_start.inc
+++ b/mysql-test/include/wait_for_slave_sql_to_start.inc
@@ -5,13 +5,33 @@
#
# ==== Usage ====
#
-# source include/wait_for_slave_sql_to_start.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_sql_to_start.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_sql_to_start.inc
+--source include/begin_include_file.inc
+
let $slave_param= Slave_SQL_Running;
let $slave_param_value= Yes;
-let $slave_error_message= Failed while waiting for slave SQL to start;
+
+# Unfortunately, the slave sql thread sets Slave_SQL_Running=Yes
+# *before* it clears Last_SQL_Errno. So we have to allow errors in
+# the SQL thread here.
+
+#--let $slave_error_param= Last_SQL_Errno
source include/wait_for_slave_param.inc;
+#--let $slave_error_param=
+
+
+--let $include_filename= wait_for_slave_sql_to_start.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_sql_to_stop.inc b/mysql-test/include/wait_for_slave_sql_to_stop.inc
index 6992613b646..492b3237be5 100644
--- a/mysql-test/include/wait_for_slave_sql_to_stop.inc
+++ b/mysql-test/include/wait_for_slave_sql_to_stop.inc
@@ -1,24 +1,40 @@
# ==== Purpose ====
#
-# Waits the SQL thread of the current connection has stopped, or until
-# a timeout is reached.
+# Waits until the SQL thread of the current connection has stopped
+# gracefully.
+#
+# Note: this script will fail if the SQL thread stops with an error.
+# If you expect an error in the SQL thread, use
+# include/wait_for_slave_io_error.inc instead.
+#
+# This script also fails if a timeout is reached (default 300
+# seconds).
+#
#
# ==== Usage ====
#
-# source include/wait_for_slave_sql_to_stop.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_sql_to_stop.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_sql_to_stop.inc
+--source include/begin_include_file.inc
+
+
+--let $slave_param= Slave_SQL_Running
+--let $slave_param_value= No
+--let $slave_error_param= Last_SQL_Errno
+--source include/wait_for_slave_param.inc
+--let $slave_error_param=
+
-# if server has not used CHANGE MASTER to initiate slave, SHOW SLAVE
-# STATUS will return an empty set.
-let $_slave_io_running= query_get_value("SHOW SLAVE STATUS", Slave_IO_Running, 1);
-if (`SELECT '$_slave_io_running' != 'No such row'`)
-{
- let $slave_param= Slave_SQL_Running;
- let $slave_param_value= No;
- let $slave_error_message= Failed while waiting for slave SQL thread to stop;
- source include/wait_for_slave_param.inc;
- let $slave_error_message= ;
-}
+--let $include_filename= wait_for_slave_sql_to_stop.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_to_start.inc b/mysql-test/include/wait_for_slave_to_start.inc
index 567950cc6d7..a916e2ea615 100644
--- a/mysql-test/include/wait_for_slave_to_start.inc
+++ b/mysql-test/include/wait_for_slave_to_start.inc
@@ -3,22 +3,28 @@
# Waits until both the IO and SQL threads of the current connection
# have started, or until a timeout is reached.
#
+#
# ==== Usage ====
#
-# source include/wait_for_slave_to_start.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_to_start.inc
+#
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_to_start.inc
+--source include/begin_include_file.inc
-let $slave_error_message= Failed while waiting for slave to start;
-let $slave_param= Slave_IO_Running;
-let $slave_param_value= Yes;
-source include/wait_for_slave_param.inc;
+--source include/wait_for_slave_io_to_start.inc
+--source include/wait_for_slave_sql_to_start.inc
-let $slave_param= Slave_SQL_Running;
-let $slave_param_value= Yes;
-source include/wait_for_slave_param.inc;
-let $slave_error_message= ;
+--let $include_filename= wait_for_slave_to_start.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/wait_for_slave_to_stop.inc b/mysql-test/include/wait_for_slave_to_stop.inc
index 56d0e7b0c91..1bfd16067c5 100644
--- a/mysql-test/include/wait_for_slave_to_stop.inc
+++ b/mysql-test/include/wait_for_slave_to_stop.inc
@@ -1,30 +1,38 @@
# ==== Purpose ====
#
# Waits until both the IO and SQL threads of the current connection
-# have stopped, or until a timeout is reached.
+# have stopped gracefully.
+#
+# Note: this script will fail if one of the threads stops with an
+# error. If you expect an error in one of the threads, use
+# include/wait_for_slave_io_error.inc or
+# include/wait_for_slave_sql_error.inc instead.
+#
+# This script also fails if a timeout is reached (default 300
+# seconds).
+#
#
# ==== Usage ====
#
-# source include/wait_for_slave_to_stop.inc;
+# [--let $slave_timeout= NUMBER]
+# [--let $rpl_debug= 1]
+# --source include/wait_for_slave_to_stop.inc
#
-# Parameters to this macro are $slave_timeout and
-# $master_connection. See wait_for_slave_param.inc for
-# descriptions.
+# Parameters:
+# $slave_timeout
+# See include/wait_for_slave_param.inc
+#
+# $rpl_debug
+# See include/rpl_init.inc
+
+
+--let $include_filename= wait_for_slave_to_stop.inc
+--source include/begin_include_file.inc
-# if server has not used CHANGE MASTER to initiate slave, SHOW SLAVE
-# STATUS will return an empty set.
-let $_slave_io_running= query_get_value("SHOW SLAVE STATUS", Slave_IO_Running, 1);
-if (`SELECT '$_slave_io_running' != 'No such row'`)
-{
- let $slave_error_message= Failed while waiting for slave to stop;
- let $slave_param= Slave_IO_Running;
- let $slave_param_value= No;
- source include/wait_for_slave_param.inc;
+--source include/wait_for_slave_sql_to_stop.inc
+--source include/wait_for_slave_io_to_stop.inc
- let $slave_param= Slave_SQL_Running;
- let $slave_param_value= No;
- source include/wait_for_slave_param.inc;
- let $slave_error_message= ;
-}
+--let $include_filename= wait_for_slave_to_stop.inc
+--source include/end_include_file.inc
diff --git a/mysql-test/include/write_var_to_file.inc b/mysql-test/include/write_var_to_file.inc
new file mode 100644
index 00000000000..e70667634a3
--- /dev/null
+++ b/mysql-test/include/write_var_to_file.inc
@@ -0,0 +1,57 @@
+# ==== Purpose ====
+#
+# Write the contents of $write_var to file $write_to_file.
+#
+#
+# ==== Usage ====
+#
+# --let $write_var = <value>
+# --let $write_to_file = [<file>|GENERATE]
+# --source include/write_var_to_file.inc
+#
+# $write_var is evaluated in sql 'string' context, so escapes like \n
+# are interpolated.
+#
+# $write_to_file can be either a filename, or the special string
+# GENERATE. If it is GENERATE, a unique filename is generated (based
+# on UUID()). The filename is saved in $write_to_file so that it can
+# be retrieved later.
+#
+#
+# ==== Implementation ====
+#
+# We can't use mysqltest's write_file because it does not evaluate
+# variables. We can't use '--exec echo $write_var > $write_file'
+# because it will use \n\r line terminator under windows. So the only
+# working way is mysql's SELECT INTO DUMPFILE, which is subject to
+# @@secure_file_priv. That makes this more complex than you might
+# expect.
+
+if (`SELECT '$write_to_file' = ''`)
+{
+ --die You must set the mysqltest variable \$write_to_file before you source include/write_var_to_file.inc
+}
+
+if (`SELECT '$write_to_file' = 'GENERATE'`)
+{
+ --let $_wvtf_suffix= `SELECT UUID()`
+ --let $write_to_file= $MYSQLTEST_VARDIR/tmp/_var_file_$_wvtf_suffix.inc
+}
+
+--error 0,1
+--remove_file $write_to_file
+
+if (`SELECT LENGTH(@@secure_file_priv) > 0`)
+{
+ --let $_wvtf_secure_file_priv= `SELECT @@secure_file_priv`
+ --let $_wvtf_suffix= `SELECT UUID()`
+ --let $_wvtf_tmp_file= $_wvtf_secure_file_priv/_wvtf_$_wvtf_suffix
+
+ --eval SELECT '$write_var' INTO DUMPFILE '$_wvtf_tmp_file'
+ --copy_file $_wvtf_tmp_file $write_to_file
+ --remove_file $_wvtf_tmp_file
+}
+if (`SELECT LENGTH(@@secure_file_priv) = 0`)
+{
+ --eval SELECT '$write_var' INTO DUMPFILE '$write_to_file'
+}