MXS-701: RAND_EVENT nows has the two seeds filled

MXS-701: RAND_EVENT nows has the two seeds filled with original packet
size and original event type:

#700101  1:00:00 server id 0  end_log_pos 0 CRC32 0x858bdfd5 	Rand
SET @@RAND_SEED1=62, @@RAND_SEED2=19/*!*/;
This commit is contained in:
MassimilianoPinto
2017-12-07 11:24:37 +01:00
parent 4903804dc9
commit 37a1431ef2

View File

@ -469,78 +469,157 @@ void BinlogFilterSession::fixEvent(uint8_t* event, uint32_t event_size)
}
/**
* Replace data in the current event: no memory allocation
* Replace data in the current packet with binlog event
* with a RAND_EVENT
* No memory allocation is done if current packet size
* is bigger than (MYSQL_HEADER_LEN + 1 + RAND_EVENT)
*
* @param pPacket The GWBUF with event data
*/
void BinlogFilterSession::replaceEvent(GWBUF** pPacket)
void BinlogFilterSession::replaceEvent(GWBUF** ppPacket)
{
//GWBUF* packet;
uint32_t event_len = gwbuf_length(*pPacket);
uint32_t buf_len = gwbuf_length(*ppPacket);
uint32_t orig_event_type = 0;
// If size < BINLOG_EVENT_HDR_LEN + crc32 add rand_event to buff contiguos
ss_dassert(m_skip == true);
// size of empty rand_event (header + 0 bytes + CRC32)
uint32_t new_event_size = BINLOG_EVENT_HDR_LEN + 0;
/**
* RAND_EVENT is:
* - 19 bytes header
* - 8 bytes first seed
* - 8 bytes second seed
* - 4 bytes CRC32 (if required)
*/
// size of rand_event (header + 16 bytes + CRC32)
uint32_t new_event_size = BINLOG_EVENT_HDR_LEN + 16;
new_event_size += m_crc ? 4 : 0;
// If size < BINLOG_EVENT_HDR_LEN + crc32, then create rand_event
if (event_len < (MYSQL_HEADER_LEN + 1 + new_event_size))
/**
* If buf_len < (network packet len with RAND_EVENT),
* then create a new complete rand_event network packet.
*
* This might happen in case of:
* - any "small" binlog event
* or
* - remaining bytes of a large event transmission
*/
if (buf_len < (MYSQL_HEADER_LEN + 1 + new_event_size))
{
GWBUF* tmp_buff;
tmp_buff = gwbuf_alloc(MYSQL_HEADER_LEN + 1 + (new_event_size - event_len));
GWBUF* pTmpbuf;
pTmpbuf = gwbuf_alloc(MYSQL_HEADER_LEN + 1 + \
(new_event_size - buf_len));
// Append new buff to current one
*pPacket = gwbuf_append(*pPacket, tmp_buff);
*ppPacket = gwbuf_append(*ppPacket, pTmpbuf);
// Make current buff contiguous
*pPacket = gwbuf_make_contiguous(*pPacket);
*ppPacket = gwbuf_make_contiguous(*ppPacket);
}
// point do data
uint8_t *ptr = GWBUF_DATA(*pPacket);
// Force OK flag
ptr[MYSQL_HEADER_LEN] = 0;
// TODO Add offsets
// Force Set timestamp to 0
gw_mysql_set_byte4(ptr + MYSQL_HEADER_LEN + 1, 0);
// Force Set server_id to 0
gw_mysql_set_byte4(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1, 0);
// Set NEW event_type
ptr[MYSQL_HEADER_LEN + 1 + 4] = RAND_EVENT;
// SET ignorable flags
gw_mysql_set_byte2(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1 + 4 + 4 + 4,
LOG_EVENT_IGNORABLE_F | LOG_EVENT_SKIP_REPLICATION_F);
// Set event_event size)
gw_mysql_set_byte4(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1 + 4,
new_event_size);
// point to data
uint8_t *ptr = GWBUF_DATA(*ppPacket);
/**
* Replication protocol:
* 1) set 3 bytes for packet size
* 2) the packet sequence is not touched!!!
* 3) set 1 byte OK indicator
*/
// Set New Packet size: new event_size + 1 byte replication status
gw_mysql_set_byte3(ptr, new_event_size + 1);
// Remove the useless bytes in the buffer
if (gwbuf_length(*pPacket) > (new_event_size + 1 + MYSQL_HEADER_LEN))
// Force OK flag after 3 bytes packet size
ptr[MYSQL_HEADER_LEN] = 0;
// Now modify the event header fields (19 bytes)
// 4 bytes timestamp
// 1 byte event type
// 4 bytes server_id
// 4 bytes event_size
// 4 bytes next_pos
// 2 bytes flags
int event_header_offset = MYSQL_HEADER_LEN + 1;
// Force Set timestamp to 0 [4 bytes]
gw_mysql_set_byte4(ptr + event_header_offset, 0);
// Point to event_type
event_header_offset += 4;
// Save current event type only for standard packets
if (!m_is_large)
{
uint32_t remove_bytes = gwbuf_length(*pPacket) - (new_event_size + 1 + MYSQL_HEADER_LEN);
*pPacket = gwbuf_rtrim(*pPacket, remove_bytes);
orig_event_type = ptr[event_header_offset];
}
// Set NEW event_type [1 byte]
ptr[event_header_offset] = RAND_EVENT;
// Point to server_id
event_header_offset++;
// Force Set server_id to 0 [4 bytes]
gw_mysql_set_byte4(ptr + event_header_offset, 0);
// Point to event_size
event_header_offset += 4;
// Set event_event size [4 bytes]
gw_mysql_set_byte4(ptr + event_header_offset, new_event_size);
// Next pos [4 bytes] is set by fixEvent(), go ahead!!!
event_header_offset += 4;
// Point to event_flags,
event_header_offset += 4;
// Set LOG_EVENT_SKIP_REPLICATION_F flags [2 bytes]
gw_mysql_set_byte2(ptr + event_header_offset,
LOG_EVENT_SKIP_REPLICATION_F);
// Point to RAND_EVENT content now
event_header_offset += 2;
/**
* We set now the value for the first and second seed
* as input packet size and event_size
* event_size is 0 for all packets belonging to a large event
*/
// Set first seed as the input packet size (4 bytes only)
gw_mysql_set_byte4(ptr + event_header_offset,
buf_len - (MYSQL_HEADER_LEN + 1));
event_header_offset += 4;
// Set 0 for next 4 bytes of first seed
gw_mysql_set_byte4(ptr + event_header_offset, 0);
// Point to second seed
event_header_offset += 4;
// Set second seed as the input event type (4 bytes only)
gw_mysql_set_byte4(ptr + event_header_offset, orig_event_type);
event_header_offset += 4;
// Set 0 for next 4 bytes of second seed
gw_mysql_set_byte4(ptr + event_header_offset, 0);
/**
* Now we remove the useless bytes in the buffer
* in case of inout packet is bigger than RAND_EVENT packet
*/
if (gwbuf_length(*ppPacket) > (new_event_size + 1 + MYSQL_HEADER_LEN))
{
uint32_t remove_bytes = gwbuf_length(*ppPacket) - \
(new_event_size + 1 + MYSQL_HEADER_LEN);
*ppPacket = gwbuf_rtrim(*ppPacket, remove_bytes);
}
// Fix Event Next pos = 0 and set new CRC32
fixEvent(ptr + MYSQL_HEADER_LEN + 1, new_event_size);
// Log Filtered event
MXS_DEBUG("Filtered event #%d,"
"ok %d, type %d, flags %d, size %d, next_pos %d, packet_size %d\n",
ptr[3],
ptr[4],
RAND_EVENT,
gw_mysql_get_byte2(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1 + 4 + 4 + 4),
gw_mysql_get_byte4(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1 + 4),
gw_mysql_get_byte4(ptr + MYSQL_HEADER_LEN + 1 + 4 + 1 + 4 + 4),
gw_mysql_get_byte3(ptr));
// Log the replaced event
// Now point to event_size offset
event_header_offset = MYSQL_HEADER_LEN + 1 + 4 + 1 + 4;
MXS_DEBUG("Filtered event #%d, "
"ok %d, type %d, flags %d, size %d, next_pos %d, packet_size %d\n",
ptr[3],
ptr[4],
RAND_EVENT,
gw_mysql_get_byte2(ptr + event_header_offset + 4 + 4),
gw_mysql_get_byte4(ptr + event_header_offset),
gw_mysql_get_byte4(ptr + event_header_offset + 4),
gw_mysql_get_byte3(ptr));
}
/**