summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBUILD/compile-pentium64-valgrind-max29
-rw-r--r--BitKeeper/etc/config1
-rw-r--r--client/mysqltest.c9
-rw-r--r--mysql-test/r/rpl_dual_pos_advance.result22
-rw-r--r--mysql-test/t/rpl_dual_pos_advance-master.opt0
-rw-r--r--mysql-test/t/rpl_dual_pos_advance.test108
-rw-r--r--sql/log.cc6
-rw-r--r--sql/log_event.cc42
-rw-r--r--sql/log_event.h28
-rw-r--r--sql/slave.cc128
-rw-r--r--sql/slave.h11
11 files changed, 341 insertions, 43 deletions
diff --git a/BUILD/compile-pentium64-valgrind-max b/BUILD/compile-pentium64-valgrind-max
new file mode 100755
index 00000000000..2e4ff8e0082
--- /dev/null
+++ b/BUILD/compile-pentium64-valgrind-max
@@ -0,0 +1,29 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$pentium64_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$pentium_configs $debug_configs"
+
+# We want to test isam when building with valgrind
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-isam --with-embedded-server --with-openssl --with-raid --with-ndbcluster"
+
+. "$path/FINISH.sh"
+
+if test -z "$just_print"
+then
+ set +v +x
+ echo "\
+******************************************************************************
+Note that by default BUILD/compile-pentium-valgrind-max calls 'configure' with
+--enable-assembler. When Valgrind detects an error involving an assembly
+function (for example an uninitialized value used as an argument of an
+assembly function), Valgrind will not print the stacktrace and 'valgrind
+--gdb-attach=yes' will not work either. If you need a stacktrace in those
+cases, you have to run BUILD/compile-pentium-valgrind-max with the
+--disable-assembler argument.
+******************************************************************************"
+fi
diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config
index af93117a517..5fa877c5e3a 100644
--- a/BitKeeper/etc/config
+++ b/BitKeeper/etc/config
@@ -72,5 +72,6 @@ hours:
[nick:]checkout:get
[jonas:]checkout:get
[tomas:]checkout:get
+[guilhem:]checkout:get
checkout:edit
eoln:unix
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 19a44b0f24c..35408368a73 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -294,6 +294,7 @@ Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_START_TIMER, Q_END_TIMER,
Q_CHARACTER_SET, Q_DISABLE_PS_PROTOCOL, Q_ENABLE_PS_PROTOCOL,
+Q_EXIT,
Q_DISABLE_RECONNECT, Q_ENABLE_RECONNECT,
Q_IF,
@@ -381,6 +382,7 @@ const char *command_names[]=
"character_set",
"disable_ps_protocol",
"enable_ps_protocol",
+ "exit",
"disable_reconnect",
"enable_reconnect",
"if",
@@ -3744,7 +3746,7 @@ int main(int argc, char **argv)
{
int error = 0;
struct st_query *q;
- my_bool require_file=0, q_send_flag=0, query_executed= 0;
+ my_bool require_file=0, q_send_flag=0, query_executed= 0, abort_flag= 0;
char save_file[FN_REFLEN];
MY_STAT res_info;
MY_INIT(argv[0]);
@@ -3825,7 +3827,7 @@ int main(int argc, char **argv)
*/
var_set_errno(-1);
- while (!read_query(&q))
+ while (!abort_flag && !read_query(&q))
{
int current_line_inc = 1, processed = 0;
if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
@@ -4028,6 +4030,9 @@ int main(int argc, char **argv)
case Q_ENABLE_RECONNECT:
cur_con->mysql.reconnect= 1;
break;
+ case Q_EXIT:
+ abort_flag= 1;
+ break;
default: processed = 0; break;
}
diff --git a/mysql-test/r/rpl_dual_pos_advance.result b/mysql-test/r/rpl_dual_pos_advance.result
new file mode 100644
index 00000000000..257baa81b74
--- /dev/null
+++ b/mysql-test/r/rpl_dual_pos_advance.result
@@ -0,0 +1,22 @@
+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;
+reset master;
+change master to master_host="127.0.0.1",master_port=SLAVE_PORT,master_user="root";
+start slave;
+create table t1 (n int);
+create table t4 (n int);
+create table t5 (n int);
+create table t6 (n int);
+show tables;
+Tables_in_test
+t1
+t4
+t5
+t6
+stop slave;
+reset slave;
+drop table t1,t4,t5,t6;
diff --git a/mysql-test/t/rpl_dual_pos_advance-master.opt b/mysql-test/t/rpl_dual_pos_advance-master.opt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/mysql-test/t/rpl_dual_pos_advance-master.opt
diff --git a/mysql-test/t/rpl_dual_pos_advance.test b/mysql-test/t/rpl_dual_pos_advance.test
new file mode 100644
index 00000000000..518fa9df885
--- /dev/null
+++ b/mysql-test/t/rpl_dual_pos_advance.test
@@ -0,0 +1,108 @@
+# This test checks that in a dual-head setup
+# A->B->A, where A has --log-slave-updates (why would it?
+# assume that there is a C as slave of A),
+# then the Exec_master_log_pos of SHOW SLAVE STATUS does
+# not stay too low on B(BUG#13023 due to events ignored because
+# of their server id).
+# It also will test BUG#13861.
+
+source include/master-slave.inc;
+
+
+# set up "dual head"
+
+connection slave;
+reset master;
+
+connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval change master to master_host="127.0.0.1",master_port=$SLAVE_MYPORT,master_user="root";
+
+start slave;
+
+# now we test it
+
+connection slave;
+
+create table t1 (n int);
+
+save_master_pos;
+connection master;
+sync_with_master;
+
+# Now test BUG#13861. This will be enabled when Guilhem fixes this
+# bug.
+
+# stop slave
+
+# create table t2 (n int); # create one ignored event
+
+# save_master_pos;
+# connection slave;
+# sync_with_master;
+
+# connection slave;
+
+# show tables;
+
+# save_master_pos;
+
+# create table t3 (n int);
+
+# connection master;
+
+# bug is that START SLAVE UNTIL may stop too late, we test that by
+# asking it to stop before creation of t3.
+
+# start slave until master_log_file="slave-bin.000001",master_log_pos=195;
+
+# wait until it's started (the position below is the start of "CREATE
+# TABLE t2") (otherwise wait_for_slave_to_stop may return at once)
+
+# select master_pos_wait("slave-bin.000001",137);
+
+# wait_for_slave_to_stop;
+
+# then BUG#13861 causes t3 to show up below (because stopped too
+# late).
+
+# show tables;
+
+# start slave;
+
+# BUG#13023 is that Exec_master_log_pos may stay too low "forever":
+
+connection master;
+
+create table t4 (n int); # create 3 ignored events
+create table t5 (n int);
+create table t6 (n int);
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+connection slave;
+
+save_master_pos;
+
+connection master;
+
+# then BUG#13023 caused hang below ("master" looks behind, while it's
+# not in terms of updates done).
+
+sync_with_master;
+
+show tables;
+
+# cleanup
+
+stop slave;
+reset slave;
+drop table t1,t4,t5,t6; # add t2 and t3 later
+
+save_master_pos;
+connection slave;
+sync_with_master;
+
+# End of 4.1 tests
diff --git a/sql/log.cc b/sql/log.cc
index a67f35e30bf..c530f15a84f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1028,7 +1028,8 @@ void MYSQL_LOG::new_file(bool need_lock)
to change base names at some point.
*/
THD *thd = current_thd; /* may be 0 if we are reacting to SIGHUP */
- Rotate_log_event r(thd,new_name+dirname_length(new_name));
+ Rotate_log_event r(thd,new_name+dirname_length(new_name),
+ 0, LOG_EVENT_OFFSET, 0);
r.set_log_pos(this);
r.write(&log_file);
bytes_written += r.get_event_len();
@@ -1106,7 +1107,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
DBUG_ASSERT(log_file.type == SEQ_READ_APPEND);
- pthread_mutex_lock(&LOCK_log);
+ safe_mutex_assert_owner(&LOCK_log);
do
{
if (my_b_append(&log_file,(byte*) buf,len))
@@ -1125,7 +1126,6 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...)
}
err:
- pthread_mutex_unlock(&LOCK_log);
if (!error)
signal_update();
DBUG_RETURN(error);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index b08439a20b8..be4654bccd3 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2013,18 +2013,44 @@ void Rotate_log_event::print(FILE* file, bool short_form, char* last_db)
#endif /* MYSQL_CLIENT */
+
/*
- Rotate_log_event::Rotate_log_event()
+ Rotate_log_event::Rotate_log_event() (2 constructors)
*/
+
+#ifndef MYSQL_CLIENT
+Rotate_log_event::Rotate_log_event(THD* thd_arg,
+ const char* new_log_ident_arg,
+ uint ident_len_arg, ulonglong pos_arg,
+ uint flags_arg)
+ :Log_event(), new_log_ident(new_log_ident_arg),
+ pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
+ (uint) strlen(new_log_ident_arg)), flags(flags_arg)
+{
+#ifndef DBUG_OFF
+ char buff[22];
+ DBUG_ENTER("Rotate_log_event::Rotate_log_event(THD*,...)");
+ DBUG_PRINT("enter",("new_log_ident %s pos %s flags %lu", new_log_ident_arg,
+ llstr(pos_arg, buff), flags));
+#endif
+ if (flags & DUP_NAME)
+ new_log_ident= my_strdup_with_length(new_log_ident_arg,
+ ident_len,
+ MYF(MY_WME));
+ DBUG_VOID_RETURN;
+}
+#endif
+
+
Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
bool old_format)
- :Log_event(buf, old_format),new_log_ident(NULL),alloced(0)
+ :Log_event(buf, old_format), new_log_ident(0), flags(DUP_NAME)
{
// The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
int header_size = (old_format) ? OLD_HEADER_LEN : LOG_EVENT_HEADER_LEN;
uint ident_offset;
- DBUG_ENTER("Rotate_log_event");
+ DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
if (event_len < header_size)
DBUG_VOID_RETURN;
@@ -2043,12 +2069,9 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
ident_offset = ROTATE_HEADER_LEN;
}
set_if_smaller(ident_len,FN_REFLEN-1);
- if (!(new_log_ident= my_strdup_with_length((byte*) buf +
- ident_offset,
- (uint) ident_len,
- MYF(MY_WME))))
- DBUG_VOID_RETURN;
- alloced = 1;
+ new_log_ident= my_strdup_with_length((byte*) buf + ident_offset,
+ (uint) ident_len,
+ MYF(MY_WME));
DBUG_VOID_RETURN;
}
@@ -2060,6 +2083,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
int Rotate_log_event::write_data(IO_CACHE* file)
{
char buf[ROTATE_HEADER_LEN];
+ DBUG_ASSERT(!(flags & ZERO_LEN)); // such an event cannot be written
int8store(buf + R_POS_OFFSET, pos);
return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
diff --git a/sql/log_event.h b/sql/log_event.h
index 5c81d0c92f0..6c4e65f7460 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -434,7 +434,7 @@ public:
}
virtual int get_data_size() { return 0;}
virtual int get_data_body_offset() { return 0; }
- int get_event_len()
+ virtual int get_event_len()
{
return (cached_event_len ? cached_event_len :
(cached_event_len = LOG_EVENT_HEADER_LEN + get_data_size()));
@@ -849,18 +849,18 @@ public:
class Rotate_log_event: public Log_event
{
public:
+ enum {
+ ZERO_LEN= 1, // if event should report 0 as its length
+ DUP_NAME= 2 // if constructor should dup the string argument
+ };
const char* new_log_ident;
ulonglong pos;
uint ident_len;
- bool alloced;
+ uint flags;
#ifndef MYSQL_CLIENT
Rotate_log_event(THD* thd_arg, const char* new_log_ident_arg,
- uint ident_len_arg = 0,
- ulonglong pos_arg = LOG_EVENT_OFFSET)
- :Log_event(), new_log_ident(new_log_ident_arg),
- pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
- (uint) strlen(new_log_ident_arg)), alloced(0)
- {}
+ uint ident_len_arg,
+ ulonglong pos_arg, uint flags);
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
@@ -872,10 +872,18 @@ public:
Rotate_log_event(const char* buf, int event_len, bool old_format);
~Rotate_log_event()
{
- if (alloced)
- my_free((gptr) new_log_ident, MYF(0));
+ if (flags & DUP_NAME)
+ my_free((gptr) new_log_ident, MYF(MY_ALLOW_ZERO_PTR));
}
Log_event_type get_type_code() { return ROTATE_EVENT;}
+ virtual int get_event_len()
+ {
+ if (flags & ZERO_LEN)
+ return 0;
+ if (cached_event_len == 0)
+ cached_event_len= LOG_EVENT_HEADER_LEN + get_data_size();
+ return cached_event_len;
+ }
int get_data_size() { return ident_len + ROTATE_HEADER_LEN;}
bool is_valid() { return new_log_ident != 0; }
int write_data(IO_CACHE* file);
diff --git a/sql/slave.cc b/sql/slave.cc
index 1be3e3b4a17..ebae8461f11 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1739,6 +1739,55 @@ static int count_relay_log_space(RELAY_LOG_INFO* rli)
}
+/*
+ Builds a Rotate from the ignored events' info and writes it to relay log.
+
+ SYNOPSIS
+ write_ignored_events_info_to_relay_log()
+ thd pointer to I/O thread's thd
+ mi
+
+ DESCRIPTION
+ Slave I/O thread, going to die, must leave a durable trace of the
+ ignored events' end position for the use of the slave SQL thread, by
+ calling this function. Only that thread can call it (see assertion).
+ */
+static void write_ignored_events_info_to_relay_log(THD *thd, MASTER_INFO *mi)
+{
+ RELAY_LOG_INFO *rli= &mi->rli;
+ pthread_mutex_t *log_lock= rli->relay_log.get_log_lock();
+ DBUG_ASSERT(thd == mi->io_thd);
+ pthread_mutex_lock(log_lock);
+ if (rli->ign_master_log_name_end[0])
+ {
+ DBUG_PRINT("info",("writing a Rotate event to track down ignored events"));
+ Rotate_log_event *ev= new Rotate_log_event(thd, rli->ign_master_log_name_end,
+ 0, rli->ign_master_log_pos_end,
+ Rotate_log_event::DUP_NAME);
+ rli->ign_master_log_name_end[0]= 0;
+ /* can unlock before writing as slave SQL thd will soon see our Rotate */
+ pthread_mutex_unlock(log_lock);
+ if (likely((bool)ev))
+ {
+ ev->server_id= 0; // don't be ignored by slave SQL thread
+ if (unlikely(rli->relay_log.append(ev)))
+ sql_print_error("Slave I/O thread failed to write a Rotate event"
+ " to the relay log, "
+ "SHOW SLAVE STATUS may be inaccurate");
+ rli->relay_log.harvest_bytes_written(&rli->log_space_total);
+ flush_master_info(mi, 1);
+ delete ev;
+ }
+ else
+ sql_print_error("Slave I/O thread failed to create a Rotate event"
+ " (out of memory?), "
+ "SHOW SLAVE STATUS may be inaccurate");
+ }
+ else
+ pthread_mutex_unlock(log_lock);
+}
+
+
void init_master_info_with_options(MASTER_INFO* mi)
{
mi->master_log_name[0] = 0;
@@ -2334,7 +2383,7 @@ st_relay_log_info::st_relay_log_info()
{
group_relay_log_name[0]= event_relay_log_name[0]=
group_master_log_name[0]= 0;
- last_slave_error[0]=0; until_log_name[0]= 0;
+ last_slave_error[0]= until_log_name[0]= ign_master_log_name_end[0]= 0;
bzero((char*) &info_file, sizeof(info_file));
bzero((char*) &cache_buf, sizeof(cache_buf));
@@ -2886,11 +2935,20 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
*/
pthread_mutex_lock(&rli->data_lock);
+ /*
+ This tests if the position of the end of the last previous executed event
+ hits the UNTIL barrier.
+ We would prefer to test if the position of the start (or possibly) end of
+ the to-be-read event hits the UNTIL barrier, this is different if there
+ was an event ignored by the I/O thread just before (BUG#13861 to be
+ fixed).
+ */
if (rli->until_condition!=RELAY_LOG_INFO::UNTIL_NONE &&
rli->is_until_satisfied())
{
+ char buf[22];
sql_print_error("Slave SQL thread stopped because it reached its"
- " UNTIL position %ld", (long) rli->until_pos());
+ " UNTIL position %s", llstr(rli->until_pos(), buf));
/*
Setting abort_slave flag because we do not want additional message about
error in query execution to be printed.
@@ -2925,7 +2983,6 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
if ((ev->server_id == (uint32) ::server_id && !replicate_same_server_id) ||
(rli->slave_skip_counter && type_code != ROTATE_EVENT))
{
- /* TODO: I/O thread should not even log events with the same server id */
rli->inc_group_relay_log_pos(ev->get_event_len(),
type_code != STOP_EVENT ? ev->log_pos : LL(0),
1/* skip lock*/);
@@ -3033,7 +3090,8 @@ extern "C" pthread_handler_decl(handle_slave_io,arg)
{
THD *thd; // needs to be first for thread_stack
MYSQL *mysql;
- MASTER_INFO *mi = (MASTER_INFO*)arg;
+ MASTER_INFO *mi = (MASTER_INFO*)arg;
+ RELAY_LOG_INFO *rli= &mi->rli;
char llbuff[22];
uint retry_count;
@@ -3276,16 +3334,16 @@ reconnect done to recover from failed read");
char llbuf1[22], llbuf2[22];
DBUG_PRINT("info", ("log_space_limit=%s log_space_total=%s \
ignore_log_space_limit=%d",
- llstr(mi->rli.log_space_limit,llbuf1),
- llstr(mi->rli.log_space_total,llbuf2),
- (int) mi->rli.ignore_log_space_limit));
+ llstr(rli->log_space_limit,llbuf1),
+ llstr(rli->log_space_total,llbuf2),
+ (int) rli->ignore_log_space_limit));
}
#endif
- if (mi->rli.log_space_limit && mi->rli.log_space_limit <
- mi->rli.log_space_total &&
- !mi->rli.ignore_log_space_limit)
- if (wait_for_relay_log_space(&mi->rli))
+ if (rli->log_space_limit && rli->log_space_limit <
+ rli->log_space_total &&
+ !rli->ignore_log_space_limit)
+ if (wait_for_relay_log_space(rli))
{
sql_print_error("Slave I/O thread aborted while waiting for relay \
log space");
@@ -3316,6 +3374,7 @@ err:
mysql_close(mysql);
mi->mysql=0;
}
+ write_ignored_events_info_to_relay_log(thd, mi);
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&mi->run_lock);
mi->slave_running = 0;
@@ -3668,6 +3727,7 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev)
if (unlikely(!rev->is_valid()))
DBUG_RETURN(1);
+ /* Safe copy as 'rev' has been "sanitized" in Rotate_log_event's ctor */
memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1);
mi->master_log_pos= rev->pos;
DBUG_PRINT("info", ("master_log_pos: '%s' %d",
@@ -3813,6 +3873,7 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
int error= 0;
ulong inc_pos;
RELAY_LOG_INFO *rli= &mi->rli;
+ pthread_mutex_t *log_lock= rli->relay_log.get_log_lock();
DBUG_ENTER("queue_event");
if (mi->old_format)
@@ -3820,11 +3881,6 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
pthread_mutex_lock(&mi->data_lock);
- /*
- TODO: figure out if other events in addition to Rotate
- require special processing.
- Guilhem 2003-06 : I don't think so.
- */
switch (buf[EVENT_TYPE_OFFSET]) {
case STOP_EVENT:
/*
@@ -3873,16 +3929,27 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
direct master (an unsupported, useless setup!).
*/
+ pthread_mutex_lock(log_lock);
+
if ((uint4korr(buf + SERVER_ID_OFFSET) == ::server_id) &&
!replicate_same_server_id)
{
/*
Do not write it to the relay log.
- We still want to increment, so that we won't re-read this event from the
- master if the slave IO thread is now stopped/restarted (more efficient if
- the events we are ignoring are big LOAD DATA INFILE).
+ a) We still want to increment mi->master_log_pos, so that we won't
+ re-read this event from the master if the slave IO thread is now
+ stopped/restarted (more efficient if the events we are ignoring are big
+ LOAD DATA INFILE).
+ b) We want to record that we are skipping events, for the information of
+ the slave SQL thread, otherwise that thread may let
+ rli->group_relay_log_pos stay too small if the last binlog's event is
+ ignored.
*/
mi->master_log_pos+= inc_pos;
+ memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN);
+ DBUG_ASSERT(rli->ign_master_log_name_end[0]);
+ rli->ign_master_log_pos_end= mi->master_log_pos;
+ rli->relay_log.signal_update(); // the slave SQL thread needs to re-check
DBUG_PRINT("info", ("master_log_pos: %d, event originating from the same server, ignored", (ulong) mi->master_log_pos));
}
else
@@ -3894,7 +3961,9 @@ int queue_event(MASTER_INFO* mi,const char* buf, ulong event_len)
DBUG_PRINT("info", ("master_log_pos: %d", (ulong) mi->master_log_pos));
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
}
+ rli->ign_master_log_name_end[0]= 0; // last event is not ignored
}
+ pthread_mutex_unlock(log_lock);
err:
pthread_mutex_unlock(&mi->data_lock);
@@ -4262,6 +4331,27 @@ Before assert, my_b_tell(cur_log)=%s rli->event_relay_log_pos=%s",
rli->last_master_timestamp= 0;
DBUG_ASSERT(rli->relay_log.get_open_count() == rli->cur_log_old_open_count);
+
+ if (rli->ign_master_log_name_end[0])
+ {
+ /* We generate and return a Rotate, to make our positions advance */
+ DBUG_PRINT("info",("seeing an ignored end segment"));
+ ev= new Rotate_log_event(thd, rli->ign_master_log_name_end,
+ 0, rli->ign_master_log_pos_end,
+ Rotate_log_event::DUP_NAME |
+ Rotate_log_event::ZERO_LEN);
+ rli->ign_master_log_name_end[0]= 0;
+ if (unlikely(!ev))
+ {
+ errmsg= "Slave SQL thread failed to create a Rotate event "
+ "(out of memory?), SHOW SLAVE STATUS may be inaccurate";
+ goto err;
+ }
+ pthread_mutex_unlock(log_lock);
+ ev->server_id= 0; // don't be ignored by slave SQL thread
+ DBUG_RETURN(ev);
+ }
+
/*
We can, and should release data_lock while we are waiting for
update. If we do not, show slave status will block
diff --git a/sql/slave.h b/sql/slave.h
index 5a85e26d9ad..f780b7c8473 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -304,6 +304,17 @@ typedef struct st_relay_log_info
*/
ulong trans_retries, retried_trans;
+ /*
+ If the end of the hot relay log is made of master's events ignored by the
+ slave I/O thread, these two keep track of the coords (in the master's
+ binlog) of the last of these events seen by the slave I/O thread. If not,
+ ign_master_log_name_end[0] == 0.
+ As they are like a Rotate event read/written from/to the relay log, they
+ are both protected by rli->relay_log.LOCK_log.
+ */
+ char ign_master_log_name_end[FN_REFLEN];
+ ulonglong ign_master_log_pos_end;
+
st_relay_log_info();
~st_relay_log_info();