summaryrefslogtreecommitdiff
path: root/sql/sql_repl.cc
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2013-09-04 12:22:09 +0200
committerunknown <knielsen@knielsen-hq.org>2013-09-04 12:22:09 +0200
commitada15c7a0f7947073664451c3804ab03723c657e (patch)
tree9a4366bccc5f87f1f8ad2700de1c4f5978ede620 /sql/sql_repl.cc
parent378bd0442a62d1067d19c67dddc3d8b27fc8a537 (diff)
downloadmariadb-git-ada15c7a0f7947073664451c3804ab03723c657e.tar.gz
Fix various places where code would work incorrectly if the common_header_len of events is different on master and slave
Patch developed with the help of Pavel Ivanov. Also fix an uninitialised variable in queue_event().
Diffstat (limited to 'sql/sql_repl.cc')
-rw-r--r--sql/sql_repl.cc72
1 files changed, 65 insertions, 7 deletions
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 3e4939b7fa8..546a3dca98c 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1269,6 +1269,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
int err;
String packet;
+ Format_description_log_event *fdev= NULL;
if (gtid_state->load((const rpl_gtid *)NULL, 0))
{
@@ -1280,6 +1281,13 @@ gtid_state_from_pos(const char *name, uint32 offset,
if ((file= open_binlog(&cache, name, &errormsg)) == (File)-1)
return errormsg;
+ if (!(fdev= new Format_description_log_event(3)))
+ {
+ errormsg= "Out of memory initializing format_description event "
+ "while scanning binlog to find start position";
+ goto end;
+ }
+
/*
First we need to find the initial GTID_LIST_EVENT. We need this even
if the offset is at the very start of the binlog file.
@@ -1315,6 +1323,8 @@ gtid_state_from_pos(const char *name, uint32 offset,
typ= (Log_event_type)(uchar)packet[EVENT_TYPE_OFFSET];
if (typ == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
if (found_format_description_event)
{
errormsg= "Duplicate format description log event found while "
@@ -1324,6 +1334,15 @@ gtid_state_from_pos(const char *name, uint32 offset,
current_checksum_alg= get_checksum_alg(packet.ptr(), packet.length());
found_format_description_event= true;
+ if (!(tmp= new Format_description_log_event(packet.ptr(), packet.length(),
+ fdev)))
+ {
+ errormsg= "Corrupt Format_description event found or out-of-memory "
+ "while searching for old-style position in binlog";
+ goto end;
+ }
+ delete fdev;
+ fdev= tmp;
}
else if (typ != FORMAT_DESCRIPTION_EVENT && !found_format_description_event)
{
@@ -1348,7 +1367,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
}
status= Gtid_list_log_event::peek(packet.ptr(), packet.length(),
current_checksum_alg,
- &gtid_list, &list_len);
+ &gtid_list, &list_len, fdev);
if (status)
{
errormsg= "Error reading Gtid_list_log_event while searching "
@@ -1376,7 +1395,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
uchar flags2;
if (Gtid_log_event::peek(packet.ptr(), packet.length(),
current_checksum_alg, &gtid.domain_id,
- &gtid.server_id, &gtid.seq_no, &flags2))
+ &gtid.server_id, &gtid.seq_no, &flags2, fdev))
{
errormsg= "Corrupt gtid_log_event found while scanning binlog to find "
"initial slave position";
@@ -1399,6 +1418,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
}
end:
+ delete fdev;
end_io_cache(&cache);
mysql_file_close(file, MYF(MY_WME));
@@ -1502,7 +1522,8 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
enum_gtid_until_state *gtid_until_group,
rpl_binlog_state *until_binlog_state,
bool slave_gtid_strict_mode, rpl_gtid *error_gtid,
- bool *send_fake_gtid_list)
+ bool *send_fake_gtid_list,
+ Format_description_log_event *fdev)
{
my_off_t pos;
size_t len= packet->length();
@@ -1516,7 +1537,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
if (ev_offset > len ||
Gtid_list_log_event::peek(packet->ptr()+ev_offset, len - ev_offset,
current_checksum_alg,
- &gtid_list, &list_len))
+ &gtid_list, &list_len, fdev))
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
return "Failed to read Gtid_list_log_event: corrupt binlog";
@@ -1545,7 +1566,7 @@ send_event_to_slave(THD *thd, NET *net, String* const packet, ushort flags,
Gtid_log_event::peek(packet->ptr()+ev_offset, len - ev_offset,
current_checksum_alg,
&event_gtid.domain_id, &event_gtid.server_id,
- &event_gtid.seq_no, &flags2))
+ &event_gtid.seq_no, &flags2, fdev))
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
return "Failed to read Gtid_log_event: corrupt binlog";
@@ -1881,6 +1902,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
uint8 current_checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF;
int old_max_allowed_packet= thd->variables.max_allowed_packet;
+ Format_description_log_event *fdev= NULL;
#ifndef DBUG_OFF
int left_events = max_binlog_dump_events;
@@ -1956,6 +1978,13 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
}
#endif
+ if (!(fdev= new Format_description_log_event(3)))
+ {
+ errmsg= "Out of memory initializing format_description event";
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ goto err;
+ }
+
if (!mysql_bin_log.is_open())
{
errmsg = "Binary log is not open";
@@ -2119,6 +2148,8 @@ impossible position";
(*packet)[EVENT_TYPE_OFFSET+ev_offset]));
if ((*packet)[EVENT_TYPE_OFFSET+ev_offset] == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
current_checksum_alg= get_checksum_alg(packet->ptr() + ev_offset,
packet->length() - ev_offset);
DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF ||
@@ -2136,6 +2167,18 @@ impossible position";
"slaves that cannot process them");
goto err;
}
+
+ if (!(tmp= new Format_description_log_event(packet->ptr()+ev_offset,
+ packet->length()-ev_offset,
+ fdev)))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ errmsg= "Corrupt Format_description event found or out-of-memory";
+ goto err;
+ }
+ delete fdev;
+ fdev= tmp;
+
(*packet)[FLAGS_OFFSET+ev_offset] &= ~LOG_EVENT_BINLOG_IN_USE_F;
/*
mark that this event with "log_pos=0", so the slave
@@ -2253,6 +2296,8 @@ impossible position";
#endif
if (event_type == FORMAT_DESCRIPTION_EVENT)
{
+ Format_description_log_event *tmp;
+
current_checksum_alg= get_checksum_alg(packet->ptr() + ev_offset,
packet->length() - ev_offset);
DBUG_ASSERT(current_checksum_alg == BINLOG_CHECKSUM_ALG_OFF ||
@@ -2271,6 +2316,17 @@ impossible position";
goto err;
}
+ if (!(tmp= new Format_description_log_event(packet->ptr()+ev_offset,
+ packet->length()-ev_offset,
+ fdev)))
+ {
+ my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ errmsg= "Corrupt Format_description event found or out-of-memory";
+ goto err;
+ }
+ delete fdev;
+ fdev= tmp;
+
(*packet)[FLAGS_OFFSET+ev_offset] &= ~LOG_EVENT_BINLOG_IN_USE_F;
}
@@ -2295,7 +2351,7 @@ impossible position";
until_gtid_state, &gtid_until_group,
&until_binlog_state,
slave_gtid_strict_mode, &error_gtid,
- &send_fake_gtid_list)))
+ &send_fake_gtid_list, fdev)))
{
errmsg= tmp_msg;
goto err;
@@ -2501,7 +2557,7 @@ impossible position";
&gtid_skip_group, until_gtid_state,
&gtid_until_group, &until_binlog_state,
slave_gtid_strict_mode, &error_gtid,
- &send_fake_gtid_list)))
+ &send_fake_gtid_list, fdev)))
{
errmsg= tmp_msg;
goto err;
@@ -2599,6 +2655,7 @@ end:
thd->current_linfo = 0;
mysql_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
+ delete fdev;
DBUG_VOID_RETURN;
err:
@@ -2674,6 +2731,7 @@ err:
if (file >= 0)
mysql_file_close(file, MYF(MY_WME));
thd->variables.max_allowed_packet= old_max_allowed_packet;
+ delete fdev;
my_message(my_errno, error_text, MYF(0));
DBUG_VOID_RETURN;