diff --git a/server/modules/routing/binlogrouter/blr.h b/server/modules/routing/binlogrouter/blr.h index 64768527e..3d2d7dbb9 100644 --- a/server/modules/routing/binlogrouter/blr.h +++ b/server/modules/routing/binlogrouter/blr.h @@ -1038,6 +1038,8 @@ extern bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *, const char *, MARIADB_GTID_INFO *); extern void blr_start_master_in_main(void* data); +extern bool blr_binlog_file_exists(ROUTER_INSTANCE *router, + const char *log_name); MXS_END_DECLS diff --git a/server/modules/routing/binlogrouter/blr_file.c b/server/modules/routing/binlogrouter/blr_file.c index 2796ed54d..5f3ee2dc3 100644 --- a/server/modules/routing/binlogrouter/blr_file.c +++ b/server/modules/routing/binlogrouter/blr_file.c @@ -4486,17 +4486,25 @@ bool blr_is_current_binlog(ROUTER_INSTANCE *router, } /** - * Check whether the current binlog file exists. + * Check whether a binlog file exists. * * The file could have been manually removed by mistake. - * The check is done when ROTATE event (real or fake) is seen by - * blr_rotate_event(). + * The check is done when: + * ROTATE event (real or fake) is seen by blr_rotate_event() + * or + * when a slave connects with a binlog_file name. * - * @param router The router instance - * @return True if file exists, false otherwise. + * If param log_file is NULL, the current router->binlog_name + * is checked. + * + * + * @param router The router instance + * @param log_file The file name to check + * @return True if file exists, false otherwise. * */ -bool blr_file_exists(ROUTER_INSTANCE *router) +bool blr_binlog_file_exists(ROUTER_INSTANCE *router, + const char *log_file) { bool ret = true; char path[PATH_MAX + 1] = ""; @@ -4518,15 +4526,22 @@ bool blr_file_exists(ROUTER_INSTANCE *router) } // Set final file name full path - strcat(path, router->binlog_name); + strcat(path, + log_file == NULL ? + router->binlog_name : + log_file); // Check file if (access(path, F_OK) == -1 && errno == ENOENT) { // No file found - MXS_WARNING("%s: ROTATE_EVENT, missing binlog file %s ", + MXS_WARNING("%s: %s, missing binlog file '%s'", router->service->name, + log_file == NULL ? + "ROTATE_EVENT" : + "Slave request", path); + ret = false; } diff --git a/server/modules/routing/binlogrouter/blr_master.c b/server/modules/routing/binlogrouter/blr_master.c index a4c5478d9..1e155bd36 100644 --- a/server/modules/routing/binlogrouter/blr_master.c +++ b/server/modules/routing/binlogrouter/blr_master.c @@ -145,7 +145,6 @@ 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); -extern bool blr_file_exists(ROUTER_INSTANCE *router); extern void blr_file_update_gtid(ROUTER_INSTANCE *router); static int blr_check_connect_retry(ROUTER_INSTANCE *router); @@ -1633,9 +1632,9 @@ blr_rotate_event(ROUTER_INSTANCE *router, uint8_t *ptr, REP_HEADER *hdr) int rotated = 1; int remove_encrytion_ctx = 0; - /* Different file name in rotate event or missing binlog file */ + /* Different file name in rotate event or missing current binlog file */ if ((strncmp(router->binlog_name, file, slen) != 0) || - !blr_file_exists(router)) + !blr_binlog_file_exists(router, NULL)) { remove_encrytion_ctx = 1; router->stats.n_rotates++; diff --git a/server/modules/routing/binlogrouter/blr_slave.c b/server/modules/routing/binlogrouter/blr_slave.c index c21a86272..be5037f09 100644 --- a/server/modules/routing/binlogrouter/blr_slave.c +++ b/server/modules/routing/binlogrouter/blr_slave.c @@ -363,6 +363,8 @@ static void blr_abort_change_master(ROUTER_INSTANCE *router, MASTER_SERVER_CFG *current_master, CHANGE_MASTER_OPTIONS *change_master, const char *error); +static void blr_slave_abort_dump_request(ROUTER_SLAVE *slave, + const char *errmsg); /** * Process a request packet from the slave server. * @@ -1847,30 +1849,22 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue { if (binlognamelen > BINLOG_FNAMELEN) { + /* Abort the request */ char req_file[binlognamelen + 1]; char errmsg[BINLOG_ERROR_MSG_LEN + 1]; memcpy(req_file, (char *)ptr, binlognamelen); req_file[binlognamelen] = 0; - MXS_ERROR("Slave %lu requests COM_BINLOG_DUMP with a filename %s" - " longer than max %d chars. Aborting.", - (unsigned long)slave->serverid, - req_file, - BINLOG_FNAMELEN); - snprintf(errmsg, BINLOG_ERROR_MSG_LEN, - "Connecting slave requested binlog" - " file name %s longer than max %d chars.", - req_file, - BINLOG_FNAMELEN); - + snprintf(errmsg, + BINLOG_ERROR_MSG_LEN, + "Requested filename %s is longer than max %d chars.", + req_file, + BINLOG_FNAMELEN); errmsg[BINLOG_ERROR_MSG_LEN] = '\0'; - blr_send_custom_error(slave->dcb, - slave->seqno + 1, - 0, - errmsg, - "HY000", - BINLOG_FATAL_ERROR_READING); + // ERROR + blr_slave_abort_dump_request(slave, errmsg); + slave->state = BLRS_ERRORED; dcb_close(slave->dcb); return 1; @@ -1893,6 +1887,7 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue binlognamelen > 0, requested_pos)) { + // ERROR slave->state = BLRS_ERRORED; dcb_close(slave->dcb); return 1; @@ -1959,6 +1954,24 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue strlen(slave->binlogfile), (unsigned long)slave->binlog_pos); + /* Check first the requested file exists */ + if (!blr_binlog_file_exists(router, slave->binlogfile)) + { + char errmsg[BINLOG_ERROR_MSG_LEN + 1]; + + snprintf(errmsg, BINLOG_ERROR_MSG_LEN, + "Requested file name '%s' doesn't exist", + slave->binlogfile); + errmsg[BINLOG_ERROR_MSG_LEN] = '\0'; + + // ERROR + blr_slave_abort_dump_request(slave, errmsg); + + slave->state = BLRS_ERRORED; + dcb_close(slave->dcb); + return 1; + } + /* First reply starts from seq = 1 */ slave->seqno = 1; @@ -6888,14 +6901,19 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router, /* Requested GTID Not Found */ if (!f_gtid.gtid) { - MXS_WARNING("Requested MariaDB GTID '%s' by server %lu" - " has not been found", - slave->mariadb_gtid, - (unsigned long)slave->serverid); + char errmsg[BINLOG_ERROR_MSG_LEN + 1]; + snprintf(errmsg, + BINLOG_ERROR_MSG_LEN, + "Requested MariaDB GTID '%s' by server %lu" + " has not been found", + slave->mariadb_gtid, + (unsigned long)slave->serverid); + errmsg[BINLOG_ERROR_MSG_LEN] = '\0'; /* Check strict mode */ if (slave->gtid_strict_mode) { + MXS_ERROR("%s", errmsg); strcpy(slave->binlogfile, ""); slave->binlog_pos = 0; blr_send_custom_error(slave->dcb, @@ -6910,6 +6928,7 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router, else { /* No strict mode: */ + MXS_WARNING("%s", errmsg); // - 1 -Set request GTID as current master one MXS_FREE(slave->mariadb_gtid); @@ -6962,8 +6981,8 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router, * The binlog file could be different due to: * a rotate event or other non GTID events written * after that GTID. - * If file exists events will be sent from requested file@pos - * otherwise file & pos = GTID info file. + * If file exists and pos >=4, events will be sent + * from requested file@pos, otherwise from GTID file & pos. */ // Add tree prefix @@ -6982,7 +7001,8 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router, router->binlogdir, file_path, t_prefix[0] ? t_prefix: NULL); - if (blr_slave_get_file_size(file_path) != 0) + // File size is >=4 read: set pos. + if (blr_slave_get_file_size(file_path) >= 4) { slave->binlog_pos = req_pos; } @@ -9131,3 +9151,24 @@ static void blr_abort_change_master(ROUTER_INSTANCE *router, /* Free parsed options */ blr_master_free_parsed_options(change_master); } + +/** + * Abort the COM_BINLOG_DUMP slave request + * + * @param slave The connecting slave + * @param errmsg Error message to send and log + */ +static void blr_slave_abort_dump_request(ROUTER_SLAVE *slave, + const char *errmsg) +{ + MXS_ERROR("Slave %lu requests COM_BINLOG_DUMP: %s. Aborting.", + (unsigned long)slave->serverid, + errmsg); + + blr_send_custom_error(slave->dcb, + slave->seqno + 1, + 0, + errmsg, + "HY000", + BINLOG_FATAL_ERROR_READING); +}