MXS-1209: MariaDB GTID registration: handling of skipped binlog files from a Fake ROTATE_EVENT

MariaDB GTID Master registration:
creating missing binlog files (with 4 byes) between current one and the
filename coming from ROTATE_EVENT.

blr_slave_binlog_dump() is also checking possible empty files.
This commit is contained in:
MassimilianoPinto
2017-05-12 17:18:38 +02:00
parent 61ffd3e0f0
commit 2c346ffc1b
3 changed files with 347 additions and 92 deletions

View File

@ -76,6 +76,7 @@
#include <maxscale/thread.h>
#include <maxscale/protocol/mysql.h>
#include <maxscale/alloc.h>
#include <inttypes.h>
static GWBUF *blr_make_query(DCB *dcb, char *query);
static GWBUF *blr_make_registration(ROUTER_INSTANCE *router);
@ -128,7 +129,7 @@ static void blr_register_cache_response(ROUTER_INSTANCE *router,
GWBUF *in_buf);
static void blr_start_master_registration(ROUTER_INSTANCE *router, GWBUF *buf);
static void blr_register_mariadb_gtid_request(ROUTER_INSTANCE *router,
GWBUF *buf);
GWBUF *buf);
static bool blr_handle_fake_rotate(ROUTER_INSTANCE *router,
REP_HEADER *hdr,
uint8_t *ptr);
@ -140,6 +141,9 @@ extern int blr_write_special_event(ROUTER_INSTANCE *router,
uint32_t hole_size,
REP_HEADER *hdr,
int type);
extern int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
static bool blr_handle_missing_files(ROUTER_INSTANCE *router,
char *new_file);
static void worker_cb_start_master(int worker_id, void* data);
static void blr_start_master_in_main(void* data);
@ -758,13 +762,12 @@ static void reset_errors(ROUTER_INSTANCE *router, REP_HEADER *hdr)
spinlock_release(&router->lock);
#ifdef SHOW_EVENTS
printf("blr: len %lu, event type 0x%02x, flags 0x%04x, "
"event size %d, event timestamp %lu\n",
(unsigned long)len - MYSQL_HEADER_LEN,
printf("blr: event type 0x%02x, flags 0x%04x, "
"event size %d, event timestamp %" PRIu32 "\n",
hdr->event_type,
hdr->flags,
hdr->event_size,
(unsigned long)hdr->timestamp);
hdr->timestamp);
#endif
}
@ -3043,8 +3046,9 @@ static void blr_start_master_registration(ROUTER_INSTANCE *router, GWBUF *buf)
* registration command
*/
static void blr_register_mariadb_gtid_request(ROUTER_INSTANCE *router,
GWBUF *buf)
GWBUF *buf)
{
const char format_gtid_val[] = "SET @slave_connect_state='%s'";
// Extract GTID domain
char *val = blr_extract_column(buf, 1);
// Store the Master GTID domain
@ -3054,9 +3058,9 @@ static void blr_register_mariadb_gtid_request(ROUTER_INSTANCE *router,
gwbuf_free(buf);
// SET the requested GTID
char set_gtid[GTID_MAX_LEN + 33 + 1];
char set_gtid[GTID_MAX_LEN + sizeof(format_gtid_val)];
sprintf(set_gtid,
"SET @slave_connect_state='%s'",
format_gtid_val,
router->last_mariadb_gtid);
MXS_INFO("%s: Requesting GTID (%s) from master server.",
@ -3104,13 +3108,18 @@ static bool blr_handle_fake_rotate(ROUTER_INSTANCE *router,
pos <<= 32;
pos |= extract_field(ptr + BINLOG_EVENT_HDR_LEN, 32);
MXS_INFO("Fake ROTATE_EVENT received: file %s, pos %lu. Next event at pos %lu\n",
file,
(unsigned long)pos,
(unsigned long)hdr->next_pos);
MXS_DEBUG("Fake ROTATE_EVENT received: file %s, pos %" PRIu64
". Next event at pos %" PRIu32,
file,
pos,
hdr->next_pos);
/**
* TODO: Detect any missing file in sequence.
* Detect any missing file in sequence.
*/
if (!blr_handle_missing_files(router, file))
{
return false;
}
spinlock_acquire(&router->binlog_lock);
@ -3129,6 +3138,7 @@ static bool blr_handle_fake_rotate(ROUTER_INSTANCE *router,
router->current_pos = BINLOG_MAGIC_SIZE;
router->binlog_position = BINLOG_MAGIC_SIZE;
router->last_event_pos = BINLOG_MAGIC_SIZE;
router->current_safe_event = BINLOG_MAGIC_SIZE;
}
router->rotating = 1;
@ -3161,10 +3171,11 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
{
uint64_t binlog_file_eof = lseek(router->binlog_fd, 0L, SEEK_END);
MXS_INFO("Fake GTID_LIST received: file %s, pos %lu. Next event at pos %lu\n",
MXS_INFO("Fake GTID_LIST received: file %s, pos %" PRIu64
". Next event at pos %" PRIu32,
router->binlog_name,
(unsigned long)router->current_pos,
(unsigned long)hdr->next_pos);
router->current_pos,
hdr->next_pos);
/**
* We could write in any binlog file position:
@ -3177,8 +3188,9 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
uint64_t hole_size = hdr->next_pos - binlog_file_eof;
MXS_INFO("Detected hole while processing"
" a Fake GTID_LIST Event: hole size will be %lu bytes",
(unsigned long)hole_size);
" a Fake GTID_LIST Event: hole size will be %"
PRIu64 " bytes",
hole_size);
/* Set the offet for the write routine */
spinlock_acquire(&router->binlog_lock);
@ -3208,3 +3220,72 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
}
}
}
/**
* Detect any missing file in sequence between
* current router->binlog_name and new_file
* in fake ROTATE_EVENT.
*
* In case of missing files, new files with 4 bytes
* will be created up to new_file.
*
* @param router The current router
* @param new_file The filename in Fake ROTATE_EVENT
* @return true on success, false on errors
*/
static bool blr_handle_missing_files(ROUTER_INSTANCE *router,
char *new_file)
{
char *fptr;
uint32_t new_fseqno;
uint32_t curr_fseqno;
char buf[BLRM_BINLOG_NAME_STR_LEN];
char bigbuf[PATH_MAX + 1];
if ((fptr = strrchr(new_file, '.')) == NULL)
{
return false;
}
new_fseqno = atol(fptr + 1);
if ((fptr = strrchr(router->binlog_name, '.')) == NULL)
{
return false;
}
curr_fseqno = atol(fptr + 1);
int32_t delta_seq = new_fseqno - (curr_fseqno + 1);
/**
* Try creating delta_seq empty binlog files
*/
if (delta_seq > 0)
{
MXS_INFO("Fake ROTATE_EVENT comes with a %" PRIu32
" delta sequence in its name."
" Creating %" PRIi32 " empty files",
delta_seq,
delta_seq);
// Create up to (delta_seq - 1) empty (with 4 bytes) binlog files
for (int i = 1; i <= delta_seq; i++)
{
sprintf(buf, BINLOG_NAMEFMT, router->fileroot, curr_fseqno + i);
if (!blr_file_new_binlog(router, buf))
{
return false;
}
else
{
MXS_INFO("Created empty binlog file [%d] '%s'"
" due to Fake ROTATE_EVENT file sequence delta.",
i,
buf);
}
}
// Some files created, return true
return true;
}
// Did nothing, just return true
return true;
}