summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <sasha@mysql.sashanet.com>2001-01-17 05:47:33 -0700
committerunknown <sasha@mysql.sashanet.com>2001-01-17 05:47:33 -0700
commit4ac091636b0f366282a8a1c2ad2ff448a5c4a6f8 (patch)
tree6d77ea3fb9cae4b29069ce7d9ad832a29cd4e0b3
parent22f568dc0d8e27442b1c0b2c5a0b6bf35c88401c (diff)
downloadmariadb-git-4ac091636b0f366282a8a1c2ad2ff448a5c4a6f8.tar.gz
rpl000016.test sync
rpl000001.result BitKeeper file /home/sasha/src/bk/mysql/mysql-test/r/rpl000001.result ignore Added BitKeeper/tmp/bkr3sAHD to the ignore list slave.h MASTER_POS_WAIT lex.h MASTER_POS_WAIT slave.cc MASTER_POS_WAIT, do automagic restart on debugging abort, skip rotate events in slave.cc debug abort count sql_repl.cc announce the log name at the start of the log with a fake rotate event item_create.h MASTER_POS_WAIT item_func.cc MASTER_POS_WAIT item_func.h MASTER_POS_WAIT sql_class.h enter_cond(), exit_cond() helper inliners item_create.cc added MASTER_POS_WAIT mysql-test-run.sh speed improvement fixes rpl000007.test sync rpl000003.test sleep -> sync rpl000004.test sleep -> sync, fixed clean up bug rpl000014.test sync rpl000009.test sync rpl000013.test sync rpl000001.test sleep -> sync rpl000008.test sync rpl000006.test sync on cleanup rpl000011.test sync rpl000012.test sync rpl000005.test sleep -> sync rpl000010.test sync rpl000015.test sync rpl000002.test sleep -> sync rpl000014.result we now know the master log name as soon as we connect mysql.cc added optional agrument to --wait mysqltest.c added save_master_pos and sync_with_master commands client/mysql.cc: added optional agrument to --wait client/mysqltest.c: added save_master_pos and sync_with_master commands mysql-test/mysql-test-run.sh: speed improvement fixes mysql-test/r/rpl000014.result: we now know the master log name as soon as we connect mysql-test/t/rpl000001.test: sleep -> sync mysql-test/t/rpl000002.test: sleep -> sync mysql-test/t/rpl000003.test: sleep -> sync mysql-test/t/rpl000004.test: sleep -> sync, fixed clean up bug mysql-test/t/rpl000005.test: sleep -> sync mysql-test/t/rpl000006.test: sync on cleanup mysql-test/t/rpl000007.test: sync mysql-test/t/rpl000008.test: sync mysql-test/t/rpl000009.test: sync mysql-test/t/rpl000010.test: sync mysql-test/t/rpl000011.test: sync mysql-test/t/rpl000012.test: sync mysql-test/t/rpl000013.test: sync mysql-test/t/rpl000014.test: sync mysql-test/t/rpl000015.test: sync BitKeeper/etc/ignore: Added BitKeeper/tmp/bkr3sAHD to the ignore list mysql-test/t/rpl000016.test: sync sql/item_create.cc: added MASTER_POS_WAIT sql/item_create.h: MASTER_POS_WAIT sql/item_func.cc: MASTER_POS_WAIT sql/item_func.h: MASTER_POS_WAIT sql/lex.h: MASTER_POS_WAIT sql/slave.cc: MASTER_POS_WAIT, do automagic restart on debugging abort, skip rotate events in debug abort count sql/slave.h: MASTER_POS_WAIT sql/sql_class.h: enter_cond(), exit_cond() helper inliners sql/sql_repl.cc: announce the log name at the start of the log with a fake rotate event
-rw-r--r--.bzrignore1
-rw-r--r--client/mysql.cc12
-rw-r--r--client/mysqltest.c60
-rw-r--r--mysql-test/mysql-test-run.sh16
-rw-r--r--mysql-test/r/rpl000001.result5
-rw-r--r--mysql-test/r/rpl000014.result8
-rw-r--r--mysql-test/t/rpl000001.test11
-rw-r--r--mysql-test/t/rpl000002.test7
-rw-r--r--mysql-test/t/rpl000003.test7
-rw-r--r--mysql-test/t/rpl000004.test7
-rw-r--r--mysql-test/t/rpl000005.test6
-rw-r--r--mysql-test/t/rpl000006.test3
-rw-r--r--mysql-test/t/rpl000007.test6
-rw-r--r--mysql-test/t/rpl000008.test7
-rw-r--r--mysql-test/t/rpl000009.test11
-rw-r--r--mysql-test/t/rpl000010.test6
-rw-r--r--mysql-test/t/rpl000011.test9
-rw-r--r--mysql-test/t/rpl000012.test9
-rw-r--r--mysql-test/t/rpl000013.test20
-rw-r--r--mysql-test/t/rpl000014.test10
-rw-r--r--mysql-test/t/rpl000015.test7
-rw-r--r--mysql-test/t/rpl000016.test9
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc23
-rw-r--r--sql/item_func.h12
-rw-r--r--sql/lex.h2
-rw-r--r--sql/slave.cc58
-rw-r--r--sql/slave.h6
-rw-r--r--sql/sql_class.h19
-rw-r--r--sql/sql_repl.cc74
31 files changed, 362 insertions, 75 deletions
diff --git a/.bzrignore b/.bzrignore
index 9b2e3387390..8fac7c488a0 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -188,3 +188,4 @@ Docs/my_sys.doc
tmp/*
extra/resolve_stack_dump
sql/share/*.sys
+BitKeeper/tmp/bkr3sAHD
diff --git a/client/mysql.cc b/client/mysql.cc
index edc2f7903df..695d11d039c 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -125,6 +125,7 @@ static char *current_host,*current_db,*current_user=0,*opt_password=0,
*default_charset;
static char *histfile;
static String glob_buffer,old_buffer;
+static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char default_pager[FN_REFLEN];
@@ -427,7 +428,7 @@ static struct option long_options[] =
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{"vertical", no_argument, 0, 'E'},
- {"wait", no_argument, 0, 'w'},
+ {"wait", optional_argument, 0, 'w'},
{0, 0, 0, 0}
};
@@ -560,7 +561,7 @@ static int get_options(int argc, char **argv)
set_all_changeable_vars(changeable_vars);
while ((c=getopt_long(argc,argv,
- "?ABCD:LfgGHinNoqrstTU::vVwWEe:h:O:P:S:u:#::p::",
+ "?ABCD:LfgGHinNoqrstTU::vVw::WEe:h:O:P:S:u:#::p::",
long_options, &option_index)) != EOF)
{
switch(c) {
@@ -664,7 +665,10 @@ static int get_options(int argc, char **argv)
case 'n': unbuffered=1; break;
case 'v': verbose++; break;
case 'E': vertical=1; break;
- case 'w': wait_flag=1; break;
+ case 'w':
+ wait_flag=1;
+ if(optarg) wait_time = atoi(optarg) ;
+ break;
case 'A': no_rehash=1; break;
case 'G': no_named_cmds=0; break;
case 'g': no_named_cmds=1; break;
@@ -2114,7 +2118,7 @@ sql_connect(char *host,char *database,char *user,char *password,uint silent)
message=1;
tee_fputs("Waiting",stderr); (void) fflush(stderr);
}
- (void) sleep(5);
+ (void) sleep(wait_time);
if (!silent)
{
putc('.',stderr); (void) fflush(stderr);
diff --git a/client/mysqltest.c b/client/mysqltest.c
index d2efead3413..e9fc6a07961 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -91,6 +91,12 @@ int *cur_block, *block_stack_end;
DYNAMIC_ARRAY q_lines;
+typedef struct
+{
+ char file[FN_REFLEN];
+ ulong pos;
+} MASTER_POS ;
+
struct connection
{
MYSQL mysql;
@@ -104,6 +110,7 @@ typedef
} PARSER;
PARSER parser;
+MASTER_POS master_pos;
int block_ok = 1; /* set to 0 if the current block should not be executed */
int false_block_depth = 0;
const char* result_file = 0; /* if set, all results are concated and
@@ -137,13 +144,15 @@ struct st_query
enum { Q_CONNECTION=1, Q_QUERY, Q_CONNECT,
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
- Q_SYSTEM, Q_RESULT, Q_REQUIRE,
+ Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_SAVE_MASTER_POS,
+ Q_SYNC_WITH_MASTER,
Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type;
};
const char *command_names[] = {
"connection", "query","connect","sleep","inc","dec","source","disconnect",
-"let","echo","while","end","system","result", "require",0
+"let","echo","while","end","system","result", "require", "save_master_pos",
+ "sync_with_master", 0
};
TYPELIB command_typelib= {array_elements(command_names),"",
@@ -471,6 +480,50 @@ int do_echo(struct st_query* q)
return 0;
}
+int do_sync_with_master()
+{
+ MYSQL_RES* res;
+ MYSQL_ROW row;
+ MYSQL* mysql = &cur_con->mysql;
+ char query_buf[FN_REFLEN+128];
+ sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
+ master_pos.pos);
+ if(mysql_query(mysql, query_buf))
+ die("At line %u: failed in %s: %d: %s", start_lineno, query_buf,
+ mysql_errno(mysql), mysql_error(mysql));
+
+ if(!(res = mysql_store_result(mysql)))
+ die("line %u: mysql_store_result() retuned NULL", start_lineno);
+ if(!(row = mysql_fetch_row(res)))
+ die("line %u: empty result in %s", start_lineno, query_buf);
+ if(!row[0])
+ die("Error on slave while syncing with master");
+ mysql_free_result(res);
+
+ return 0;
+}
+
+int do_save_master_pos()
+{
+ MYSQL_RES* res;
+ MYSQL_ROW row;
+ MYSQL* mysql = &cur_con->mysql;
+ if(mysql_query(mysql, "show master status"))
+ die("At line %u: failed in show master status: %d: %s", start_lineno,
+ mysql_errno(mysql), mysql_error(mysql));
+
+ if(!(res = mysql_store_result(mysql)))
+ die("line %u: mysql_store_result() retuned NULL", start_lineno);
+ if(!(row = mysql_fetch_row(res)))
+ die("line %u: empty result in show master status", start_lineno);
+ strncpy(master_pos.file, row[0], sizeof(master_pos.file));
+ master_pos.pos = strtoul(row[1], (char**) 0, 10);
+ mysql_free_result(res);
+
+ return 0;
+}
+
+
int do_let(struct st_query* q)
{
char* p=q->first_argument;
@@ -1299,6 +1352,7 @@ int main(int argc, char** argv)
cur_con = cons;
memset(file_stack, 0, sizeof(file_stack));
+ memset(&master_pos, 0, sizeof(master_pos));
file_stack_end = file_stack + MAX_INCLUDE_DEPTH;
cur_file = file_stack;
lineno = lineno_stack;
@@ -1361,6 +1415,8 @@ int main(int argc, char** argv)
get_file_name(save_file,q);
require_file=1;
break;
+ case Q_SAVE_MASTER_POS: do_save_master_pos(q); break;
+ case Q_SYNC_WITH_MASTER: do_sync_with_master(q); break;
case Q_COMMENT: /* Ignore row */
case Q_COMMENT_WITH_COMMAND:
default: processed = 0; break;
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 0af315e9774..9d7145fed49 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -192,11 +192,13 @@ if [ x$SOURCE_DIST = x1 ] ; then
MYSQLD="$BASEDIR/sql/mysqld"
MYSQL_TEST="$BASEDIR/client/mysqltest"
MYSQLADMIN="$BASEDIR/client/mysqladmin"
+ MYSQL="$BASEDIR/client/mysql"
INSTALL_DB="./install_test_db"
else
MYSQLD="$BASEDIR/bin/mysqld"
MYSQL_TEST="$BASEDIR/bin/mysqltest"
MYSQLADMIN="$BASEDIR/bin/mysqladmin"
+ MYSQL="$BASEDIR/bin/mysql"
INSTALL_DB="./install_test_db -bin"
fi
@@ -230,6 +232,11 @@ SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov
#++
# Function Definitions
#--
+wait_for_server_start ()
+ {
+ $MYSQL -e "select 1" --silent -w1 --host=127.0.0.1 --port=$1 \
+ >/dev/null
+ }
prompt_user ()
{
@@ -320,6 +327,7 @@ gcov_collect () {
$ECHO "gcov info in $GCOV_MSG, errors in $GCOV_ERR"
}
+
start_master()
{
[ x$MASTER_RUNNING = 1 ] && return
@@ -354,6 +362,7 @@ start_master()
else
$MYSQLD $master_args >> $MASTER_MYERR 2>&1 &
fi
+ wait_for_server_start $MASTER_MYPORT
MASTER_RUNNING=1
}
@@ -399,6 +408,7 @@ start_slave()
else
$SLAVE_MYSQLD $slave_args >> $SLAVE_MYERR 2>&1 &
fi
+ wait_for_server_start $SLAVE_MYPORT
SLAVE_RUNNING=1
}
@@ -407,7 +417,6 @@ mysql_start () {
start_master
start_slave
cd $MYSQL_TEST_DIR
- sleep $SLEEP_TIME # Give mysqld time to start properly
return 1
}
@@ -430,7 +439,6 @@ stop_slave ()
fi
fi
SLAVE_RUNNING=0
- sleep $SLEEP_TIME # Give mysqld time to go down properly
fi
}
@@ -453,7 +461,6 @@ stop_master ()
fi
fi
MASTER_RUNNING=0
- sleep $SLEEP_TIME # Give mysqld time to go down properly
fi
}
@@ -463,7 +470,10 @@ mysql_stop ()
$ECHO "Shutting-down MySQL daemon"
$ECHO ""
stop_master
+ $ECHO "Master shutdown finished"
stop_slave
+ $ECHO "Slave shutdown finished"
+
return 1
}
diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result
new file mode 100644
index 00000000000..a15ce85526c
--- /dev/null
+++ b/mysql-test/r/rpl000001.result
@@ -0,0 +1,5 @@
+n
+1
+2
+sum(length(word))
+71
diff --git a/mysql-test/r/rpl000014.result b/mysql-test/r/rpl000014.result
index 40421f71fee..9e45b9c10a3 100644
--- a/mysql-test/r/rpl000014.result
+++ b/mysql-test/r/rpl000014.result
@@ -1,13 +1,13 @@
File Position Binlog_do_db Binlog_ignore_db
master-bin.001 73
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
-127.0.0.1 root 9306 1 73 Yes
+127.0.0.1 root 9306 1 master-bin.001 73 Yes
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
-127.0.0.1 root 9306 1 73 No
+127.0.0.1 root 9306 1 master-bin.001 73 No
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
-127.0.0.1 root 9306 1 73 Yes
+127.0.0.1 root 9306 1 master-bin.001 73 Yes
Master_Host Master_User Master_Port Connect_retry Log_File Pos Slave_Running Replicate_do_db Replicate_ignore_db
-127.0.0.1 root 9306 1 173 Yes
+127.0.0.1 root 9306 1 master-bin.001 173 Yes
File Position Binlog_do_db Binlog_ignore_db
master-bin.001 73
n
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 426624ee989..a26580d7ef7 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -7,12 +7,15 @@ load data infile '../../std_data/words.dat' into table t1;
drop table if exists foo;
create table foo(n int);
insert into foo values(1),(2);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
use test;
-@r/rpl000001.a.result select * from foo;
-@r/rpl000001.b.result select sum(length(word)) from t1;
+select * from foo;
+select sum(length(word)) from t1;
connection master;
drop table t1;
-
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000002.test b/mysql-test/t/rpl000002.test
index 7a29088dc7a..c982bd54b8c 100644
--- a/mysql-test/t/rpl000002.test
+++ b/mysql-test/t/rpl000002.test
@@ -5,8 +5,13 @@ drop table if exists t1;
create table t1 (n int auto_increment primary key);
set insert_id = 2000;
insert into t1 values (NULL),(NULL),(NULL);
+save_master_pos;
connection slave;
use test;
-sleep 2;
+sync_with_master;
@r/rpl000002.result select * from t1;
+connection master;
drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000003.test b/mysql-test/t/rpl000003.test
index 38befa8b9c3..b5957615c5b 100644
--- a/mysql-test/t/rpl000003.test
+++ b/mysql-test/t/rpl000003.test
@@ -4,7 +4,12 @@ drop table if exists t1;
create table t1(n int primary key);
!insert into t1 values (1),(2),(2);
insert into t1 values (3);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
@r/rpl000003.result select * from t1;
+connection master;
drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000004.test b/mysql-test/t/rpl000004.test
index cd23078112d..9959c272adb 100644
--- a/mysql-test/t/rpl000004.test
+++ b/mysql-test/t/rpl000004.test
@@ -16,4 +16,11 @@ drop table if exists t2;
load table t2 from master;
@r/rpl000004.a.result check table t1;
@r/rpl000004.b.result select count(*) from t2;
+connection master;
+set SQL_LOG_BIN=1;
drop table if exists t1,t2;
+save_master_pos;
+connection slave;
+sync_with_master;
+create table t1(n int);
+drop table t1;
diff --git a/mysql-test/t/rpl000005.test b/mysql-test/t/rpl000005.test
index 59b52f1a0cf..3e1d14912b2 100644
--- a/mysql-test/t/rpl000005.test
+++ b/mysql-test/t/rpl000005.test
@@ -7,8 +7,12 @@ INSERT t1 SET name='Jacob', age=2;
INSERT into t1 SET name='Caleb', age=1;
ALTER TABLE t1 ADD id int(8) ZEROFILL AUTO_INCREMENT PRIMARY KEY;
@r/rpl000005.result select * from t1;
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
@r/rpl000005.result select * from t1;
connection master;
drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000006.test b/mysql-test/t/rpl000006.test
index 01475d9fbd9..ffab3ebfc1e 100644
--- a/mysql-test/t/rpl000006.test
+++ b/mysql-test/t/rpl000006.test
@@ -12,3 +12,6 @@ load table foo from master;
@r/rpl000006.result select unix_timestamp(t) from foo;
connection master;
drop table foo;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000007.test b/mysql-test/t/rpl000007.test
index cc98b054212..5b121afaa99 100644
--- a/mysql-test/t/rpl000007.test
+++ b/mysql-test/t/rpl000007.test
@@ -15,8 +15,12 @@ insert into foo values('five');
drop table if exists bar;
create table bar (m int);
insert into bar values(15);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
@r/rpl000007.result select foo.n,bar.m from foo,bar;
connection master;
drop table if exists bar,foo;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000008.test b/mysql-test/t/rpl000008.test
index d17190ef31d..8cbc724c3a6 100644
--- a/mysql-test/t/rpl000008.test
+++ b/mysql-test/t/rpl000008.test
@@ -17,8 +17,13 @@ insert into bar values(15);
drop table if exists choo;
create table choo (k int);
insert into choo values(55);
+save_master_pos;
connection slave;
-sleep 3;
+sync_with_master;
@r/rpl000008.result select foo.n,bar.m,choo.k from foo,bar,choo;
connection master;
drop table if exists foo,bar,choo;
+save_master_pos;
+connection slave;
+sync_with_master;
+drop table if exists foo,bar,choo;
diff --git a/mysql-test/t/rpl000009.test b/mysql-test/t/rpl000009.test
index 9297da3bb6b..1f20981f7d0 100644
--- a/mysql-test/t/rpl000009.test
+++ b/mysql-test/t/rpl000009.test
@@ -6,8 +6,9 @@ drop database if exists foo;
create database foo;
drop database if exists bar;
create database bar;
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
drop table if exists foo.foo;
create table foo.foo (n int);
insert into foo.foo values(4);
@@ -18,9 +19,15 @@ insert into foo.foo values(5);
drop table if exists bar.bar;
create table bar.bar (m int);
insert into bar.bar values(15);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
@r/rpl000009.result select foo.foo.n,bar.bar.m from foo.foo,bar.bar;
connection master;
drop database if exists bar;
drop database if exists foo;
+save_master_pos;
+connection slave;
+sync_with_master;
+drop database if exists bar;
+drop database if exists foo;
diff --git a/mysql-test/t/rpl000010.test b/mysql-test/t/rpl000010.test
index 653f8c3fe8c..ab68f0ae45f 100644
--- a/mysql-test/t/rpl000010.test
+++ b/mysql-test/t/rpl000010.test
@@ -8,8 +8,12 @@ drop table if exists t1;
create table t1 (n int not null auto_increment primary key);
insert into t1 values(NULL);
insert into t1 values(2);
+save_master_pos;
connection slave;
-sleep 5;
+sync_with_master;
@r/rpl000010.result select n from t1;
connection master;
drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000011.test b/mysql-test/t/rpl000011.test
index 14280be45cf..78483027405 100644
--- a/mysql-test/t/rpl000011.test
+++ b/mysql-test/t/rpl000011.test
@@ -4,16 +4,21 @@ use test;
drop table if exists t1;
create table t1 (n int);
insert into t1 values(1);
+save_master_pos;
connection slave;
#give slave some breathing room to get started
-sleep 2;
+sync_with_master;
slave stop;
slave start;
connection master;
insert into t1 values(2);
+save_master_pos;
connection slave;
#let slave catch up
-sleep 2;
+sync_with_master;
@r/rpl000011.result select * from t1;
connection master;
drop table t1;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000012.test b/mysql-test/t/rpl000012.test
index d4b40a48386..495cb81167e 100644
--- a/mysql-test/t/rpl000012.test
+++ b/mysql-test/t/rpl000012.test
@@ -14,13 +14,18 @@ disconnect master;
connection master1;
insert into t2 values(6);
disconnect master1;
+connect (master2,localhost,root,,test,0,mysql-master.sock);
+connection master2;
+save_master_pos;
connection slave;
-sleep 1;
+sync_with_master;
@r/rpl000012.result select * from t2;
@r/rpl000012.status.result show status like 'Slave_open_temp_tables';
#
# Clean up
#
-connect (master2,localhost,root,,test,0,mysql-master.sock);
connection master2;
drop table if exists t1,t2;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000013.test b/mysql-test/t/rpl000013.test
index 4d4dc3f491a..f5056839791 100644
--- a/mysql-test/t/rpl000013.test
+++ b/mysql-test/t/rpl000013.test
@@ -1,5 +1,9 @@
source include/master-slave.inc;
connection master;
+save_master_pos;
+connection slave;
+sync_with_master;
+connection master;
drop table if exists t2;
create table t2(n int);
create temporary table t1 (n int);
@@ -12,21 +16,19 @@ insert into t2 select * from t1;
disconnect master;
connection master1;
insert into t2 values(6);
-sleep 2;
disconnect master1;
+connect (master2,localhost,root,,test,0,mysql-master.sock);
+connection master2;
+save_master_pos;
connection slave;
-let $1=12;
-while ($1)
-{
- !slave start;
- sleep 0.2;
- dec $1;
-}
+sync_with_master;
@r/rpl000013.result select * from t2;
@r/rpl000013.status.result show status like 'Slave_open_temp_tables';
#
# Clean up
#
-connect (master2,localhost,root,,test,0,mysql-master.sock);
connection master2;
drop table if exists t1,t2;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000014.test b/mysql-test/t/rpl000014.test
index 1a2ce014813..34e160a760c 100644
--- a/mysql-test/t/rpl000014.test
+++ b/mysql-test/t/rpl000014.test
@@ -2,11 +2,11 @@ source include/master-slave.inc;
source include/have_default_master.inc;
connection master;
show master status;
+save_master_pos;
connection slave;
-sleep 0.2;
+sync_with_master;
show slave status;
change master to master_log_pos=73;
-sleep 0.2;
slave stop;
change master to master_log_pos=73;
show slave status;
@@ -20,9 +20,13 @@ create table if not exists foo(n int);
drop table if exists foo;
create table foo (n int);
insert into foo values (1),(2),(3);
+save_master_pos;
connection slave;
change master to master_log_pos=73;
-sleep 2;
+sync_with_master;
select * from foo;
connection master;
drop table foo;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl000015.test b/mysql-test/t/rpl000015.test
index a2528aa9b42..ac4d5d7d08c 100644
--- a/mysql-test/t/rpl000015.test
+++ b/mysql-test/t/rpl000015.test
@@ -18,8 +18,13 @@ connection master;
drop table if exists foo;
create table foo (n int);
insert into foo values (10),(45),(90);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
select * from foo;
connection master;
drop table foo;
+save_master_pos;
+connection slave;
+sync_with_master;
+
diff --git a/mysql-test/t/rpl000016.test b/mysql-test/t/rpl000016.test
index 2ee68cd230f..115dea734cf 100644
--- a/mysql-test/t/rpl000016.test
+++ b/mysql-test/t/rpl000016.test
@@ -15,8 +15,9 @@ connection master;
drop table if exists t1;
create table t1 (s text);
insert into t1 values('Could not break slave'),('Tried hard');
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
select * from t1;
connection master;
flush logs;
@@ -24,12 +25,14 @@ drop table if exists t2;
create table t2(m int);
insert into t2 values (34),(67),(123);
flush logs;
-sleep 0.3;
show master logs;
purge master logs to 'master-bin.003';
show master logs;
insert into t2 values (65);
+save_master_pos;
connection slave;
-sleep 2;
+sync_with_master;
select * from t2;
drop table if exists t1,t2;
+connection master;
+drop table if exists t1,t2;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 8e6332d4e16..ef9f5f2d38b 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -376,3 +376,8 @@ Item *create_load_file(Item* a)
{
return new Item_load_file(a);
}
+
+Item *create_wait_for_master_pos(Item* a, Item* b)
+{
+ return new Item_master_pos_wait(a, b);
+}
diff --git a/sql/item_create.h b/sql/item_create.h
index de2726b32b0..cc7497b0183 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -85,3 +85,4 @@ Item *create_func_ucase(Item* a);
Item *create_func_version(void);
Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
+Item *create_wait_for_master_pos(Item* a, Item* b);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index bad789479b2..592ef9ae3d4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -26,6 +26,7 @@
#include <hash.h>
#include <time.h>
#include <ft_global.h>
+#include "slave.h" // for wait_for_master_pos
/* return TRUE if item is a constant */
@@ -1388,6 +1389,28 @@ void item_user_lock_release(ULL *ull)
}
/*
+ Wait until we are at or past the given position in the master binlog
+ on the slave
+ */
+
+longlong Item_master_pos_wait::val_int()
+{
+ THD* thd = current_thd;
+ String *log_name = args[0]->val_str(&value);
+ int event_count;
+
+ if(thd->slave_thread || !log_name || !log_name->length())
+ {
+ null_value = 1;
+ return 0;
+ }
+ ulong pos = (ulong)args[1]->val_int();
+ if((event_count = glob_mi.wait_for_pos(thd, log_name, pos)) == -1)
+ null_value = 1;;
+ return event_count;
+}
+
+/*
Get a user level lock. If the thread has an old lock this is first released.
Returns 1: Got lock
Returns 0: Timeout
diff --git a/sql/item_func.h b/sql/item_func.h
index 90400b4181a..5810307e81c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -778,6 +778,18 @@ class Item_func_release_lock :public Item_int_func
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
};
+/* replication functions */
+
+class Item_master_pos_wait :public Item_int_func
+{
+ String value;
+ public:
+ Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {}
+ longlong val_int();
+ const char *func_name() const { return "master_pos_wait"; }
+ void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+};
+
/* Handling of user definiable variables */
diff --git a/sql/lex.h b/sql/lex.h
index 399106bfd77..bff45eb0f06 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -397,6 +397,8 @@ static SYMBOL sql_functions[] = {
{ "LOWER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_lcase)},
{ "LPAD", SYM(FUNC_ARG3),0,CREATE_FUNC(create_func_lpad)},
{ "LTRIM", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ltrim)},
+ { "MASTER_POS_WAIT", SYM(FUNC_ARG2),0,
+ CREATE_FUNC(create_wait_for_master_pos)},
{ "MAKE_SET", SYM(MAKE_SET_SYM),0,0},
{ "MAX", SYM(MAX_SYM),0,0},
{ "MD5", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_md5)},
diff --git a/sql/slave.cc b/sql/slave.cc
index 246dbdde93d..d27bb76c065 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -616,6 +616,46 @@ int flush_master_info(MASTER_INFO* mi)
return 0;
}
+int st_master_info::wait_for_pos(THD* thd, String* log_name, ulong log_pos)
+{
+ if(!inited) return -1;
+ bool pos_reached = 0;
+ int event_count = 0;
+ for(;!pos_reached && !thd->killed;)
+ {
+ int cmp_result;
+ char* basename;
+ pthread_mutex_lock(&lock);
+ if(*log_file_name)
+ {
+ basename = strrchr(log_file_name, FN_LIBCHAR);
+ if(basename)
+ ++basename;
+ else
+ basename = log_file_name;
+ cmp_result = strncmp(basename, log_name->ptr(),
+ log_name->length());
+ }
+ else
+ cmp_result = 0;
+
+ pos_reached = ((!cmp_result && pos >= log_pos) || cmp_result > 0);
+ if(!pos_reached && !thd->killed)
+ {
+ const char* msg = thd->enter_cond(&cond, &lock,
+ "Waiting for master update");
+ pthread_cond_wait(&cond, &lock);
+ thd->exit_cond(msg);
+ event_count++;
+ }
+ pthread_mutex_unlock(&lock);
+ if(thd->killed)
+ return -1;
+ }
+
+ return event_count;
+}
+
static int init_slave_thread(THD* thd)
{
@@ -1003,10 +1043,17 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
{
Rotate_log_event* rev = (Rotate_log_event*)ev;
int ident_len = rev->ident_len;
+ pthread_mutex_lock(&mi->lock);
memcpy(mi->log_file_name, rev->new_log_ident,ident_len );
mi->log_file_name[ident_len] = 0;
mi->pos = 4; // skip magic number
+ pthread_cond_broadcast(&mi->cond);
+ pthread_mutex_unlock(&mi->lock);
flush_master_info(mi);
+#ifndef DBUG_OFF
+ if(abort_slave_event_count)
+ ++events_till_abort;
+#endif
delete ev;
break;
}
@@ -1045,6 +1092,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
pthread_handler_decl(handle_slave,arg __attribute__((unused)))
{
+#ifndef DBUG_OFF
+ slave_begin:
+#endif
THD *thd; // needs to be first for thread_stack
MYSQL *mysql = NULL ;
@@ -1068,8 +1118,8 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
#ifndef DBUG_OFF
events_till_abort = abort_slave_event_count;
#endif
- pthread_cond_broadcast(&COND_slave_start);
- pthread_mutex_unlock(&LOCK_slave);
+ pthread_cond_broadcast(&COND_slave_start);
+ pthread_mutex_unlock(&LOCK_slave);
int error = 1;
bool retried_once = 0;
@@ -1241,6 +1291,10 @@ position %ld",
net_end(&thd->net); // destructor will not free it, because we are weird
delete thd;
my_thread_end();
+#ifndef DBUG_OFF
+ if(abort_slave_event_count && !events_till_abort)
+ goto slave_begin;
+#endif
pthread_exit(0);
DBUG_RETURN(0); // Can't return anything here
}
diff --git a/sql/slave.h b/sql/slave.h
index c26be966fc3..b7e2d783749 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -14,17 +14,20 @@ typedef struct st_master_info
uint port;
uint connect_retry;
pthread_mutex_t lock;
+ pthread_cond_t cond;
bool inited;
st_master_info():pending(0),fd(-1),inited(0)
{
host[0] = 0; user[0] = 0; password[0] = 0;
pthread_mutex_init(&lock, NULL);
+ pthread_cond_init(&cond, NULL);
}
~st_master_info()
{
pthread_mutex_destroy(&lock);
+ pthread_cond_destroy(&cond);
}
inline void inc_pending(ulonglong val)
{
@@ -35,6 +38,7 @@ typedef struct st_master_info
pthread_mutex_lock(&lock);
pos += val + pending;
pending = 0;
+ pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&lock);
}
// thread safe read of position - not needed if we are in the slave thread,
@@ -45,6 +49,8 @@ typedef struct st_master_info
var = pos;
pthread_mutex_unlock(&lock);
}
+
+ int wait_for_pos(THD* thd, String* log_name, ulong log_pos);
} MASTER_INFO;
typedef struct st_table_rule_ent
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 46c37e1b57f..ef42eaf594c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -281,6 +281,25 @@ public:
THD();
~THD();
bool store_globals();
+ inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
+ const char* msg)
+ {
+ const char* old_msg = proc_info;
+ pthread_mutex_lock(&mysys_var->mutex);
+ mysys_var->current_mutex = mutex;
+ mysys_var->current_cond = cond;
+ proc_info = msg;
+ pthread_mutex_unlock(&mysys_var->mutex);
+ return old_msg;
+ }
+ inline void exit_cond(const char* old_msg)
+ {
+ pthread_mutex_lock(&mysys_var->mutex);
+ mysys_var->current_mutex = 0;
+ mysys_var->current_cond = 0;
+ proc_info = old_msg;
+ pthread_mutex_unlock(&mysys_var->mutex);
+ }
inline time_t query_start() { query_start_used=1; return start_time; }
inline void set_time() { if (user_time) start_time=time_after_lock=user_time; else time_after_lock=time(&start_time); }
inline void end_time() { time(&start_time); }
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 0aaaf027ea3..5e37d590c47 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -26,6 +26,36 @@
extern const char* any_db;
extern pthread_handler_decl(handle_slave,arg);
+static int fake_rotate_event(NET* net, String* packet,
+ const char* log_file_name);
+
+static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
+ const char**errmsg)
+{
+ char header[LOG_EVENT_HEADER_LEN];
+ memset(header, 0, 4); // when does not matter
+ header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
+ char* p = strrchr(log_file_name, FN_LIBCHAR);
+ // find the last slash
+ if(p)
+ p++;
+ else
+ p = log_file_name;
+
+ uint ident_len = (uint) strlen(p);
+ ulong event_len = ident_len + sizeof(header);
+ int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
+ int4store(header + EVENT_LEN_OFFSET, event_len);
+ packet->append(header, sizeof(header));
+ packet->append(p,ident_len);
+ if(my_net_write(net, (char*)packet->ptr(), packet->length()))
+ {
+ *errmsg = "failed on my_net_write()";
+ return -1;
+ }
+ return 0;
+}
+
static int send_file(THD *thd)
{
@@ -281,6 +311,15 @@ sweepstakes if you report the bug";
// we need to start a packet with something other than 255
// to distiquish it from error
+ if(pos == 4) // tell the client log name with a fake rotate_event
+ // if we are at the start of the log
+ {
+ if(fake_rotate_event(net, packet, log_file_name, &errmsg))
+ goto err;
+ packet->length(0);
+ packet->append("\0", 1);
+ }
+
while(!net->error && net->vio != 0 && !thd->killed)
{
pthread_mutex_t *log_lock = mysql_bin_log.get_log_lock();
@@ -437,36 +476,15 @@ sweepstakes if you report the bug";
end_io_cache(&log);
(void) my_close(file, MYF(MY_WME));
- if ((file=open_log(&log, log_file_name, &errmsg)) < 0)
- goto err;
-
+
// fake Rotate_log event just in case it did not make it to the log
// otherwise the slave make get confused about the offset
- {
- char header[LOG_EVENT_HEADER_LEN];
- memset(header, 0, 4); // when does not matter
- header[EVENT_TYPE_OFFSET] = ROTATE_EVENT;
- char* p = strrchr(log_file_name, FN_LIBCHAR);
- // find the last slash
- if(p)
- p++;
- else
- p = log_file_name;
-
- uint ident_len = (uint) strlen(p);
- ulong event_len = ident_len + sizeof(header);
- int4store(header + EVENT_TYPE_OFFSET + 1, server_id);
- int4store(header + EVENT_LEN_OFFSET, event_len);
- packet->append(header, sizeof(header));
- packet->append(p,ident_len);
- if(my_net_write(net, (char*)packet->ptr(), packet->length()))
- {
- errmsg = "failed on my_net_write()";
- goto err;
- }
- packet->length(0);
- packet->append("\0",1);
- }
+ if ((file=open_log(&log, log_file_name, &errmsg)) < 0 ||
+ fake_rotate_event(net, packet, log_file_name, &errmsg))
+ goto err;
+
+ packet->length(0);
+ packet->append("\0",1);
}
}