#At file:///data0/magnus/mysql/trunk-bugfixing-wl3127/ based on revid:magnus.blaudd@strippedw81dur833h06
3388 Magnus Blåudd 2010-11-25
WL#3127 slave side TCP address binding
- Extend CHANGE MASTER with MASTER_BIND='interface'
- Extend SHOW SLAVE STATUS with a new column Master_Bind
- Add testcase
added:
mysql-test/suite/rpl/t/rpl_change_master_bind.inc
modified:
mysql-test/include/check_ipv6.inc
mysql-test/suite/rpl/r/rpl_change_master.result
mysql-test/suite/rpl/t/rpl_change_master.test
sql/lex.h
sql/rpl_mi.cc
sql/rpl_mi.h
sql/rpl_slave.cc
sql/sql_lex.h
sql/sql_yacc.yy
=== modified file 'mysql-test/include/check_ipv6.inc'
--- a/mysql-test/include/check_ipv6.inc 2009-11-23 16:38:42 +0000
+++ b/mysql-test/include/check_ipv6.inc 2010-11-25 10:40:05 +0000
@@ -1,10 +1,20 @@
-# Check if ipv6 is available. If not, server is crashing (see BUG#48915).
+# Check if ipv6 is available.
+#
+# Parameters:
+# $check_ipv6_just_check - don't skip the test if IPv6 is unsupported,
+# just set the variable $check_ipv6_supported
+#
--disable_query_log
--disable_abort_on_error
+let $check_ipv6_supported=1;
connect (checkcon123456789,::1,root,,test);
if($mysql_errno)
{
-skip wrong IP;
+ let $check_ipv6_supported=0;
+ if(!$check_ipv6_just_check)
+ {
+ skip No IPv6 support;
+ }
}
connection default;
disconnect checkcon123456789;
=== modified file 'mysql-test/suite/rpl/r/rpl_change_master.result'
--- a/mysql-test/suite/rpl/r/rpl_change_master.result 2010-11-18 15:51:24 +0000
+++ b/mysql-test/suite/rpl/r/rpl_change_master.result 2010-11-25 10:40:05 +0000
@@ -71,6 +71,34 @@ ERROR 42000: You have an error in your S
CHANGE MASTER TO master_retry_count=-1;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1' at line 1
include/start_slave.inc
+include/stop_slave.inc
+create table t1(n int, b varchar(256));
+insert into t1 values(1, <master_bind>);
+change master to master_bind=<master_bind>;
+start slave;
+drop table t1;
+include/stop_slave.inc
+create table t1(n int, b varchar(256));
+insert into t1 values(1, <master_bind>);
+change master to master_bind=<master_bind>;
+start slave;
+got expected error 2003
+include/stop_slave.inc
+change master to master_bind='';
+start slave;
+drop table t1;
+include/stop_slave.inc
+create table t1(n int, b varchar(256));
+insert into t1 values(1, <master_bind>);
+change master to master_bind=<master_bind>;
+start slave;
+drop table t1;
+include/stop_slave.inc
+create table t1(n int, b varchar(256));
+insert into t1 values(1, <master_bind>);
+change master to master_bind=<master_bind>;
+start slave;
+drop table t1;
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
=== modified file 'mysql-test/suite/rpl/t/rpl_change_master.test'
--- a/mysql-test/suite/rpl/t/rpl_change_master.test 2010-11-25 09:12:05 +0000
+++ b/mysql-test/suite/rpl/t/rpl_change_master.test 2010-11-25 10:40:05 +0000
@@ -254,5 +254,38 @@ if (`SELECT $retry_count6 <> $retry_coun
-- die
}
+#
+# WL#3127 slave side TCP address binding
+# - CHANGE MASTER ... MASTER_BIND='interface'
+# - SHOW SLAVE STATUS has new column Master_Bind
+#
+
+let $check_ipv6_just_check=1;
+source include/check_ipv6.inc;
+let $check_ipv6_just_check=0;
+
+# Test valid IPv4 address
+let $master_bind='127.0.0.1';
+--source rpl_change_master_bind.inc
+
+# Test invalid IPv4 address
+let $master_bind='1.1.1.1';
+let $master_bind_error_expected=2003;
+--source rpl_change_master_bind.inc
+let $master_bind_error_expected=0;
+
+# Test valid IPv6 address
+let $master_bind='::1';
+if (!$check_ipv6_supported)
+{
+ # No IPv6 support, fallback to IPv4
+ let $master_bind='127.0.0.1';
+}
+--source rpl_change_master_bind.inc
+
+# Test with no bind address(check that reset works)
+let $master_bind='';
+--source rpl_change_master_bind.inc
+
-- source include/master-slave-reset.inc
-- source include/master-slave-end.inc
=== added file 'mysql-test/suite/rpl/t/rpl_change_master_bind.inc'
--- a/mysql-test/suite/rpl/t/rpl_change_master_bind.inc 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_change_master_bind.inc 2010-11-25 10:40:05 +0000
@@ -0,0 +1,69 @@
+#
+# Test CHANGE MASTER MASTER_BIND=xxx
+#
+# Parameters:
+# $master_bind - the address to use for MASTER_BIND
+# $master_bind_error_expected - expect an error when using the specified
+# master_bind address
+#
+#
+
+# Stop the slave
+connection slave;
+source include/stop_slave.inc;
+
+# Create table and insert one record with the bind address on master
+connection master;
+create table t1(n int, b varchar(256));
+--replace_result $master_bind <master_bind>
+eval insert into t1 values(1, $master_bind);
+
+# Configure slave to connect to master with then give bind address
+connection slave;
+--replace_result $master_bind <master_bind>
+eval change master to master_bind=$master_bind;
+start slave;
+
+# Check that SHOW SLAVE STATUS has Master_bind column set to $master_bind
+let $master_bind_value= query_get_value(SHOW SLAVE STATUS, Master_Bind, 1);
+if (`select '$master_bind_value' != $master_bind`)
+{
+ source include/show_rpl_debug_info.inc;
+ echo 'master_bind_value: $master_bind_value' != 'master_bind: $master_bind';
+ die Master_bind in SHOW SLAVE STAUS not showing configured value;
+}
+
+if ($master_bind_error_expected)
+{
+ # The given master bind address is not valid
+ # and replication should fail
+ let $slave_io_errno= $master_bind_error_expected;
+ source include/wait_for_slave_io_error.inc;
+ echo got expected error $master_bind_error_expected;
+ source include/stop_slave.inc;
+
+ # Reset the master_bind to that cleanup can run
+ eval change master to master_bind='';
+ start slave;
+
+}
+
+source include/wait_for_slave_to_start.inc;
+
+connection master;
+sync_slave_with_master;
+
+connection slave;
+let $master_bind_repl= query_get_value(select b from t1, b, 1);
+if (`select '$master_bind_repl' != $master_bind`)
+{
+ select * from t1;
+ source include/show_rpl_debug_info.inc;
+ echo 'master_bind_repl: $master_bind_repl' != 'master_bind: $master_bind';
+ die The replicated value to show replication working was not correct;
+}
+
+# Clean up
+connection master;
+drop table t1;
+sync_slave_with_master;
=== modified file 'sql/lex.h'
--- a/sql/lex.h 2010-10-21 12:18:25 +0000
+++ b/sql/lex.h 2010-11-25 10:40:05 +0000
@@ -316,6 +316,7 @@ static SYMBOL symbols[] = {
{ "LOOP", SYM(LOOP_SYM)},
{ "LOW_PRIORITY", SYM(LOW_PRIORITY)},
{ "MASTER", SYM(MASTER_SYM)},
+ { "MASTER_BIND", SYM(MASTER_BIND_SYM)},
{ "MASTER_CONNECT_RETRY", SYM(MASTER_CONNECT_RETRY_SYM)},
{ "MASTER_DELAY", SYM(MASTER_DELAY_SYM)},
{ "MASTER_HOST", SYM(MASTER_HOST_SYM)},
=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc 2010-08-24 08:39:26 +0000
+++ b/sql/rpl_mi.cc 2010-11-25 10:40:05 +0000
@@ -89,7 +89,7 @@ Master_info::Master_info(PSI_mutex_key *
clock_diff_with_master(0), heartbeat_period(0),
received_heartbeats(0), master_id(0), retry_count(master_retry_count)
{
- host[0] = 0; user[0] = 0; password[0] = 0;
+ host[0] = 0; user[0] = 0; password[0] = 0; bind_addr[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;
@@ -371,13 +371,7 @@ bool Master_info::read_info(Rpl_info_han
*/
if (lines >= LINE_FOR_MASTER_BIND)
{
- /*
- This is a placeholder for the bind option.
- Please, update this after WL#3126 and
- WL#3127.
- */
- char fake_bind[2];
- if (from->get_info(fake_bind, sizeof(fake_bind), ""))
+ if (from->get_info(bind_addr, sizeof(bind_addr), ""))
DBUG_RETURN(TRUE);
}
@@ -447,12 +441,7 @@ bool Master_info::write_info(Rpl_info_ha
to->set_info(ssl_key) ||
to->set_info(ssl_verify_server_cert) ||
to->set_info(heartbeat_period) ||
- /*
- This is a placeholder for the bind option.
- Please, update this after WL#3126 and
- WL#3127.
- */
- to->set_info("") ||
+ to->set_info(bind_addr) ||
to->set_info(ignore_server_ids) ||
to->set_info(master_uuid) ||
to->set_info(retry_count))
=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h 2010-08-05 17:45:25 +0000
+++ b/sql/rpl_mi.h 2010-11-25 10:40:05 +0000
@@ -72,6 +72,7 @@ class Master_info : public Rpl_info
/* the variables below are needed because we can change masters on the fly */
char host[HOSTNAME_LENGTH+1];
+ char bind_addr[HOSTNAME_LENGTH+1];
char user[USERNAME_LENGTH+1];
char password[MAX_PASSWORD_LENGTH+1];
my_bool ssl; // enables use of SSL connection if true
=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc 2010-11-18 16:34:56 +0000
+++ b/sql/rpl_slave.cc 2010-11-25 10:40:05 +0000
@@ -1912,6 +1912,8 @@ bool show_master_info(THD* thd, Master_i
field_list.push_back(new Item_empty_string("Slave_SQL_Running_State", 20));
field_list.push_back(new Item_return_int("Master_Retry_Count", 10,
MYSQL_TYPE_LONGLONG));
+ field_list.push_back(new Item_empty_string("Master_Bind",
+ sizeof(mi->bind_addr)));
if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
@@ -2100,6 +2102,8 @@ bool show_master_info(THD* thd, Master_i
protocol->store(slave_sql_running_state, &my_charset_bin);
// Master_Retry_Count
protocol->store((ulonglong) mi->retry_count);
+ // Master_Bind
+ protocol->store(mi->bind_addr, &my_charset_bin);
mysql_mutex_unlock(&mi->rli->err_lock);
mysql_mutex_unlock(&mi->err_lock);
@@ -4450,6 +4454,12 @@ static int connect_to_master(THD* thd, M
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
+ if (mi->bind_addr[0])
+ {
+ DBUG_PRINT("info",("bind_addr: %s", mi->bind_addr));
+ mysql_options(mysql, MYSQL_OPT_BIND, mi->bind_addr);
+ }
+
#ifdef HAVE_OPENSSL
if (mi->ssl)
{
@@ -4576,6 +4586,12 @@ MYSQL *rpl_connect_master(MYSQL *mysql)
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout);
+ if (mi->bind_addr[0])
+ {
+ DBUG_PRINT("info",("bind_addr: %s", mi->bind_addr));
+ mysql_options(mysql, MYSQL_OPT_BIND, mi->bind_addr);
+ }
+
#ifdef HAVE_OPENSSL
if (mi->ssl)
{
@@ -5509,7 +5525,7 @@ bool change_master(THD* thd, Master_info
bool need_relay_log_purge= 1;
char *var_master_log_name= NULL, *var_group_master_log_name= NULL;
bool ret= FALSE;
- char saved_host[HOSTNAME_LENGTH + 1];
+ char saved_host[HOSTNAME_LENGTH + 1], saved_bind_addr[HOSTNAME_LENGTH + 1];
uint saved_port= 0;
char saved_log_name[FN_REFLEN];
my_off_t saved_log_pos= 0;
@@ -5558,6 +5574,7 @@ bool change_master(THD* thd, Master_info
Before processing the command, save the previous state.
*/
strmake(saved_host, mi->host, HOSTNAME_LENGTH);
+ strmake(saved_bind_addr, mi->bind_addr, HOSTNAME_LENGTH);
saved_port= mi->port;
strmake(saved_log_name, mi->get_master_log_name(), FN_REFLEN - 1);
saved_log_pos= mi->get_master_log_pos();
@@ -5591,6 +5608,8 @@ bool change_master(THD* thd, Master_info
if (lex_mi->host)
strmake(mi->host, lex_mi->host, sizeof(mi->host)-1);
+ if (lex_mi->bind_addr)
+ strmake(mi->bind_addr, lex_mi->bind_addr, sizeof(mi->bind_addr)-1);
if (lex_mi->user)
strmake(mi->user, lex_mi->user, sizeof(mi->user)-1);
if (lex_mi->password)
@@ -5773,11 +5792,12 @@ bool change_master(THD* thd, Master_info
sql_print_information("'CHANGE MASTER TO executed'. "
"Previous state master_host='%s', master_port='%u', master_log_file='%s', "
- "master_log_pos='%ld'. "
+ "master_log_pos='%ld', master_bind='%s'. "
"New state master_host='%s', master_port='%u', master_log_file='%s', "
- "master_log_pos='%ld'.", saved_host, saved_port, saved_log_name,
- (ulong) saved_log_pos, mi->host, mi->port, mi->get_master_log_name(),
- (ulong) mi->get_master_log_pos());
+ "master_log_pos='%ld', master_bind='%s'.",
+ saved_host, saved_port, saved_log_name, (ulong) saved_log_pos,
+ saved_bind_addr, mi->host, mi->port, mi->get_master_log_name(),
+ (ulong) mi->get_master_log_pos(), mi->bind_addr);
/*
If we don't write new coordinates to disk now, then old will remain in
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-11-18 16:34:56 +0000
+++ b/sql/sql_lex.h 2010-11-25 10:40:05 +0000
@@ -205,7 +205,7 @@ typedef struct st_lex_server_options
*/
typedef struct st_lex_master_info
{
- char *host, *user, *password, *log_file_name;
+ char *host, *user, *password, *log_file_name, *bind_addr;
uint port, connect_retry;
float heartbeat_period;
int sql_delay;
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2010-11-18 16:34:56 +0000
+++ b/sql/sql_yacc.yy 2010-11-25 10:40:05 +0000
@@ -1072,6 +1072,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
%token LOOP_SYM
%token LOW_PRIORITY
%token LT /* OPERATOR */
+%token MASTER_BIND_SYM
%token MASTER_CONNECT_RETRY_SYM
%token MASTER_DELAY_SYM
%token MASTER_HOST_SYM
@@ -1894,6 +1895,10 @@ master_def:
{
Lex->mi.host = $3.str;
}
+ | MASTER_BIND_SYM EQ TEXT_STRING_sys
+ {
+ Lex->mi.bind_addr = $3.str;
+ }
| MASTER_USER_SYM EQ TEXT_STRING_sys
{
Lex->mi.user = $3.str;
Attachment: [text/bzr-bundle] bzr/magnus.blaudd@oracle.com-20101125104005-s7j05q5k3uws619i.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-bugfixing branch (magnus.blaudd:3388) WL#3127 | Magnus Blåudd | 25 Nov |