From 5ac736a14e3a6b6079fd9c3c1827b8967ba56f37 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Fri, 30 Jan 2015 14:55:14 +0000 Subject: [PATCH] Fix for CRC in fake rotate events --- server/modules/routing/binlog/blr_master.c | 22 +++++++++++--- server/modules/routing/binlog/blr_slave.c | 34 +++++++++------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/server/modules/routing/binlog/blr_master.c b/server/modules/routing/binlog/blr_master.c index 9e3e2064c..3ce019558 100644 --- a/server/modules/routing/binlog/blr_master.c +++ b/server/modules/routing/binlog/blr_master.c @@ -681,6 +681,11 @@ static REP_HEADER phdr; } pkt_length = gwbuf_length(pkt); + /* + * Loop over all the packets while we still have some data + * and the packet length is enough to hold a replication event + * header. + */ while (pkt && pkt_length > 24) { reslen = GWBUF_LENGTH(pkt); @@ -708,6 +713,7 @@ static REP_HEADER phdr; { len = EXTRACT24(pdata) + 4; } + /* len is now the payload length for the packet we are working on */ if (reslen < len && pkt_length >= len) { @@ -787,10 +793,17 @@ static REP_HEADER phdr; n_bufs = 1; } + /* + * ptr now points at the current message in a contiguous buffer, + * this buffer is either within the GWBUF or in a malloc'd + * copy if the message straddles GWBUF's. + */ + if (len < BINLOG_EVENT_HDR_LEN) { char *msg = ""; + /* Packet is too small to be a binlog event */ if (ptr[4] == 0xfe) /* EOF Packet */ { msg = "end of file"; @@ -812,7 +825,7 @@ static REP_HEADER phdr; blr_extract_header(ptr, &hdr); - if (hdr.event_size != len - 5) + if (hdr.event_size != len - 5) /* Sanity check */ { LOGIF(LE,(skygw_log_write( LOGFILE_ERROR, @@ -843,8 +856,10 @@ static REP_HEADER phdr; phdr = hdr; if (hdr.ok == 0) { -#define CHECK_CRC 1 -#if CHECK_CRC + /* + * First check that the checksum we calculate matches the + * checksum in the packet we received. + */ uint32_t chksum, pktsum; chksum = crc32(0L, NULL, 0); @@ -870,7 +885,6 @@ static REP_HEADER phdr; blr_master_delayed_connect(router); return; } -#endif router->stats.n_binlogs++; router->lastEventReceived = hdr.event_type; diff --git a/server/modules/routing/binlog/blr_slave.c b/server/modules/routing/binlog/blr_slave.c index f76b151d0..09de1892f 100644 --- a/server/modules/routing/binlog/blr_slave.c +++ b/server/modules/routing/binlog/blr_slave.c @@ -888,7 +888,8 @@ if (hkheartbeat - beat1 > 1) LOGIF(LE, (skygw_log_write( LOGIF(LE, (skygw_log_write(LOGFILE_ERROR, "Slave reached end of file for binlog file %s at %u " "which is not the file currently being downloaded. " - "Master binlog is %s, %lu.", + "Master binlog is %s, %lu. This may be caused by a " + "previous failure of the master.", slave->binlogfile, slave->binlog_pos, router->binlog_name, router->binlog_position))); if (blr_slave_fake_rotate(router, slave)) @@ -1014,11 +1015,7 @@ uint32_t chksum; return 0; binlognamelen = strlen(slave->binlogfile); - - if (slave->nocrc) - len = 19 + 8 + binlognamelen; - else - len = 19 + 8 + 4 + binlognamelen; + len = 19 + 8 + 4 + binlognamelen; // Build a fake rotate event resp = gwbuf_alloc(len + 5); @@ -1037,20 +1034,17 @@ uint32_t chksum; memcpy(ptr, slave->binlogfile, binlognamelen); ptr += binlognamelen; - if (!slave->nocrc) - { - /* - * Now add the CRC to the fake binlog rotate event. - * - * The algorithm is first to compute the checksum of an empty buffer - * and then the checksum of the event portion of the message, ie we do not - * include the length, sequence number and ok byte that makes up the first - * 5 bytes of the message. We also do not include the 4 byte checksum itself. - */ - chksum = crc32(0L, NULL, 0); - chksum = crc32(chksum, GWBUF_DATA(resp) + 5, hdr.event_size - 4); - encode_value(ptr, chksum, 32); - } + /* + * Now add the CRC to the fake binlog rotate event. + * + * The algorithm is first to compute the checksum of an empty buffer + * and then the checksum of the event portion of the message, ie we do not + * include the length, sequence number and ok byte that makes up the first + * 5 bytes of the message. We also do not include the 4 byte checksum itself. + */ + chksum = crc32(0L, NULL, 0); + chksum = crc32(chksum, GWBUF_DATA(resp) + 5, hdr.event_size - 4); + encode_value(ptr, chksum, 32); slave->dcb->func.write(slave->dcb, resp); return 1;