Added checksum calculations for events larger than 2^24 bytes
The checksums are now properly calculated for large events that span multiple SQL packets.
This commit is contained in:
@ -424,6 +424,7 @@ typedef struct router_instance {
|
|||||||
int trx_safe; /*< Detect and handle partial transactions */
|
int trx_safe; /*< Detect and handle partial transactions */
|
||||||
int pending_transaction; /*< Pending transaction */
|
int pending_transaction; /*< Pending transaction */
|
||||||
enum blr_event_state master_event_state; /*< Packet read state */
|
enum blr_event_state master_event_state; /*< Packet read state */
|
||||||
|
uint32_t stored_checksum; /*< The current value of the checksum */
|
||||||
REP_HEADER stored_header; /*< Relication header of the event the master is sending */
|
REP_HEADER stored_header; /*< Relication header of the event the master is sending */
|
||||||
uint64_t last_safe_pos; /* last committed transaction */
|
uint64_t last_safe_pos; /* last committed transaction */
|
||||||
char binlog_name[BINLOG_FNAMELEN+1];
|
char binlog_name[BINLOG_FNAMELEN+1];
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
#define GW_MYSQL_READ 0
|
#define GW_MYSQL_READ 0
|
||||||
#define GW_MYSQL_WRITE 1
|
#define GW_MYSQL_WRITE 1
|
||||||
#define MYSQL_HEADER_LEN 4L
|
#define MYSQL_HEADER_LEN 4L
|
||||||
|
#define MYSQL_CHECKSUM_LEN 4L
|
||||||
|
|
||||||
#define GW_MYSQL_PROTOCOL_VERSION 10 // version is 10
|
#define GW_MYSQL_PROTOCOL_VERSION 10 // version is 10
|
||||||
#define GW_MYSQL_HANDSHAKE_FILLER 0x00
|
#define GW_MYSQL_HANDSHAKE_FILLER 0x00
|
||||||
|
@ -1002,38 +1002,6 @@ uint32_t partialpos = 0;
|
|||||||
#ifdef SHOW_EVENTS
|
#ifdef SHOW_EVENTS
|
||||||
printf("blr: len %lu, event type 0x%02x, flags 0x%04x, event size %d, event timestamp %lu\n", (unsigned long)len-4, hdr.event_type, hdr.flags, hdr.event_size, (unsigned long)hdr.timestamp);
|
printf("blr: len %lu, event type 0x%02x, flags 0x%04x, event size %d, event timestamp %lu\n", (unsigned long)len-4, hdr.event_type, hdr.flags, hdr.event_size, (unsigned long)hdr.timestamp);
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
* First check that the checksum we calculate matches the
|
|
||||||
* checksum in the packet we received.
|
|
||||||
*/
|
|
||||||
if (router->master_chksum &&
|
|
||||||
router->master_event_state == BLR_EVENT_DONE)
|
|
||||||
{
|
|
||||||
uint32_t chksum, pktsum;
|
|
||||||
|
|
||||||
chksum = crc32(0L, NULL, 0);
|
|
||||||
chksum = crc32(chksum, ptr + 5, hdr.event_size - 4);
|
|
||||||
pktsum = EXTRACT32(ptr + hdr.event_size + 1);
|
|
||||||
if (pktsum != chksum)
|
|
||||||
{
|
|
||||||
router->stats.n_badcrc++;
|
|
||||||
if (msg)
|
|
||||||
{
|
|
||||||
free(msg);
|
|
||||||
msg = NULL;
|
|
||||||
}
|
|
||||||
MXS_ERROR("%s: Checksum error in event "
|
|
||||||
"from master, "
|
|
||||||
"binlog %s @ %lu. "
|
|
||||||
"Closing master connection.",
|
|
||||||
router->service->name,
|
|
||||||
router->binlog_name,
|
|
||||||
router->current_pos);
|
|
||||||
blr_master_close(router);
|
|
||||||
blr_master_delayed_connect(router);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,27 +1018,40 @@ uint32_t partialpos = 0;
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* pending 16 mb */
|
|
||||||
/* current partial event is being written to disk file */
|
/* current partial event is being written to disk file */
|
||||||
uint32_t offset = 4;
|
uint32_t offset = MYSQL_HEADER_LEN;
|
||||||
|
uint32_t extra_bytes = MYSQL_HEADER_LEN;
|
||||||
|
|
||||||
/** Don't write the OK byte into the binlog */
|
/** Don't write the OK byte into the binlog */
|
||||||
if (router->master_event_state == BLR_EVENT_STARTED)
|
if (router->master_event_state == BLR_EVENT_STARTED)
|
||||||
{
|
{
|
||||||
offset++;
|
offset = MYSQL_HEADER_LEN + 1;
|
||||||
router->master_event_state = BLR_EVENT_ONGOING;
|
router->master_event_state = BLR_EVENT_ONGOING;
|
||||||
|
|
||||||
|
/** Initialize the checksum and calculate it for
|
||||||
|
* the first packet */
|
||||||
|
if (router->master_chksum)
|
||||||
|
{
|
||||||
|
router->stored_checksum = crc32(0L, NULL, 0);
|
||||||
|
extra_bytes = MYSQL_HEADER_LEN + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (router->master_chksum)
|
||||||
|
{
|
||||||
|
router->stored_checksum = crc32(router->stored_checksum,
|
||||||
|
ptr + offset,
|
||||||
|
len - extra_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blr_write_data_into_binlog(router, len - offset, ptr + offset) == 0)
|
if (blr_write_data_into_binlog(router, len - offset, ptr + offset) == 0)
|
||||||
{
|
{
|
||||||
/*
|
/** Failed to write to the binlog file, destroy the buffer
|
||||||
* Failed to write to the
|
* chain and close the connection with the master */
|
||||||
* binlog file, destroy the
|
while (pkt)
|
||||||
* buffer chain and close the
|
{
|
||||||
* connection with the master
|
pkt = GWBUF_CONSUME_ALL(pkt);
|
||||||
*/
|
}
|
||||||
while ((pkt = gwbuf_consume(pkt,
|
|
||||||
GWBUF_LENGTH(pkt))) != NULL);
|
|
||||||
blr_master_close(router);
|
blr_master_close(router);
|
||||||
blr_master_delayed_connect(router);
|
blr_master_delayed_connect(router);
|
||||||
return;
|
return;
|
||||||
@ -1081,6 +1062,43 @@ uint32_t partialpos = 0;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First check that the checksum we calculate matches the
|
||||||
|
* checksum in the packet we received.
|
||||||
|
*/
|
||||||
|
if (router->master_chksum)
|
||||||
|
{
|
||||||
|
uint32_t pktsum, offset = MYSQL_HEADER_LEN;
|
||||||
|
uint32_t size = len - MYSQL_HEADER_LEN - MYSQL_CHECKSUM_LEN;
|
||||||
|
|
||||||
|
if (router->master_event_state == BLR_EVENT_DONE)
|
||||||
|
{
|
||||||
|
/** Initialize the checksum and set the pointer offset to
|
||||||
|
* the first byte after the header and OK byte */
|
||||||
|
router->stored_checksum = crc32(0L, NULL, 0);
|
||||||
|
offset = MYSQL_HEADER_LEN + 1;
|
||||||
|
size = len - MYSQL_HEADER_LEN - MYSQL_CHECKSUM_LEN - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
router->stored_checksum = crc32(router->stored_checksum,
|
||||||
|
ptr + offset, size);
|
||||||
|
|
||||||
|
pktsum = EXTRACT32(ptr + len - MYSQL_CHECKSUM_LEN);
|
||||||
|
if (pktsum != router->stored_checksum)
|
||||||
|
{
|
||||||
|
router->stats.n_badcrc++;
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
MXS_ERROR("%s: Checksum error in event from master, "
|
||||||
|
"binlog %s @ %lu. Closing master connection.",
|
||||||
|
router->service->name, router->binlog_name,
|
||||||
|
router->current_pos);
|
||||||
|
blr_master_close(router);
|
||||||
|
blr_master_delayed_connect(router);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hdr.ok == 0)
|
if (hdr.ok == 0)
|
||||||
{
|
{
|
||||||
router->lastEventReceived = hdr.event_type;
|
router->lastEventReceived = hdr.event_type;
|
||||||
|
Reference in New Issue
Block a user