MXS-1383: fix for some change master to MASTER_LOG_FILE, POS settings that fail.

MXS-1383: fix for some change master to MASTER_LOG_FILE, POS settings
that fail.
This commit is contained in:
MassimilianoPinto 2017-09-12 14:22:13 +02:00
parent e0c85d02fa
commit 43d5f67a76

View File

@ -365,6 +365,17 @@ static void blr_abort_change_master(ROUTER_INSTANCE *router,
const char *error);
static void blr_slave_abort_dump_request(ROUTER_SLAVE *slave,
const char *errmsg);
static bool blr_binlog_change_check(const ROUTER_INSTANCE *router,
const CHANGE_MASTER_OPTIONS change_master,
char *error);
static bool blr_change_binlog_name(ROUTER_INSTANCE *router,
char *log_file,
char **new_logfile,
char *error);
static bool blr_apply_changes(ROUTER_INSTANCE *router,
CHANGE_MASTER_OPTIONS change_master,
char *new_logfile,
char *error);
/**
* Process a request packet from the slave server.
*
@ -4052,291 +4063,33 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
}
/**
* Check if binlog file can be changed
*
* Change the binlog filename as from MASTER_LOG_FILE
* New binlog file could be the next one or current one
* or empty if router->mariadb10_master_gtid is set.
*/
master_logfile = blr_set_master_logfile(router,
change_master.binlog_file,
error);
/**
* If MASTER_LOG_FILE is not set
* and master connection is configured
* set master_logfile to current binlog_name.
*
* 'router->use_mariadb10_gtid' value is checked before
* returning an error
*/
if (master_logfile == NULL)
if (!blr_binlog_change_check(router,
change_master,
error) ||
!blr_change_binlog_name(router,
change_master.binlog_file,
&master_logfile,
error) ||
!blr_apply_changes(router,
change_master,
master_logfile,
error))
{
bool change_binlog_error = true;
const char *err_prefix = "Router is not configured "
"for master connection,";
/* Replication is not configured yet */
if (router->master_state == BLRM_UNCONFIGURED)
{
/* Check MASTER_USE_GTID option */
if (router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_USE_GTID=Slave_pos is required",
err_prefix);
}
else
{
/* If there is another error message keep it */
if (!strlen(error) &&
!change_master.use_mariadb10_gtid)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_LOG_FILE is required",
err_prefix);
}
}
blr_abort_change_master(router,
current_master,
&change_master,
error);
MXS_FREE(master_logfile);
change_binlog_error = strlen(error) ? true : false;
}
else
{
/* If errors returned set error */
if (strlen(error) &&
(router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid))
{
/* MASTER_USE_GTID option not set */
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_USE_GTID=Slave_pos is required",
err_prefix);
}
else
{
/* Use current binlog file */
master_logfile = MXS_STRDUP_A(router->binlog_name);
spinlock_release(&router->lock);
change_binlog_error = false;
}
}
if (change_binlog_error)
{
blr_abort_change_master(router,
current_master,
&change_master,
error);
spinlock_release(&router->lock);
return -1;
}
}
else
/* master_log_file is not NULL */
{
/* Check for MASTER_USE_GTID option */
const char *err_prefix = "Router is not configured "
"for master connection,";
if (router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_USE_GTID=Slave_pos is required",
err_prefix);
blr_abort_change_master(router,
current_master,
&change_master,
error);
spinlock_release(&router->lock);
return -1;
}
}
/**
* If master connection is configured check new binlog name:
* If binlog name has changed to next one
* then only position 4 is allowed
*/
/**
* Check whether MASTER_USE_GTID option was set
*/
if ((router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid) &&
strcmp(master_logfile, router->binlog_name) != 0 &&
router->master_state != BLRM_UNCONFIGURED)
{
int return_error = 0;
if (master_log_pos == NULL)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Please provide an explicit MASTER_LOG_POS "
"for new MASTER_LOG_FILE %s: "
"Permitted binlog pos is %d. "
"Current master_log_file=%s, master_log_pos=%lu",
master_logfile,
4,
router->binlog_name,
router->current_pos);
return_error = 1;
}
else
{
if (pos != 4)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Can not set MASTER_LOG_POS to %s for "
"MASTER_LOG_FILE %s: "
"Permitted binlog pos is %d. "
"Current master_log_file=%s, master_log_pos=%lu",
master_log_pos,
master_logfile,
4,
router->binlog_name,
router->current_pos);
return_error = 1;
}
}
/* Return an error or set new binlog name at pos 4 */
if (return_error)
{
blr_abort_change_master(router,
current_master,
&change_master,
error);
MXS_FREE(master_logfile);
spinlock_release(&router->lock);
return -1;
}
else
{
/* Set new filename at pos 4 */
strcpy(router->binlog_name, master_logfile);
router->current_pos = 4;
router->binlog_position = 4;
router->current_safe_event = 4;
/**
* Close current file binlog file,
* next start slave will create the new one
*/
fsync(router->binlog_fd);
close(router->binlog_fd);
router->binlog_fd = -1;
MXS_INFO("%s: New MASTER_LOG_FILE is [%s]",
router->service->name,
router->binlog_name);
}
}
/* MariaDB 10 GTID request */
else if (router->mariadb10_master_gtid &&
change_master.use_mariadb10_gtid)
{
/* Set empty filename at pos 4 */
strcpy(router->binlog_name, "");
router->current_pos = 4;
router->binlog_position = 4;
router->current_safe_event = 4;
MXS_INFO("%s: MASTER_USE_GTID is [%s], value [%s]",
router->service->name,
change_master.use_mariadb10_gtid,
router->last_mariadb_gtid);
}
else
{
/**
* Same binlog or master connection not configured
* Position cannot be different from
* current pos or 4 (if BLRM_UNCONFIGURED)
*/
int return_error = 0;
if (router->master_state == BLRM_UNCONFIGURED)
{
if (master_log_pos != NULL && pos != 4)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Can not set MASTER_LOG_POS to %s: "
"Permitted binlog pos is 4. Specified master_log_file=%s",
master_log_pos,
master_logfile);
return_error = 1;
}
}
else
{
if (master_log_pos != NULL && pos != router->current_pos)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN, "Can not set MASTER_LOG_POS to %s: "
"Permitted binlog pos is %lu. "
"Current master_log_file=%s, master_log_pos=%lu",
master_log_pos,
router->current_pos,
router->binlog_name,
router->current_pos);
return_error = 1;
}
}
/* log error and return */
if (return_error)
{
blr_abort_change_master(router,
current_master,
&change_master,
error);
MXS_FREE(master_logfile);
spinlock_release(&router->lock);
return -1;
}
else
{
/**
* no pos change, set it to 4 if BLRM_UNCONFIGURED
* Also set binlog name if UNCONFIGURED
*/
if (router->master_state == BLRM_UNCONFIGURED)
{
router->current_pos = 4;
router->binlog_position = 4;
router->current_safe_event = 4;
strcpy(router->binlog_name, master_logfile);
MXS_INFO("%s: New MASTER_LOG_FILE is [%s]",
router->service->name,
router->binlog_name);
}
MXS_INFO("%s: New MASTER_LOG_POS is [%lu]",
router->service->name,
router->current_pos);
}
return -1;
}
/* Log config changes (without passwords) */
@ -4444,7 +4197,9 @@ blr_set_master_port(ROUTER_INSTANCE *router, char *port)
* @return New binlog file or NULL on error
*/
static char *
blr_set_master_logfile(ROUTER_INSTANCE *router, char *filename, char *error)
blr_set_master_logfile(ROUTER_INSTANCE *router,
char *filename,
char *error)
{
char *new_binlog_file = NULL;
@ -9172,3 +8927,301 @@ static void blr_slave_abort_dump_request(ROUTER_SLAVE *slave,
"HY000",
BINLOG_FATAL_ERROR_READING);
}
/**
* Check whether the current binlog file can be changed
*
* @param router The curret router instance
* @param change_master The options in CHANGE_MASTER TO command
* @param error Pointer to outout error message
*
* @return True if binlog can be changed or false.
*/
static bool blr_binlog_change_check(const ROUTER_INSTANCE *router,
const CHANGE_MASTER_OPTIONS change_master,
char *error)
{
char *master_logfile = NULL;
/**
* MASTER_LOG_FILE is not set in CHANGE MASTER TO.
* If binlog server is not configured and
* mariadb10_master_gtid is not set, then return an error.
*/
if (change_master.binlog_file == NULL)
{
if (router->master_state == BLRM_UNCONFIGURED &&
!router->mariadb10_master_gtid)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Router is not configured for master connection, "
"MASTER_LOG_FILE is required");
return false;
}
else
{
return true;
}
}
else
/**
* If binlog file is set in CHANGE MASTER TO
* and MASTER_USE_GTID option is on, then return an error.
*/
{
/**
* Check first MASTER_USE_GTID option:
*
* if not present return an error:
*/
if (router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_USE_GTID=Slave_pos is required",
router->master_state == BLRM_UNCONFIGURED ?
"Router is not configured for master connection," :
"Cannot use MASTER_LOG_FILE for master connection,");
return false;
}
else
{
return true;
}
}
return true;
}
/**
* Set the new binlog filenanme from MASTER_LOG_FILE
*
* If no name change, the current router file is set.
* Note:
* Empty filename, MASTER_LOG_FILE = '', can be passed only
* if mariadb10_master_gtid option is set.
*
* @param router The router instance
* @param binlog_file The binlog file in MASTER_LOG_FILE
* @param error Ouput error message
* @param new_logfile The new log file name
*
* @return True if binlog name has been set or false
* on errors
*/
static bool blr_change_binlog_name(ROUTER_INSTANCE *router,
char *binlog_file,
char **new_logfile,
char *error)
{
bool ret = true;
/* MASTER_LOG_FILE is not present in CHANGE MASTER TO */
if (binlog_file == NULL)
{
/* Use current binlog file */
*new_logfile = MXS_STRDUP_A(router->binlog_name);
}
else
{
/**
* Change the binlog filename as from MASTER_LOG_FILE
* New binlog file can be:
* - the next in sequence router file
* - current router file
* - empty if router->mariadb10_master_gtid is set.
*/
*new_logfile = blr_set_master_logfile(router,
binlog_file,
error);
if (*new_logfile == NULL)
{
if (!router->mariadb10_master_gtid ||
strlen(binlog_file) > 1)
{
/* Binlog name can not be changed */
ret = false;
}
else
{
*new_logfile = MXS_STRDUP_A("");
}
}
}
return ret;
}
/**
* Apply binlog filename and position changes
*
* @param router The current router instance
* @param change_master The change master options
* @param error The error message to fill
* @param new_logfile The new binlog filename
* set in previous stage
*
* @return True if changes have been set
* or false on errors.
*/
static bool blr_apply_changes(ROUTER_INSTANCE *router,
CHANGE_MASTER_OPTIONS change_master,
char *new_logfile,
char *error)
{
bool ret = true;
char *master_log_pos = NULL;
long long pos = 0;
/* Set new binlog position from MASTER_LOG_POS */
master_log_pos = change_master.binlog_pos;
if (master_log_pos == NULL)
{
pos = 0;
}
else
{
pos = atoll(master_log_pos);
}
/**
* Binlog name and position are checked if:
* - mariadb10_master_gtid is off and
* - master connection is already configured.
* Checks:
* (1) filename is different from current router log file and pos != 4
* (2) position is not current one for current file
* Binlog file and pos can set after all checks.
*/
/* MariaDB 10 GTID request */
if (router->mariadb10_master_gtid)
{
if (change_master.use_mariadb10_gtid)
{
/* MASTER_USE_GTID=Slave_pos is set */
MXS_INFO("%s: MASTER_USE_GTID is [%s]",
router->service->name,
change_master.use_mariadb10_gtid);
}
/* Always log the current GTID value with CHANGE_MASTER TO */
MXS_INFO("%s: CHANGE MASTER TO, current GTID value is [%s]",
router->service->name,
router->last_mariadb_gtid);
/* Always set empty filename at pos 4 with CHANGE_MASTER TO */
strcpy(router->binlog_name, "");
router->current_pos = 4;
router->binlog_position = 4;
router->current_safe_event = 4;
}
/* The new filename is not the current one */
else if (strcmp(new_logfile, router->binlog_name) != 0 &&
router->master_state != BLRM_UNCONFIGURED)
{
if (master_log_pos == NULL)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Please provide an explicit MASTER_LOG_POS "
"for new MASTER_LOG_FILE %s: "
"Permitted binlog pos is %d. "
"Current master_log_file=%s, master_log_pos=%lu",
new_logfile,
4,
router->binlog_name,
router->current_pos);
ret = false;
}
else
{
if (pos != 4)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Can not set MASTER_LOG_POS to %s for "
"MASTER_LOG_FILE %s: "
"Permitted binlog pos is %d. "
"Current master_log_file=%s, master_log_pos=%lu",
master_log_pos,
new_logfile,
4,
router->binlog_name,
router->current_pos);
ret = false;
}
}
/* Set new binlog name at pos 4 */
if (ret)
{
strcpy(router->binlog_name, new_logfile);
router->current_pos = 4;
router->binlog_position = 4;
router->current_safe_event = 4;
/**
* Close current file binlog file,
* next start slave will create the new one
*/
fsync(router->binlog_fd);
close(router->binlog_fd);
router->binlog_fd = -1;
MXS_INFO("%s: New MASTER_LOG_FILE is [%s]",
router->service->name,
router->binlog_name);
}
}
else
{
/**
* Same binlog or master connection not configured
* Position cannot be different from
* current pos or 4 (if BLRM_UNCONFIGURED).
* Note:
* pos is not checked if router->mariadb10_master_gtid is set
*/
if (router->master_state == BLRM_UNCONFIGURED)
{
if (master_log_pos != NULL && pos != 4)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN,
"Can not set MASTER_LOG_POS to %s: "
"Permitted binlog pos is 4. Specified master_log_file=%s",
master_log_pos,
new_logfile);
ret = false;
}
}
else
{
if (master_log_pos != NULL && pos != router->current_pos)
{
snprintf(error,
BINLOG_ERROR_MSG_LEN, "Can not set MASTER_LOG_POS to %s: "
"Permitted binlog pos is %lu. "
"Current master_log_file=%s, master_log_pos=%lu",
master_log_pos,
router->current_pos,
router->binlog_name,
router->current_pos);
ret = false;
}
}
}
return ret;
}