diff options
Diffstat (limited to 'mysql-test/include')
73 files changed, 3366 insertions, 858 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 c55e2937242..921484ec695 100644 --- a/mysql-test/include/cleanup_fake_relay_log.inc +++ b/mysql-test/include/cleanup_fake_relay_log.inc @@ -1,18 +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. ---disable_warnings -remove_file $_fake_relay_log; -remove_file $_fake_relay_index; ---enable_warnings --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/ctype_8bit.inc b/mysql-test/include/ctype_8bit.inc new file mode 100644 index 00000000000..7259db54d05 --- /dev/null +++ b/mysql-test/include/ctype_8bit.inc @@ -0,0 +1,46 @@ +# +# Test Unicode conversion, upper, lower +# +SELECT @@collation_connection; +CREATE TABLE t1 AS SELECT ' ' AS a LIMIT 0; +INSERT INTO t1 VALUES (0x00),(0x01),(0x02),(0x03),(0x04),(0x05),(0x06),(0x07); +INSERT INTO t1 VALUES (0x08),(0x09),(0x0A),(0x0B),(0x0C),(0x0D),(0x0E),(0x0F); +INSERT INTO t1 VALUES (0x10),(0x11),(0x12),(0x13),(0x14),(0x15),(0x16),(0x17); +INSERT INTO t1 VALUES (0x18),(0x19),(0x1A),(0x1B),(0x1C),(0x1D),(0x1E),(0x1F); +INSERT INTO t1 VALUES (0x20),(0x21),(0x22),(0x23),(0x24),(0x25),(0x26),(0x27); +INSERT INTO t1 VALUES (0x28),(0x29),(0x2A),(0x2B),(0x2C),(0x2D),(0x2E),(0x2F); +INSERT INTO t1 VALUES (0x30),(0x31),(0x32),(0x33),(0x34),(0x35),(0x36),(0x37); +INSERT INTO t1 VALUES (0x38),(0x39),(0x3A),(0x3B),(0x3C),(0x3D),(0x3E),(0x3F); +INSERT INTO t1 VALUES (0x40),(0x41),(0x42),(0x43),(0x44),(0x45),(0x46),(0x47); +INSERT INTO t1 VALUES (0x48),(0x49),(0x4A),(0x4B),(0x4C),(0x4D),(0x4E),(0x4F); +INSERT INTO t1 VALUES (0x50),(0x51),(0x52),(0x53),(0x54),(0x55),(0x56),(0x57); +INSERT INTO t1 VALUES (0x58),(0x59),(0x5A),(0x5B),(0x5C),(0x5D),(0x5E),(0x5F); +INSERT INTO t1 VALUES (0x60),(0x61),(0x62),(0x63),(0x64),(0x65),(0x66),(0x67); +INSERT INTO t1 VALUES (0x68),(0x69),(0x6A),(0x6B),(0x6C),(0x6D),(0x6E),(0x6F); +INSERT INTO t1 VALUES (0x70),(0x71),(0x72),(0x73),(0x74),(0x75),(0x76),(0x77); +INSERT INTO t1 VALUES (0x78),(0x79),(0x7A),(0x7B),(0x7C),(0x7D),(0x7E),(0x7F); +INSERT INTO t1 VALUES (0x80),(0x81),(0x82),(0x83),(0x84),(0x85),(0x86),(0x87); +INSERT INTO t1 VALUES (0x88),(0x89),(0x8A),(0x8B),(0x8C),(0x8D),(0x8E),(0x8F); +INSERT INTO t1 VALUES (0x90),(0x91),(0x92),(0x93),(0x94),(0x95),(0x96),(0x97); +INSERT INTO t1 VALUES (0x98),(0x99),(0x9A),(0x9B),(0x9C),(0x9D),(0x9E),(0x9F); +INSERT INTO t1 VALUES (0xA0),(0xA1),(0xA2),(0xA3),(0xA4),(0xA5),(0xA6),(0xA7); +INSERT INTO t1 VALUES (0xA8),(0xA9),(0xAA),(0xAB),(0xAC),(0xAD),(0xAE),(0xAF); +INSERT INTO t1 VALUES (0xB0),(0xB1),(0xB2),(0xB3),(0xB4),(0xB5),(0xB6),(0xB7); +INSERT INTO t1 VALUES (0xB8),(0xB9),(0xBA),(0xBB),(0xBC),(0xBD),(0xBE),(0xBF); +INSERT INTO t1 VALUES (0xC0),(0xC1),(0xC2),(0xC3),(0xC4),(0xC5),(0xC6),(0xC7); +INSERT INTO t1 VALUES (0xC8),(0xC9),(0xCA),(0xCB),(0xCC),(0xCD),(0xCE),(0xCF); +INSERT INTO t1 VALUES (0xD0),(0xD1),(0xD2),(0xD3),(0xD4),(0xD5),(0xD6),(0xD7); +INSERT INTO t1 VALUES (0xD8),(0xD9),(0xDA),(0xDB),(0xDC),(0xDD),(0xDE),(0xDF); +INSERT INTO t1 VALUES (0xE0),(0xE1),(0xE2),(0xE3),(0xE4),(0xE5),(0xE6),(0xE7); +INSERT INTO t1 VALUES (0xE8),(0xE9),(0xEA),(0xEB),(0xEC),(0xED),(0xEE),(0xEF); +INSERT INTO t1 VALUES (0xF0),(0xF1),(0xF2),(0xF3),(0xF4),(0xF5),(0xF6),(0xF7); +INSERT INTO t1 VALUES (0xF8),(0xF9),(0xFA),(0xFB),(0xFC),(0xFD),(0xFE),(0xFF); +SELECT + HEX(a) AS chr, + HEX(LOWER(a)) AS upper, + HEX(LOWER(a)) AS lower, + HEX(@utf8:=CONVERT(a USING utf8)) AS utf8, + HEX(@roundtrip:=CAST(@utf8 AS CHAR)) AS roundtrip, + if(a=BINARY @roundtrip,'','Round trip unsafe') AS issafe +FROM t1 ORDER BY chr; +DROP TABLE t1; 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 8a463686fdb..42a8b11740b 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 +# +# 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. # -# [master:|slave:]database.table +# $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,70 +56,138 @@ # 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; -disable_warnings; ---error 0,1 ---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_1 ---error 0,1 ---remove_file $MYSQLTEST_VARDIR/tmp/diff_table_2 -enable_warnings; - -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. + --disable_warnings + --remove_file $_dt_prev_outfile + --enable_warnings + } + --let $_dt_prev_outfile= $_dt_outfile } +--disable_warnings +--remove_file $_dt_prev_outfile +--enable_warnings -# ==== 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/get_relay_log_pos.inc b/mysql-test/include/get_relay_log_pos.inc index 61ee07fc655..93dbc7d284b 100644 --- a/mysql-test/include/get_relay_log_pos.inc +++ b/mysql-test/include/get_relay_log_pos.inc @@ -66,5 +66,11 @@ let $relay_log_pos= `SELECT SUBSTRING(a.c2, 5) FROM events_at a, events_pos b WHERE a.c1=b.c1+1 and b.c2 LIKE '% $master_log_pos%'`; DROP TEMPORARY TABLE mysqlbinlog_events, events_at, events_pos; + +if (!$relay_log_pos) +{ + --echo 'Failed to read from relay_log_file: $relay_log_file pos: $master_log_pos' + --die 'variable $relay_log_pos is null' +} --remove_file $_tmp_file --enable_query_log diff --git a/mysql-test/include/have_innodb.inc b/mysql-test/include/have_innodb.inc index c3c8b5cc4f2..fa3e586834c 100644 --- a/mysql-test/include/have_innodb.inc +++ b/mysql-test/include/have_innodb.inc @@ -1,5 +1,4 @@ -if (!`SELECT count(*) FROM information_schema.engines WHERE - (support = 'YES' OR support = 'DEFAULT') AND - engine = 'innodb'`){ - skip Needs innodb engine; +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/have_ndb.inc b/mysql-test/include/have_ndb.inc index cfc5b5d0ff8..1266f80c8cd 100644 --- a/mysql-test/include/have_ndb.inc +++ b/mysql-test/include/have_ndb.inc @@ -1,10 +1,2 @@ # Check that server is compiled and started with support for NDB -#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; -# always make sure we have both mysql servers started ok before test starts -# there are some initial startup bugs that are avoided by doing this, avoiding sporadic -# failures in mysql-test-run --source include/have_multi_ndb.inc diff --git a/mysql-test/include/io_thd_fault_injection.inc b/mysql-test/include/io_thd_fault_injection.inc new file mode 100644 index 00000000000..7cbe055dbf6 --- /dev/null +++ b/mysql-test/include/io_thd_fault_injection.inc @@ -0,0 +1,21 @@ +# +# Takes the flag as an argument: +# -- let $io_thd_injection_fault_flag=+d,fault_injection_new_file_rotate_event +# -- source include/io_thd_fault_injection.inc +# + +SET @old_debug=@@global.debug; +-- disable_warnings +-- source include/stop_slave.inc +-- enable_warnings +-- eval SET GLOBAL debug="+d,$io_thd_injection_fault_flag" + +START SLAVE io_thread; +-- 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 +--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 798b0774849..a5654d3596c 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -59,13 +59,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 0f363ff1ee3..7cb9c7994d8 100644 --- a/mysql-test/include/restart_mysqld.inc +++ b/mysql-test/include/restart_mysqld.inc @@ -1,18 +1,24 @@ +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 ---write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -wait -EOF +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect +--exec echo "wait" > $_expect_file_name # Send shutdown to the connected server and give # it 10 seconds to die before zapping it shutdown_server 10; # Write file to make mysql-test-run.pl start up the server again ---append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect -restart -EOF +--exec echo "restart" > $_expect_file_name # Turn on reconnect --enable_reconnect 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' +} |