2998 Li-Bing.Song@stripped 2010-06-22 [merge]
Manual merge from mysql-5.1-rep+2
added:
mysql-test/include/show_slave_hosts.inc
mysql-test/r/server_uuid.result
mysql-test/suite/rpl/r/rpl_server_uuid.result
mysql-test/suite/rpl/t/rpl_server_uuid.cnf
mysql-test/suite/rpl/t/rpl_server_uuid.test
mysql-test/suite/sys_vars/r/server_uuid_basic.result
mysql-test/suite/sys_vars/t/server_uuid_basic.test
mysql-test/t/server_uuid.test
modified:
mysql-test/include/mtr_warnings.sql
mysql-test/mysql-test-run.pl
mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result
mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result
mysql-test/suite/rpl/r/rpl_show_slave_hosts.result
mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test
mysql-test/suite/rpl/t/rpl_show_slave_hosts.test
mysys/default.c
sql/item_strfunc.h
sql/mysqld.cc
sql/mysqld.h
sql/repl_failsafe.cc
sql/rpl_mi.cc
sql/rpl_mi.h
sql/slave.cc
sql/slave.h
sql/sql_parse.cc
sql/sql_repl.cc
sql/sql_repl.h
sql/sys_vars.cc
2997 Sven Sandberg 2010-06-21 [merge]
In next-mr-rpl-bugfixing, the following things happened concurrently:
- luis merged next-mr -> next-mr-rpl-merge
- sven merged WL#344/BUG#28760 from 5.1-rep+2 -> next-mr-rpl-merge
This merge merges these two merges.
added:
mysql-test/include/ctype_ascii_order.inc
mysql-test/include/ctype_pad_space.inc
mysql-test/include/weight_string.inc
mysql-test/include/weight_string_8140.inc
mysql-test/include/weight_string_8EA1.inc
mysql-test/include/weight_string_8FA2C3.inc
mysql-test/include/weight_string_A1A1.inc
mysql-test/include/weight_string_chde.inc
mysql-test/include/weight_string_euro.inc
mysql-test/include/weight_string_l1.inc
mysql-test/include/weight_string_l12.inc
mysql-test/include/weight_string_l14.inc
mysql-test/include/weight_string_l2.inc
mysql-test/include/weight_string_l3.inc
mysql-test/include/weight_string_l4.inc
mysql-test/r/func_weight_string.result
mysql-test/t/func_weight_string.test
modified:
include/m_ctype.h
mysql-test/include/ctype_german.inc
mysql-test/r/ctype_big5.result
mysql-test/r/ctype_cp1250_ch.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_cp932_binlog_stm.result
mysql-test/r/ctype_eucjpms.result*
mysql-test/r/ctype_euckr.result
mysql-test/r/ctype_gb2312.result
mysql-test/r/ctype_gbk.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_latin1_de.result
mysql-test/r/ctype_latin2.result
mysql-test/r/ctype_latin2_ch.result
mysql-test/r/ctype_sjis.result
mysql-test/r/ctype_tis620.result
mysql-test/r/ctype_uca.result
mysql-test/r/ctype_ucs.result
mysql-test/r/ctype_ujis.result
mysql-test/r/ctype_utf16.result
mysql-test/r/ctype_utf16_uca.result
mysql-test/r/ctype_utf32.result
mysql-test/r/ctype_utf32_uca.result
mysql-test/r/ctype_utf8.result
mysql-test/r/ctype_utf8mb4.result
mysql-test/r/ctype_utf8mb4_heap.result
mysql-test/r/ctype_utf8mb4_innodb.result
mysql-test/r/ctype_utf8mb4_myisam.result
mysql-test/r/ctype_utf8mb4_ndb.result
mysql-test/r/locale.result
mysql-test/r/variables.result
mysql-test/suite/sys_vars/r/lc_time_names_basic.result
mysql-test/suite/sys_vars/t/lc_time_names_basic.test
mysql-test/t/ctype_big5.test
mysql-test/t/ctype_cp1250_ch.test
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_cp932_binlog_stm.test
mysql-test/t/ctype_eucjpms.test
mysql-test/t/ctype_euckr.test
mysql-test/t/ctype_gb2312.test
mysql-test/t/ctype_gbk.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_latin1_de.test
mysql-test/t/ctype_latin2.test
mysql-test/t/ctype_latin2_ch.test
mysql-test/t/ctype_sjis.test
mysql-test/t/ctype_tis620.test
mysql-test/t/ctype_uca.test
mysql-test/t/ctype_ucs.test
mysql-test/t/ctype_ujis.test
mysql-test/t/ctype_utf16.test
mysql-test/t/ctype_utf16_uca.test
mysql-test/t/ctype_utf32.test
mysql-test/t/ctype_utf32_uca.test
mysql-test/t/ctype_utf8.test
mysql-test/t/locale.test
mysql-test/t/variables.test
mysys/charset-def.c
mysys/charset.c
scripts/mysqld_safe.sh
sql/field.cc
sql/filesort.cc
sql/item_strfunc.cc
sql/item_strfunc.h
sql/lex.h
sql/sql_locale.cc
sql/sql_yacc.yy
storage/ndb/src/common/util/NdbSqlUtil.cpp
strings/conf_to_src.c
strings/ctype-big5.c
strings/ctype-bin.c
strings/ctype-cp932.c
strings/ctype-czech.c
strings/ctype-euc_kr.c
strings/ctype-eucjpms.c
strings/ctype-extra.c
strings/ctype-gb2312.c
strings/ctype-gbk.c
strings/ctype-latin1.c
strings/ctype-mb.c
strings/ctype-simple.c
strings/ctype-sjis.c
strings/ctype-tis620.c
strings/ctype-uca.c
strings/ctype-ucs2.c
strings/ctype-ujis.c
strings/ctype-utf8.c
strings/ctype-win1250ch.c
=== modified file 'mysql-test/include/mtr_warnings.sql'
--- a/mysql-test/include/mtr_warnings.sql 2010-04-11 07:17:42 +0000
+++ b/mysql-test/include/mtr_warnings.sql 2010-06-22 09:34:59 +0000
@@ -162,9 +162,14 @@ INSERT INTO global_suppressions VALUES
("Slave: Unknown column 'c7' in 't15' Error_code: 1054"),
("Slave: Can't DROP 'c7'.* 1091"),
("Slave: Key column 'c6'.* 1072"),
+ ("The slave I.O thread stops because a fatal error is encountered when it try to get the value of SERVER_UUID variable from master."),
+ ("init-command:'.*' failed with error:.*"),
("The slave I.O thread stops because a fatal error is encountered when it try to get the value of SERVER_ID variable from master."),
(".SELECT UNIX_TIMESTAMP... failed on master, do not trust column Seconds_Behind_Master of SHOW SLAVE STATUS"),
+ /*It will print a warning if a new UUID of server is generated.*/
+ ("It might be a maiden lunch of the server, for there is no UUID existing.*"),
+
/* Test case for Bug#31590 in order_by.test produces the following error */
("Out of sort memory; increase server sort buffer size"),
@@ -205,6 +210,7 @@ INSERT INTO global_suppressions VALUES
Transient network failures that cause warnings on reconnect.
BUG#47743 and BUG#47983.
*/
+ ("Slave I/O: Get master SERVER_UUID failed with error:.*"),
("Slave I/O: Get master SERVER_ID failed with error:.*"),
("Slave I/O: Get master clock failed with error:.*"),
("Slave I/O: Get master COLLATION_SERVER failed with error:.*"),
=== added file 'mysql-test/include/show_slave_hosts.inc'
--- a/mysql-test/include/show_slave_hosts.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/show_slave_hosts.inc 2010-04-01 11:34:04 +0000
@@ -0,0 +1,3 @@
+--replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT
+--replace_regex /[0-9, a-f]{8}-[0-9, a-f]{4}-[0-9, a-f]{4}-[0-9, a-f]{4}-[0-9, a-f]{12}/SLAVE_UUID/
+SHOW SLAVE HOSTS;
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2010-06-07 09:14:56 +0000
+++ b/mysql-test/mysql-test-run.pl 2010-06-22 09:34:59 +0000
@@ -4820,6 +4820,7 @@ sub start_servers($) {
# Save this test case information, so next can examine it
$mysqld->{'started_tinfo'}= $tinfo;
+ mtr_milli_sleep(500);
}
}
=== added file 'mysql-test/r/server_uuid.result'
--- a/mysql-test/r/server_uuid.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/server_uuid.result 2010-04-01 11:34:04 +0000
@@ -0,0 +1,19 @@
+CALL mtr.add_suppression("Master's UUID has changed, its old UUID is");
+
+# Case 1:
+# @@SERVER_UUID is readonly.
+-----------------------------------------------------------------------------
+SET GLOBAL SERVER_UUID= UUID();
+ERROR HY000: Variable 'server_uuid' is a read only variable
+
+# Case 2:
+# If the file does not exists, mysqld generates it automatically.
+-----------------------------------------------------------------------------
+
+# Case 3:
+# If there is no UUID in the file, mysqld generates it automatically.
+-----------------------------------------------------------------------------
+
+# Case 4:
+# If there is a UUID in the file, it will be loaded into SERVER_UUID.
+-----------------------------------------------------------------------------
=== modified file 'mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result'
--- a/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result 2010-06-19 09:24:34 +0000
+++ b/mysql-test/suite/rpl/r/rpl_get_master_version_and_clock.result 2010-06-22 09:34:59 +0000
@@ -24,6 +24,14 @@ slave is unblocked
SET DEBUG_SYNC='now SIGNAL signal.get_server_id';
Check network error happened here
set @@global.debug = "-d,'debug_lock.before_get_SERVER_ID'";
+stop slave;
+SET @@global.debug= "+d,'dbug.before_get_MASTER_UUID'";
+start slave;
+slave is going to hang in get_master_version_and_clock
+slave is unblocked
+SET DEBUG_SYNC='now SIGNAL signal.get_master_uuid';
+Check network error happened here
+set @@global.debug = "-d,'dbug.before_get_MASTER_UUID'";
set global debug= '';
reset master;
include/stop_slave.inc
=== modified file 'mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result'
--- a/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result 2009-10-20 06:30:15 +0000
+++ b/mysql-test/suite/rpl/r/rpl_mixed_ddl_dml.result 2010-06-22 01:41:53 +0000
@@ -12,9 +12,9 @@ n
2000
2001
2002
-show slave hosts;
-Server_id Host Port Master_id
-2 127.0.0.1 9999 1
+SHOW SLAVE HOSTS;
+Server_id Host Port Master_id Slave_UUID
+2 127.0.0.1 SLAVE_PORT 1 SLAVE_UUID
drop table t1;
stop slave;
create table t2(id int auto_increment primary key, created datetime);
=== added file 'mysql-test/suite/rpl/r/rpl_server_uuid.result'
--- a/mysql-test/suite/rpl/r/rpl_server_uuid.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_server_uuid.result 2010-06-22 09:34:59 +0000
@@ -0,0 +1,84 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CALL mtr.add_suppression(".*master and slave have equal MySQL server UUIDs.*");
+CALL mtr.add_suppression("Master's UUID has changed, its old UUID is.*");
+
+# Case 1:
+# Master's UUID appears in the result of 'SHOW SLAVE STATUS'.
+# Slave's UUID appears in the resule of 'SHOW SLAVE HOSTS'.
+-----------------------------------------------------------------------------
+SHOW SLAVE HOSTS;
+Server_id Host Port Master_id Slave_UUID
+2 127.0.0.1 SLAVE_PORT 1 SLAVE_UUID
+
+# Case 2:
+# After executing 'STOP SLAVE [IO_THREAD|SQL_THREAD]' successfully, Master's UUID
+# is still kept into Slave status.
+-----------------------------------------------------------------------------
+STOP SLAVE IO_THREAD;
+STOP SLAVE SQL_THREAD;
+include/start_slave.inc
+include/stop_slave.inc
+
+# Case 3:
+# Slave generates an errror and aborts, if master's UUID is
+# equal to slave's UUID unless --replicate-same-server-id
+# option is set.
+-----------------------------------------------------------------------------
+START SLAVE IO_THREAD;
+
+# slave2 is running with --replicate-same-server-id option
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1',
+MASTER_PORT= MASTER_PORT,
+MASTER_USER= 'root',
+MASTER_LOG_FILE='master-bin.000001';
+include/start_slave.inc
+include/stop_slave.inc
+
+# Case 4:
+# When executing 'CHANGE MASTER ...', master's UUID and server_id will be
+# cleared if master_host or/and master_port are changed.
+# Master's UUID and server_id will not be cleared if both master_port
+# and master_host are not changed.
+-----------------------------------------------------------------------------
+START SLAVE IO_THREAD;
+include/stop_slave.inc
+
+# Only change MASTER_PORT
+CHANGE MASTER TO MASTER_PORT= 1111;
+CHANGE MASTER TO MASTER_PORT= MASTER_PORT,
+MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_POS;
+START SLAVE IO_THREAD;
+
+# Only change MASTER_HOST
+STOP SLAVE IO_THREAD;
+CHANGE MASTER TO MASTER_HOST= 'localhost';
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1',
+MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_POS;
+START SLAVE IO_THREAD;
+
+# Both MASTER_HOST and MASTER_PORT are changed
+STOP SLAVE IO_THREAD;
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= 1111;
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= MASTER_PORT,
+MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_POS;
+START SLAVE IO_THREAD;
+
+# Both MASTER_HOST and MASTER_PORT are NOT changed
+STOP SLAVE IO_THREAD;
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= MASTER_PORT;
+CHANGE MASTER TO
+MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_POS;
+
+# Case 5:
+# After executing 'RESET SLAVE' successfully, Master's UUID is still kept
+# into Slave status.
+-----------------------------------------------------------------------------
+RESET SLAVE;
+CHANGE MASTER TO
+MASTER_LOG_FILE= 'MASTER_LOG_FILE', MASTER_LOG_POS= MASTER_POS;
+include/start_slave.inc
=== modified file 'mysql-test/suite/rpl/r/rpl_show_slave_hosts.result'
--- a/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result 2009-10-23 02:19:50 +0000
+++ b/mysql-test/suite/rpl/r/rpl_show_slave_hosts.result 2010-06-22 01:41:53 +0000
@@ -8,10 +8,10 @@ RESET SLAVE;
CHANGE MASTER TO master_host='127.0.0.1',master_port=MASTER_PORT,master_user='root';
START SLAVE IO_THREAD;
SHOW SLAVE HOSTS;
-Server_id Host Port Master_id
-3 slave2 DEFAULT_PORT 1
-2 SLAVE_PORT 1
+Server_id Host Port Master_id Slave_UUID
+3 slave2 DEFAULT_PORT 1 SLAVE_UUID
+2 SLAVE_PORT 1 SLAVE_UUID
STOP SLAVE IO_THREAD;
SHOW SLAVE HOSTS;
-Server_id Host Port Master_id
-2 SLAVE_PORT 1
+Server_id Host Port Master_id Slave_UUID
+2 SLAVE_PORT 1 SLAVE_UUID
=== modified file 'mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test'
--- a/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test 2010-05-26 14:34:25 +0000
+++ b/mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test 2010-06-22 09:34:59 +0000
@@ -46,9 +46,16 @@ let $dbug_sync_point= 'debug_lock.before
let $debug_sync_action= 'now SIGNAL signal.get_server_id';
source extra/rpl_tests/rpl_get_master_version_and_clock.test;
+#Test case 3: Try to get the value of the MASTER_UUID from master under network disconnection
+connection slave;
+
+let $dbug_sync_point= 'dbug.before_get_MASTER_UUID';
+let $debug_sync_action= 'now SIGNAL signal.get_master_uuid';
+source extra/rpl_tests/rpl_get_master_version_and_clock.test;
+
eval set global debug= '$debug_saved';
-#Test case 3: This test checks that the slave I/O thread refuses to start
+#Test case 4: This test checks that the slave I/O thread refuses to start
#if slave and master have the same server id.
connection slave;
reset master;
=== modified file 'mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test'
--- a/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test 2009-11-27 23:34:47 +0000
+++ b/mysql-test/suite/rpl/t/rpl_mixed_ddl_dml.test 2010-06-22 01:41:53 +0000
@@ -13,8 +13,7 @@ insert into t1 values (NULL),(NULL),(NUL
sync_slave_with_master;
select * from t1;
connection master;
---replace_result $SLAVE_MYPORT 9999
-show slave hosts;
+--source include/show_slave_hosts.inc
drop table t1;
sync_slave_with_master;
stop slave;
=== added file 'mysql-test/suite/rpl/t/rpl_server_uuid.cnf'
--- a/mysql-test/suite/rpl/t/rpl_server_uuid.cnf 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_server_uuid.cnf 2010-06-22 01:41:53 +0000
@@ -0,0 +1,8 @@
+!include ../my.cnf
+
+[mysqld.3]
+replicate-same-server-id=1
+
+[ENV]
+SLAVE_MYPORT1= @mysqld.3.port
+SLAVE_MYSOCK1= @mysqld.3.socket
=== added file 'mysql-test/suite/rpl/t/rpl_server_uuid.test'
--- a/mysql-test/suite/rpl/t/rpl_server_uuid.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_server_uuid.test 2010-06-22 09:34:59 +0000
@@ -0,0 +1,229 @@
+##############################################################################
+# WL#4677 Unique Server Ids for Replication Topology (UUIDs) #
+#
+# Master and slave exchange their UUID each other when connecting. Master's
+# UUID is set into the result of 'SHOW SLAVE STATUS' and stored into
+# master.info file. Slave's UUID appears in the result of 'SHOW SLAVE HOSTS'.
+# Slave and master cannot have the same UUID, except
+# --replicate-same-server-id is set.
+#
+##############################################################################
+--source include/master-slave.inc
+--source include/not_embedded.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+CALL mtr.add_suppression(".*master and slave have equal MySQL server UUIDs.*");
+CALL mtr.add_suppression("Master's UUID has changed, its old UUID is.*");
+
+--let $uuid_file= auto.cnf
+
+--let $master_datadir=`SELECT @@DATADIR`
+# Sync suppressions
+sync_slave_with_master;
+--let $slave_datadir=`SELECT @@DATADIR`
+
+connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT1,);
+connection slave2;
+--let $slave2_datadir=`SELECT @@DATADIR`
+
+connection master;
+--let $original_master_uuid=query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+--copy_file $master_datadir/$uuid_file $master_datadir/original_$uuid_file
+
+--echo
+--echo # Case 1:
+--echo # Master's UUID appears in the result of 'SHOW SLAVE STATUS'.
+--echo # Slave's UUID appears in the resule of 'SHOW SLAVE HOSTS'.
+--echo -----------------------------------------------------------------------------
+connection master;
+--let $master_uuid_on_master= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+--let $slave_uuid_on_master= query_get_value(SHOW SLAVE HOSTS, Slave_UUID, 1)
+
+--source include/show_slave_hosts.inc
+
+connection slave;
+--let $slave_uuid_on_slave= query_get_value(SHOW VARIABLES LIKE 'SERVER_UUID', Value, 1)
+
+--let $slave_param= Master_UUID
+--let $slave_param_value= $master_uuid_on_master
+source include/check_slave_param.inc;
+
+if (`SELECT '$slave_uuid_on_slave' <> '$slave_uuid_on_master'`)
+{
+ --echo slave_uuid_on_slave <> slave_uuid_on_master
+ --echo $slave_uuid_on_slave <> $slave_uuid_on_master
+}
+
+--echo
+--echo # Case 2:
+--echo # After executing 'STOP SLAVE [IO_THREAD|SQL_THREAD]' successfully, Master's UUID
+--echo # is still kept into Slave status.
+--echo -----------------------------------------------------------------------------
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+source include/check_slave_param.inc;
+
+STOP SLAVE SQL_THREAD;
+--source include/wait_for_slave_sql_to_stop.inc
+--source include/check_slave_param.inc
+
+--source include/start_slave.inc
+--source include/stop_slave.inc
+source include/check_slave_param.inc;
+
+--echo
+--echo # Case 3:
+--echo # Slave generates an errror and aborts, if master's UUID is
+--echo # equal to slave's UUID unless --replicate-same-server-id
+--echo # option is set.
+--echo -----------------------------------------------------------------------------
+connection master;
+# copy slave's server_properties file to master, so master will have a same
+# UUID as slave.
+--remove_file $master_datadir/$uuid_file
+--copy_file $slave_datadir/$uuid_file $master_datadir/$uuid_file
+--source include/restart_mysqld.inc
+
+connection slave;
+START SLAVE IO_THREAD;
+
+let $show_statement= SHOW SLAVE STATUS;
+--let $slave_io_errno= 1593
+--source include/wait_for_slave_io_error.inc
+
+connection master;
+--remove_file $master_datadir/$uuid_file
+--copy_file $slave2_datadir/$uuid_file $master_datadir/$uuid_file
+--source include/restart_mysqld.inc
+--let $master_log_file= query_get_value(SHOW MASTER STATUS, 'File', 1)
+--let $master_log_pos= query_get_value(SHOW MASTER STATUS, 'Position', 1)
+
+--echo
+--echo # slave2 is running with --replicate-same-server-id option
+connection slave2;
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST= '127.0.0.1',
+ MASTER_PORT= $MASTER_MYPORT,
+ MASTER_USER= 'root',
+ MASTER_LOG_FILE='master-bin.000001';
+--source include/start_slave.inc
+--source include/check_slave_no_error.inc
+
+connection master;
+sync_slave_with_master slave2;
+--source include/stop_slave.inc
+
+connection master;
+--remove_file $master_datadir/$uuid_file
+--move_file $master_datadir/original_$uuid_file $master_datadir/$uuid_file
+--source include/restart_mysqld.inc
+
+--echo
+--echo # Case 4:
+--echo # When executing 'CHANGE MASTER ...', master's UUID and server_id will be
+--echo # cleared if master_host or/and master_port are changed.
+--echo # Master's UUID and server_id will not be cleared if both master_port
+--echo # and master_host are not changed.
+--echo -----------------------------------------------------------------------------
+connection slave;
+START SLAVE IO_THREAD;
+--let $slave_param= Master_UUID
+--let $slave_param_value= $original_master_uuid
+--source include/wait_for_slave_param.inc
+
+--source include/stop_slave.inc
+
+--echo
+--echo # Only change MASTER_PORT
+let $old_master_log_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $old_master_log_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+
+CHANGE MASTER TO MASTER_PORT= 1111;
+--let $slave_param= Master_UUID
+--let $slave_param_value=
+--source include/check_slave_param.inc
+--let $slave_param= Master_Server_Id
+--let $slave_param_value= 0
+--source include/check_slave_param.inc
+
+--replace_result $old_master_log_file MASTER_LOG_FILE $MASTER_MYPORT MASTER_PORT $old_master_log_pos MASTER_POS
+eval CHANGE MASTER TO MASTER_PORT= $MASTER_MYPORT,
+ MASTER_LOG_FILE= '$old_master_log_file', MASTER_LOG_POS= $old_master_log_pos;
+START SLAVE IO_THREAD;
+--let $slave_param= Master_UUID
+--let $slave_param_value= $original_master_uuid
+--source include/wait_for_slave_param.inc
+
+--echo
+--echo # Only change MASTER_HOST
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+let $old_master_log_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1);
+let $old_master_log_pos= query_get_value(SHOW SLAVE STATUS, Read_Master_Log_Pos, 1);
+
+CHANGE MASTER TO MASTER_HOST= 'localhost';
+--let $slave_param= Master_UUID
+--let $slave_param_value=
+--source include/check_slave_param.inc
+--let $slave_param= Master_Server_Id
+--let $slave_param_value= 0
+--source include/check_slave_param.inc
+
+--replace_result $old_master_log_file MASTER_LOG_FILE $MASTER_MYPORT MASTER_PORT $old_master_log_pos MASTER_POS
+eval CHANGE MASTER TO MASTER_HOST= '127.0.0.1',
+ MASTER_LOG_FILE= '$old_master_log_file', MASTER_LOG_POS= $old_master_log_pos;
+START SLAVE IO_THREAD;
+--let $slave_param= Master_UUID
+--let $slave_param_value= $original_master_uuid
+--source include/wait_for_slave_param.inc
+
+--echo
+--echo # Both MASTER_HOST and MASTER_PORT are changed
+STOP SLAVE IO_THREAD;
+
+--source include/wait_for_slave_io_to_stop.inc
+CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= 1111;
+--let $slave_param= Master_UUID
+--let $slave_param_value=
+--source include/check_slave_param.inc
+--let $slave_param= Master_Server_Id
+--let $slave_param_value= 0
+--source include/check_slave_param.inc
+
+--replace_result $old_master_log_file MASTER_LOG_FILE $MASTER_MYPORT MASTER_PORT $old_master_log_pos MASTER_POS
+eval CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= $MASTER_MYPORT,
+ MASTER_LOG_FILE= '$old_master_log_file', MASTER_LOG_POS= $old_master_log_pos;
+START SLAVE IO_THREAD;
+--let $slave_param= Master_UUID
+--let $slave_param_value= $original_master_uuid
+--source include/wait_for_slave_param.inc
+
+--echo
+--echo # Both MASTER_HOST and MASTER_PORT are NOT changed
+STOP SLAVE IO_THREAD;
+--source include/wait_for_slave_io_to_stop.inc
+
+--replace_result $MASTER_MYPORT MASTER_PORT
+eval CHANGE MASTER TO MASTER_HOST= '127.0.0.1', MASTER_PORT= $MASTER_MYPORT;
+--source include/check_slave_param.inc
+
+--replace_result $old_master_log_file MASTER_LOG_FILE $MASTER_MYPORT MASTER_PORT $old_master_log_pos MASTER_POS
+eval CHANGE MASTER TO
+ MASTER_LOG_FILE= '$old_master_log_file', MASTER_LOG_POS= $old_master_log_pos;
+--source include/check_slave_param.inc
+
+--echo
+--echo # Case 5:
+--echo # After executing 'RESET SLAVE' successfully, Master's UUID is still kept
+--echo # into Slave status.
+--echo -----------------------------------------------------------------------------
+connection slave;
+RESET SLAVE;
+--source include/check_slave_param.inc
+
+--replace_result $old_master_log_file MASTER_LOG_FILE $MASTER_MYPORT MASTER_PORT $old_master_log_pos MASTER_POS
+eval CHANGE MASTER TO
+ MASTER_LOG_FILE= '$old_master_log_file', MASTER_LOG_POS= $old_master_log_pos;
+--source include/start_slave.inc
+--source include/master-slave-end.inc
=== modified file 'mysql-test/suite/rpl/t/rpl_show_slave_hosts.test'
--- a/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test 2009-10-23 02:19:50 +0000
+++ b/mysql-test/suite/rpl/t/rpl_show_slave_hosts.test 2010-06-22 01:41:53 +0000
@@ -25,8 +25,7 @@ let $field= Server_id;
# 3 is server_id of slave2.
let $connection= ='3';
source include/wait_show_condition.inc;
---replace_result $SLAVE_MYPORT SLAVE_PORT $DEFAULT_MASTER_PORT DEFAULT_PORT
-SHOW SLAVE HOSTS;
+source include/show_slave_hosts.inc;
connection slave2;
STOP SLAVE IO_THREAD;
@@ -41,7 +40,6 @@ let $condition= <> '3';
# knew the leave of slave2 and has unregistered it.
let $wait_for_all= 1;
source include/wait_show_condition.inc;
---replace_result $SLAVE_MYPORT SLAVE_PORT
-SHOW SLAVE HOSTS;
+source include/show_slave_hosts.inc;
source include/master-slave-end.inc;
=== added file 'mysql-test/suite/sys_vars/r/server_uuid_basic.result'
--- a/mysql-test/suite/sys_vars/r/server_uuid_basic.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/server_uuid_basic.result 2010-06-22 09:34:59 +0000
@@ -0,0 +1,53 @@
+'#---------------------BS_STVARS_004_01----------------------#'
+SELECT COUNT(@@GLOBAL.server_uuid);
+COUNT(@@GLOBAL.server_uuid)
+1
+1 Expected
+'#---------------------BS_STVARS_004_02----------------------#'
+SET @@GLOBAL.server_uuid=1;
+ERROR HY000: Variable 'server_uuid' is a read only variable
+Expected error 'Read only variable'
+SELECT COUNT(@@GLOBAL.server_uuid);
+COUNT(@@GLOBAL.server_uuid)
+1
+1 Expected
+'#---------------------BS_STVARS_004_03----------------------#'
+SELECT @@GLOBAL.server_uuid = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='server_uuid';
+@@GLOBAL.server_uuid = VARIABLE_VALUE
+1
+1 Expected
+SELECT COUNT(@@GLOBAL.server_uuid);
+COUNT(@@GLOBAL.server_uuid)
+1
+1 Expected
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='server_uuid';
+COUNT(VARIABLE_VALUE)
+1
+1 Expected
+'#---------------------BS_STVARS_004_04----------------------#'
+SELECT @@server_uuid = @@GLOBAL.datadir;
+@@server_uuid = @@GLOBAL.datadir
+0
+1 Expected
+'#---------------------BS_STVARS_004_05----------------------#'
+SELECT COUNT(@@server_uuid);
+COUNT(@@server_uuid)
+1
+1 Expected
+SELECT COUNT(@@local.server_uuid);
+ERROR HY000: Variable 'server_uuid' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@SESSION.server_uuid);
+ERROR HY000: Variable 'server_uuid' is a GLOBAL variable
+Expected error 'Variable is a GLOBAL variable'
+SELECT COUNT(@@GLOBAL.server_uuid);
+COUNT(@@GLOBAL.server_uuid)
+1
+1 Expected
+SELECT server_uuid = @@SESSION.datadir;
+ERROR 42S22: Unknown column 'server_uuid' in 'field list'
+Expected error 'Readonly variable'
=== added file 'mysql-test/suite/sys_vars/t/server_uuid_basic.test'
--- a/mysql-test/suite/sys_vars/t/server_uuid_basic.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/server_uuid_basic.test 2010-06-22 09:34:59 +0000
@@ -0,0 +1,95 @@
+
+
+################## mysql-test\t\server_uuid_basic.test ########################
+# #
+# Variable Name: server_uuid #
+# Scope: Global #
+# Access Type: Static #
+# Data Type: filename #
+# #
+# #
+# Creation Date: 2010-06-22 #
+# Author : Libing Song #
+# #
+# #
+#
+# Description:Test Cases of Static System Variable server_uuid #
+# that checks the behavior of this variable in the following ways #
+# * Value Check #
+# * Scope Check #
+# #
+# Reference: http://dev.mysql.com/doc/refman/6.0/en/ #
+# server-system-variables.html #
+# #
+###############################################################################
+
+--echo '#---------------------BS_STVARS_004_01----------------------#'
+####################################################################
+# Displaying default value #
+####################################################################
+SELECT COUNT(@@GLOBAL.server_uuid);
+--echo 1 Expected
+
+
+--echo '#---------------------BS_STVARS_004_02----------------------#'
+####################################################################
+# Check if Value can set #
+####################################################################
+
+--error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SET @@GLOBAL.server_uuid=1;
+--echo Expected error 'Read only variable'
+
+SELECT COUNT(@@GLOBAL.server_uuid);
+--echo 1 Expected
+
+
+
+
+--echo '#---------------------BS_STVARS_004_03----------------------#'
+#################################################################
+# Check if the value in GLOBAL Table matches value in variable #
+#################################################################
+
+SELECT @@GLOBAL.server_uuid = VARIABLE_VALUE
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='server_uuid';
+--echo 1 Expected
+
+SELECT COUNT(@@GLOBAL.server_uuid);
+--echo 1 Expected
+
+SELECT COUNT(VARIABLE_VALUE)
+FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
+WHERE VARIABLE_NAME='server_uuid';
+--echo 1 Expected
+
+
+
+--echo '#---------------------BS_STVARS_004_04----------------------#'
+################################################################################
+# Check if accessing variable with and without GLOBAL point to same variable #
+################################################################################
+SELECT @@server_uuid = @@GLOBAL.datadir;
+--echo 1 Expected
+
+
+
+--echo '#---------------------BS_STVARS_004_05----------------------#'
+################################################################################
+# Check if server_uuid can be accessed with and without @@ sign #
+################################################################################
+
+SELECT COUNT(@@server_uuid);
+--echo 1 Expected
+
+--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@local.server_uuid);
+--echo Expected error 'Variable is a GLOBAL variable'
+
+--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
+SELECT COUNT(@@SESSION.server_uuid);
+--echo Expected error 'Variable is a GLOBAL variable'
+
+SELECT COUNT(@@GLOBAL.server_uuid);
+--echo 1 Expected
=== added file 'mysql-test/t/server_uuid.test'
--- a/mysql-test/t/server_uuid.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/server_uuid.test 2010-06-22 09:34:59 +0000
@@ -0,0 +1,74 @@
+##############################################################################
+# WL#4677 Unique Server Ids for Replication Topology (UUIDs) #
+#
+# Each server has a UUID generated by server itself. It is stored in auto.cnf
+# in @@DATADIR directory.
+#
+# @@SERVER_UUID is a readonly system variable, it is initialized as the
+# server's UUID when starting. Users can get the server's UUID from
+# @@SERVER_UUID.
+#
+# This test case tests whether the server's UUID can be generated, stored,
+# initialized correctly.
+##############################################################################
+source include/not_embedded.inc;
+
+CALL mtr.add_suppression("Master's UUID has changed, its old UUID is");
+
+--let $uuid_file= auto.cnf
+--let $original_server_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+
+--let $datadir= query_get_value(SELECT @@DATADIR, @@DATADIR, 1)
+--copy_file $datadir/$uuid_file $datadir/original_$uuid_file
+
+--echo
+--echo # Case 1:
+--echo # @@SERVER_UUID is readonly.
+--echo -----------------------------------------------------------------------------
+--error 1238
+SET GLOBAL SERVER_UUID= UUID();
+
+--echo
+--echo # Case 2:
+--echo # If the file does not exists, mysqld generates it automatically.
+--echo -----------------------------------------------------------------------------
+--remove_file $datadir/$uuid_file
+--source include/restart_mysqld.inc
+--let $server_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+if (`SELECT '$server_uuid' = '' OR '$server_uuid' = 'NULL'`)
+{
+ --echo server's UUID is null
+}
+
+--echo
+--echo # Case 3:
+--echo # If there is no UUID in the file, mysqld generates it automatically.
+--echo -----------------------------------------------------------------------------
+
+--remove_file $datadir/$uuid_file
+# There is a blank line in the file
+--write_file $datadir/$uuid_file
+[auto]
+EOF
+--source include/restart_mysqld.inc
+
+--let $server_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+if (`SELECT '$server_uuid' = '' OR '$server_uuid' = 'NULL'`)
+{
+ --echo server's UUID is null
+}
+
+--echo
+--echo # Case 4:
+--echo # If there is a UUID in the file, it will be loaded into SERVER_UUID.
+--echo -----------------------------------------------------------------------------
+
+--remove_file $datadir/$uuid_file
+--move_file $datadir/original_$uuid_file $datadir/$uuid_file
+--source include/restart_mysqld.inc
+
+--let $server_uuid= query_get_value(SELECT @@SERVER_UUID, @@SERVER_UUID, 1)
+if (`SELECT '$server_uuid' <> '$original_server_uuid'`)
+{
+ --echo $server_uuid<> $original_server_uuid
+}
=== modified file 'mysys/default.c'
--- a/mysys/default.c 2010-03-20 09:35:40 +0000
+++ b/mysys/default.c 2010-06-22 09:34:59 +0000
@@ -458,11 +458,12 @@ int my_load_defaults(const char *conf_fi
MEM_ROOT alloc;
char *ptr,**res;
struct handle_option_ctx ctx;
- const char **dirs;
+ const char **dirs= NULL;
DBUG_ENTER("load_defaults");
init_alloc_root(&alloc,512,0);
- if ((dirs= init_default_directories(&alloc)) == NULL)
+ if (default_directories != NULL &&
+ (dirs= init_default_directories(&alloc)) == NULL)
goto err;
/*
Check if the user doesn't want any default option processing
=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h 2010-06-21 08:39:53 +0000
+++ b/sql/item_strfunc.h 2010-06-22 09:34:59 +0000
@@ -897,7 +897,6 @@ public:
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
};
-#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
class Item_func_uuid: public Item_str_func
{
public:
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2010-06-19 07:50:33 +0000
+++ b/sql/mysqld.cc 2010-06-22 09:34:59 +0000
@@ -579,6 +579,8 @@ const double log_10[] = {
time_t server_start_time, flush_status_time;
+char server_uuid[UUID_LENGTH+1];
+const char *server_uuid_ptr;
char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
char default_logfile_name[FN_REFLEN];
char *default_tz_name;
@@ -3978,6 +3980,161 @@ static void end_ssl()
#endif /* HAVE_OPENSSL */
}
+/**
+ Generate a UUID and save it into server_uuid variable.
+
+ @return Retur 0 or 1 if an error occurred.
+ */
+static int generate_server_uuid()
+{
+ THD *thd;
+ Item_func_uuid *func_uuid;
+ String uuid;
+
+ /*
+ To be able to run this from boot, we allocate a temporary THD
+ */
+ if (!(thd=new THD))
+ {
+ sql_print_error("Failed to generate a server UUID because it is failed"
+ " to allocate the THD.");
+ return 1;
+ }
+ thd->thread_stack= (char*) &thd;
+ thd->store_globals();
+ lex_start(thd);
+ func_uuid= new (thd->mem_root) Item_func_uuid();
+ func_uuid->fixed= 1;
+ func_uuid->val_str(&uuid);
+ delete thd;
+ /* Remember that we don't have a THD */
+ my_pthread_setspecific_ptr(THR_THD, 0);
+
+ strncpy(server_uuid, uuid.c_ptr(), UUID_LENGTH);
+ server_uuid[UUID_LENGTH]= '\0';
+ return 0;
+}
+
+/**
+ Save all options which was auto-generated by server-self into the given file.
+
+ @param fname The name of the file in which the auto-generated options will b
+ e saved.
+
+ @return Return 0 or 1 if an error occurred.
+ */
+int flush_auto_options(const char* fname)
+{
+ File fd;
+ IO_CACHE io_cache;
+ int result= 0;
+
+ if ((fd= my_open((const char *)fname, O_CREAT|O_RDWR, MYF(MY_WME))) < 0)
+ {
+ sql_print_error("Failed to create file(file: '%s', errno %d)", fname, my_errno);
+ return 1;
+ }
+
+ if (init_io_cache(&io_cache, fd, IO_SIZE*2, WRITE_CACHE, 0L, 0, MYF(MY_WME)))
+ {
+ sql_print_error("Failed to create a cache on (file: %s', errno %d)", fname, my_errno);
+ my_close(fd, MYF(MY_WME));
+ return 1;
+ }
+
+ my_b_seek(&io_cache, 0L);
+ my_b_printf(&io_cache, "%s\n", "[auto]");
+ my_b_printf(&io_cache, "server-uuid=%s\n", server_uuid);
+
+ if (flush_io_cache(&io_cache) || my_sync(fd, MYF(MY_WME)))
+ result= 1;
+
+ my_close(fd, MYF(MY_WME));
+ end_io_cache(&io_cache);
+ return result;
+}
+
+/**
+ File 'auto.cnf' resides in the data directory to hold values of options that
+ server evaluates itself and that needs to be durable to sustain the server
+ restart. There is only a section ['auto'] in the file. All these options are
+ in the section. Only one option exists now, it is server_uuid.
+ Note, the user may not supply any literal value to these auto-options, and
+ only allowed to trigger (re)evaluation.
+ For instance, 'server_uuid' value will be evaluated and stored if there is
+ no corresponding line in the file.
+ Because of the specifics of the auto-options, they need a seperate storage.
+ Meanwhile, it is the 'auto.cnf' that has the same structure as 'my.cnf'.
+
+ @todo consider to implement sql-query-able persistent storage by WL#5279.
+ @return Return 0 or 1 if an error occurred.
+ */
+static int init_server_auto_options()
+{
+ bool flush= false;
+ char fname[FN_REFLEN];
+ char *name= "auto";
+ const char *groups[]= {"auto", NULL};
+ char *uuid= 0;
+ my_option auto_options[]= {
+ {"server-uuid", 0, "", (uchar**) &uuid, (uchar **) &uuid,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+ };
+
+ DBUG_ENTER("init_server_auto_options");
+
+ if (NULL == fn_format(fname, "auto.cnf", mysql_data_home, "",
+ MY_UNPACK_FILENAME | MY_SAFE_PATH))
+ DBUG_RETURN(1);
+
+ /* load_defaults require argv[0] is not null */
+ char **argv= &name;
+ int argc= 1;
+ /* load all options in 'auto.cnf'. */
+ if (my_load_defaults(fname, groups, &argc, &argv, NULL))
+ DBUG_RETURN(1);
+
+ /*
+ Record the origial pointer allocated by my_load_defaults for free,
+ because argv will be changed by handle_options
+ */
+ char **old_argv= argv;
+ if (handle_options(&argc, &argv, auto_options, mysqld_get_one_option))
+ DBUG_RETURN(1);
+
+ if (uuid)
+ {
+ if (strlen(uuid) != UUID_LENGTH)
+ {
+ sql_print_error("Invalid UUID in the auto.cnf file");
+ goto err;
+ }
+ strcpy(server_uuid, uuid);
+ }
+ else
+ {
+ flush= TRUE;
+ /* server_uuid will be set in the function */
+ if (generate_server_uuid())
+ goto err;
+ sql_print_warning("It might be a maiden lunch of the server, for there is"
+ " no UUID existing. A new UUID is generated. it is %s",
+ server_uuid);
+ }
+ /*
+ The uuid has been copied to server_uuid, so the memory allocated by
+ my_load_defaults can be freed now.
+ */
+ free_defaults(old_argv);
+
+ if (flush)
+ DBUG_RETURN(flush_auto_options(fname));
+ DBUG_RETURN(0);
+err:
+ free_defaults(argv);
+ DBUG_RETURN(1);
+}
static int init_server_components()
{
@@ -4201,6 +4358,15 @@ a file name for --log-bin-index option",
if (opt_help)
unireg_abort(0);
+ /*
+ Each server should have one UUID. We will create it automatically, if it
+ does not exist.
+ */
+ if (!opt_bootstrap && init_server_auto_options())
+ {
+ sql_print_error("Initializing server's UUID failed");
+ unireg_abort(1);
+ }
/* if the errmsg.sys is not loaded, terminate to maintain behaviour */
if (!DEFAULT_ERRMSGS[0][0])
@@ -7031,6 +7197,7 @@ static int mysql_init_variables(void)
opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
key_map_full.set_all();
+ server_uuid[0]= 0;
/* Character sets */
system_charset_info= &my_charset_utf8_general_ci;
=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h 2010-05-28 05:49:57 +0000
+++ b/sql/mysqld.h 2010-06-22 09:34:59 +0000
@@ -150,6 +150,10 @@ extern char glob_hostname[FN_REFLEN], my
extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file;
extern char default_logfile_name[FN_REFLEN];
extern char log_error_file[FN_REFLEN], *opt_tc_log_file;
+/*Move UUID_LENGTH from item_strfunc.h*/
+#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
+extern char server_uuid[UUID_LENGTH+1];
+extern const char *server_uuid_ptr;
extern const double log_10[309];
extern ulonglong keybuff_size;
extern ulonglong thd_startup_options;
=== modified file 'sql/repl_failsafe.cc'
--- a/sql/repl_failsafe.cc 2010-04-01 19:34:09 +0000
+++ b/sql/repl_failsafe.cc 2010-06-22 09:34:59 +0000
@@ -710,6 +710,7 @@ bool show_slave_hosts(THD* thd)
field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Master_id", 10,
MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_empty_string("Slave_UUID", UUID_LENGTH));
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -730,6 +731,11 @@ bool show_slave_hosts(THD* thd)
}
protocol->store((uint32) si->port);
protocol->store((uint32) si->master_id);
+
+ /* get slave's UUID */
+ String slave_uuid;
+ if (get_slave_uuid(si->thd, &slave_uuid));
+ protocol->store(slave_uuid.c_ptr_safe(), &my_charset_bin);
if (protocol->write())
{
mysql_mutex_unlock(&LOCK_slave_list);
=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc 2010-06-21 12:32:29 +0000
+++ b/sql/rpl_mi.cc 2010-06-22 09:34:59 +0000
@@ -37,6 +37,7 @@ Master_info::Master_info(bool is_slave_r
host[0] = 0; user[0] = 0; password[0] = 0;
ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
ssl_cipher[0]= 0; ssl_key[0]= 0;
+ master_uuid[0]=0;
my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16);
bzero((char*) &file, sizeof(file));
@@ -130,8 +131,10 @@ enum {
LINE_FOR_MASTER_BIND = 17,
/* 6.0 added value of master_ignore_server_id */
LINE_FOR_REPLICATE_IGNORE_SERVER_IDS= 18,
+ /* 6.0 added value of master_uuid */
+ LINE_FOR_MASTER_UUID= 19,
/* Number of lines currently used when saving master info file */
- LINES_IN_MASTER_INFO= LINE_FOR_REPLICATE_IGNORE_SERVER_IDS
+ LINES_IN_MASTER_INFO= LINE_FOR_MASTER_UUID
};
int init_master_info(Master_info* mi, const char* master_info_fname,
@@ -343,6 +346,10 @@ file '%s')", mi->info_file_name);
sql_print_error("Failed to initialize master info ignore_server_ids");
goto errwithmsg;
}
+
+ if (lines >= LINE_FOR_MASTER_UUID &&
+ init_strvar_from_file(mi->master_uuid, sizeof(mi->master_uuid), &mi->file, 0))
+ goto errwithmsg;
}
#ifndef HAVE_OPENSSL
@@ -485,14 +492,14 @@ int flush_master_info(Master_info* mi,
my_sprintf(heartbeat_buf, (heartbeat_buf, "%.3f", mi->heartbeat_period));
my_b_seek(file, 0L);
my_b_printf(file,
- "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n",
+ "%u\n%s\n%s\n%s\n%s\n%s\n%d\n%d\n%d\n%s\n%s\n%s\n%s\n%s\n%d\n%s\n%s\n%s\n%s\n",
LINES_IN_MASTER_INFO,
mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user,
mi->password, mi->port, mi->connect_retry,
(int)(mi->ssl), mi->ssl_ca, mi->ssl_capath, mi->ssl_cert,
mi->ssl_cipher, mi->ssl_key, mi->ssl_verify_server_cert,
- heartbeat_buf, "", ignore_server_ids_buf);
+ heartbeat_buf, "", ignore_server_ids_buf, mi->master_uuid);
my_free(ignore_server_ids_buf, MYF(0));
err= flush_io_cache(file);
if (sync_masterinfo_period && !err &&
=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h 2010-05-18 15:35:14 +0000
+++ b/sql/rpl_mi.h 2010-06-22 09:34:59 +0000
@@ -112,6 +112,7 @@ class Master_info : public Slave_reporti
ulonglong received_heartbeats; // counter of received heartbeat events
DYNAMIC_ARRAY ignore_server_ids;
ulong master_id;
+ char master_uuid[UUID_LENGTH+1];
char info_file_name[FN_REFLEN + 128];
};
void init_master_log_pos(Master_info* mi);
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2010-06-21 12:32:29 +0000
+++ b/sql/slave.cc 2010-06-22 09:34:59 +0000
@@ -156,6 +156,8 @@ static int connect_to_master(THD* thd, M
static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed,
void* thread_killed_arg);
static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi);
+static int get_master_uuid(MYSQL *mysql, Master_info *mi);
+int io_thread_init_commands(MYSQL *mysql, Master_info *mi);
static Log_event* next_event(Relay_log_info* rli);
static int queue_event(Master_info* mi,const char* buf,ulong event_len);
static int terminate_slave_thread(THD *thd,
@@ -1180,6 +1182,139 @@ bool is_network_error(uint errorno)
return FALSE;
}
+/**
+ An auxiliary function extracts slave UUID.
+
+ @param[in] thd THD to access a user variable
+ @param[out] value String to return UUID value.
+
+ @return if success value is returned else NULL is returned.
+*/
+String *get_slave_uuid(THD *thd, String *value)
+{
+ uchar name[]= "slave_uuid";
+
+ if (value == NULL)
+ return NULL;
+ user_var_entry *entry=
+ (user_var_entry*) my_hash_search(&thd->user_vars, name, sizeof(name)-1);
+ if (entry && entry->length > 0)
+ {
+ value->copy(entry->value, entry->length, NULL);
+ return value;
+ }
+ else
+ return NULL;
+}
+
+int io_thread_init_commands(MYSQL *mysql, Master_info *mi)
+{
+ char query[256];
+ int ret= 0;
+
+ my_sprintf(query, (query, "SET @slave_uuid= '%s'", server_uuid));
+ if (mysql_real_query(mysql, query, strlen(query))
+ && !check_io_slave_killed(mi->io_thd, mi, NULL))
+ goto err;
+
+ mysql_free_result(mysql_store_result(mysql));
+ return ret;
+
+err:
+ if (mysql_errno(mysql) && is_network_error(mysql_errno(mysql)))
+ {
+ mi->report(WARNING_LEVEL, mysql_errno(mysql),
+ "init-command:'%s' failed with error: %s", mysql_error(mysql));
+ ret= 2;
+ }
+ else
+ {
+ mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
+ query);
+ ret= 1;
+ }
+ mysql_free_result(mysql_store_result(mysql));
+ return ret;
+}
+
+/**
+ Get master's uuid on connecting.
+
+ @param mysql MYSQL to request uuid from master.
+ @param mi Master_info to set master_uuid
+
+ @return 0: Success, 1: Fatal error, 2: Network error.
+*/
+static int get_master_uuid(MYSQL *mysql, Master_info *mi)
+{
+ const char *errmsg;
+ MYSQL_RES *master_res= NULL;
+ MYSQL_ROW master_row= NULL;
+ int ret= 0;
+
+ DBUG_EXECUTE_IF("dbug.before_get_MASTER_UUID",
+ {
+ const char act[]= "now wait_for signal.get_master_uuid";
+ DBUG_ASSERT(opt_debug_sync_timeout > 0);
+ DBUG_ASSERT(!debug_sync_set_action(current_thd,
+ STRING_WITH_LEN(act)));
+ };);
+
+ if (!mysql_real_query(mysql,
+ STRING_WITH_LEN("SHOW VARIABLES LIKE 'SERVER_UUID'")) &&
+ (master_res= mysql_store_result(mysql)) &&
+ (master_row= mysql_fetch_row(master_res)))
+ {
+ if (!strcmp(::server_uuid, master_row[1]) &&
+ !mi->rli.replicate_same_server_id)
+ {
+ errmsg= "The slave I/O thread stops because master and slave have equal "
+ "MySQL server UUIDs; these UUIDs must be different for "
+ "replication to work.";
+ mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
+ errmsg);
+ // Fatal error
+ ret= 1;
+ }
+ else
+ {
+ if (mi->master_uuid[0] != 0 && strcmp(mi->master_uuid, master_row[1]))
+ sql_print_warning("Master's UUID has changed, its old UUID is %s, "
+ "the new one is %s", mi->master_uuid, master_row[1]);
+ strncpy(mi->master_uuid, master_row[1], UUID_LENGTH);
+ mi->master_uuid[UUID_LENGTH]= 0;
+ }
+ }
+ else if (mysql_errno(mysql))
+ {
+ if (is_network_error(mysql_errno(mysql)))
+ {
+ mi->report(WARNING_LEVEL, mysql_errno(mysql),
+ "Get master SERVER_UUID failed with error: %s",
+ mysql_error(mysql));
+ ret= 2;
+ }
+ else
+ {
+ /* Fatal error */
+ errmsg= "The slave I/O thread stops because a fatal error is encountered "
+ "when it try to get the value of SERVER_UUID variable from master.";
+ mi->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
+ errmsg);
+ ret= 1;
+ }
+ }
+ else if (!master_row && master_res)
+ {
+ mi->report(WARNING_LEVEL, ER_UNKNOWN_SYSTEM_VARIABLE,
+ "Unknown system variable 'SERVER_UUID' on master, "
+ "maybe it is a *VERY OLD MASTER*.");
+ }
+
+ if (master_res)
+ mysql_free_result(master_res);
+ return ret;
+}
/*
Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
@@ -1806,6 +1941,7 @@ bool show_master_info(THD* thd, Master_i
FN_REFLEN));
field_list.push_back(new Item_return_int("Master_Server_Id", sizeof(ulong),
MYSQL_TYPE_LONG));
+ field_list.push_back(new Item_empty_string("Master_UUID", UUID_LENGTH));
field_list.push_back(new Item_empty_string("Master_Info_File",
sizeof(mi->info_file_name)));
field_list.push_back(new Item_return_int("SQL_Delay", 10, MYSQL_TYPE_LONG));
@@ -1959,6 +2095,7 @@ bool show_master_info(THD* thd, Master_i
}
// Master_Server_id
protocol->store((uint32) mi->master_id);
+ protocol->store(mi->master_uuid, &my_charset_bin);
// Master_Info_File
protocol->store(mi->info_file_name, &my_charset_bin);
// SQL_Delay
@@ -2938,6 +3075,11 @@ connected:
thd->slave_net = &mysql->net;
thd_proc_info(thd, "Checking master version");
ret= get_master_version_and_clock(mysql, mi);
+ if (!ret)
+ ret= get_master_uuid(mysql, mi);
+ if (!ret)
+ io_thread_init_commands(mysql, mi);
+
if (ret == 1)
/* Fatal error */
goto err;
=== modified file 'sql/slave.h'
--- a/sql/slave.h 2010-06-21 12:32:29 +0000
+++ b/sql/slave.h 2010-06-22 09:34:59 +0000
@@ -247,6 +247,7 @@ extern char *master_ssl_cipher, *master_
extern I_List<THD> threads;
+extern String *get_slave_uuid(THD *thd, String *value);
#endif /* HAVE_REPLICATION */
/* masks for start/stop operations on io and sql slave threads */
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-06-19 07:50:33 +0000
+++ b/sql/sql_parse.cc 2010-06-22 09:34:59 +0000
@@ -1284,7 +1284,7 @@ bool dispatch_command(enum enum_server_c
{
ulong pos;
ushort flags;
- uint32 slave_server_id;
+ String slave_uuid;
status_var_increment(thd->status_var.com_other);
thd->enable_slow_log= opt_log_slow_admin_statements;
@@ -1294,10 +1294,10 @@ bool dispatch_command(enum enum_server_c
/* TODO: The following has to be changed to an 8 byte integer */
pos = uint4korr(packet);
flags = uint2korr(packet + 4);
- thd->server_id=0; /* avoid suicide */
- if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
- kill_zombie_dump_threads(slave_server_id);
- thd->server_id = slave_server_id;
+ thd->server_id= uint4korr(packet+6);
+
+ get_slave_uuid(thd, &slave_uuid);
+ kill_zombie_dump_threads(&slave_uuid);
general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10,
(long) pos);
=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc 2010-06-21 12:32:29 +0000
+++ b/sql/sql_repl.cc 2010-06-22 09:34:59 +0000
@@ -1296,24 +1296,32 @@ err:
SYNOPSIS
kill_zombie_dump_threads()
- slave_server_id the slave's server id
+ slave_uuid the slave's UUID
*/
-void kill_zombie_dump_threads(uint32 slave_server_id)
+void kill_zombie_dump_threads(String *slave_uuid)
{
+ if (slave_uuid->length() == 0)
+ return;
+ DBUG_ASSERT(slave_uuid->length() == UUID_LENGTH);
+
mysql_mutex_lock(&LOCK_thread_count);
I_List_iterator<THD> it(threads);
THD *tmp;
while ((tmp=it++))
{
- if (tmp->command == COM_BINLOG_DUMP &&
- tmp->server_id == slave_server_id)
+ if (tmp != current_thd && tmp->command == COM_BINLOG_DUMP)
{
- mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
- break;
+ String tmp_uuid;
+ if (get_slave_uuid(tmp, &tmp_uuid) != NULL &&
+ !strncmp(slave_uuid->c_ptr(), tmp_uuid.c_ptr(), UUID_LENGTH))
+ {
+ mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ break;
+ }
}
}
mysql_mutex_unlock(&LOCK_thread_count);
@@ -1409,6 +1417,13 @@ bool change_master(THD* thd, Master_info
reset binlog's name to FIRST and position to 4.
*/
+ if ((lex_mi->host && strcmp(lex_mi->host, mi->host)) ||
+ (lex_mi->port && lex_mi->port != mi->port))
+ {
+ mi->master_uuid[0]= 0;
+ mi->master_id= 0;
+ }
+
if ((lex_mi->host || lex_mi->port) && !lex_mi->log_file_name && !lex_mi->pos)
{
mi->master_log_name[0] = 0;
=== modified file 'sql/sql_repl.h'
--- a/sql/sql_repl.h 2010-03-31 14:05:33 +0000
+++ b/sql/sql_repl.h 2010-06-22 09:34:59 +0000
@@ -53,7 +53,7 @@ bool log_in_use(const char* log_name);
void adjust_linfo_offsets(my_off_t purge_offset);
bool show_binlogs(THD* thd);
extern int init_master_info(Master_info* mi);
-void kill_zombie_dump_threads(uint32 slave_server_id);
+void kill_zombie_dump_threads(String *slave_uuid);
int check_binlog_magic(IO_CACHE* log, const char** errmsg);
typedef struct st_load_file_info
=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc 2010-06-10 10:32:52 +0000
+++ b/sql/sys_vars.cc 2010-06-22 09:34:59 +0000
@@ -585,6 +585,9 @@ static Sys_var_dbug Sys_dbug(
ON_CHECK(check_has_super));
#endif
+static Sys_var_charptr Sys_server_uuid("server_uuid", "UUID of the server",
+ READ_ONLY GLOBAL_VAR(server_uuid_ptr),
+ NO_CMD_LINE, IN_FS_CHARSET, DEFAULT(server_uuid));
/**
@todo
When updating myisam_delay_key_write, we should do a 'flush tables'
Attachment: [text/bzr-bundle] bzr/li-bing.song@sun.com-20100622093459-4pqujvbz5sdx9qv7.bundle
| Thread |
|---|
| • bzr push into mysql-next-mr-rpl-merge branch (Li-Bing.Song:2997 to 2998) | Li-Bing.Song | 22 Jun |