MXS-1266: Master GTID registration: MASTER_USE_GTID=Slave_pos

MASTER_USE_GTID=Slave_pos is now handled by CHANGE MASTER TO

If mariadb10_master_gtid is On

MASTER_LOG_FILE is no longer required, only MASTER_USE_GTID=Slave_pos

Slave_pos must be set before to empty value or request value:

set @@global.gtid_slave_pos = '0-10116-194';
This commit is contained in:
MassimilianoPinto
2017-06-12 16:19:53 +02:00
parent 23befe8380
commit 2cb874e95f
5 changed files with 323 additions and 93 deletions

View File

@ -691,14 +691,17 @@ createInstance(SERVICE *service, char **options)
} }
inst->orig_masterid = 0; inst->orig_masterid = 0;
inst->mariadb10_gtid_domain = BLR_DEFAULT_GTID_DOMAIN_ID;
/* Override master_id */
if (inst->masterid) if (inst->masterid)
{ {
inst->set_master_server_id = true; inst->set_master_server_id = true;
} }
if ((inst->binlogdir == NULL) || if ((inst->binlogdir == NULL) ||
(inst->binlogdir != NULL && !strlen(inst->binlogdir))) (inst->binlogdir != NULL &&
!strlen(inst->binlogdir)))
{ {
MXS_ERROR("Service %s, binlog directory is not specified", MXS_ERROR("Service %s, binlog directory is not specified",
service->name); service->name);
@ -956,7 +959,9 @@ createInstance(SERVICE *service, char **options)
/* Read any cached response messages */ /* Read any cached response messages */
blr_cache_read_master_data(inst); blr_cache_read_master_data(inst);
/* Find latest binlog file */ /**
* Find latest binlog file in binlogdir or GTID maps repo
*/
if (blr_file_init(inst) == 0) if (blr_file_init(inst) == 0)
{ {
MXS_ERROR("%s: Service not started due to lack of binlog directory %s", MXS_ERROR("%s: Service not started due to lack of binlog directory %s",
@ -1036,6 +1041,7 @@ createInstance(SERVICE *service, char **options)
f_prefix, f_prefix,
inst->binlog_name); inst->binlog_name);
/* Check current binlog */
if (!blr_check_binlog(inst)) if (!blr_check_binlog(inst))
{ {
if (inst->trx_safe || inst->encryption.enabled) if (inst->trx_safe || inst->encryption.enabled)
@ -1047,8 +1053,8 @@ createInstance(SERVICE *service, char **options)
} }
} }
/* Report current pos in binlog file and last seen transaction pos */ /* Log current pos in binlog file and last seen transaction pos */
MXS_INFO("Current binlog file is %s, safe pos %lu, current pos is %lu\n", MXS_INFO("Current binlog file is %s, safe pos %lu, current pos is %lu",
inst->binlog_name, inst->binlog_position, inst->current_pos); inst->binlog_name, inst->binlog_position, inst->current_pos);
/** /**
@ -1102,7 +1108,10 @@ createInstance(SERVICE *service, char **options)
} }
} }
/* Don't start replication if binlog has START_ENCRYPTION_EVENT but binlog encryption is off */ /**
* Don't start replication if binlog has START_ENCRYPTION_EVENT
* but binlog encryption is off
*/
if (!inst->encryption.enabled && inst->encryption_ctx) if (!inst->encryption.enabled && inst->encryption_ctx)
{ {
MXS_ERROR("Found START_ENCRYPTION_EVENT but " MXS_ERROR("Found START_ENCRYPTION_EVENT but "
@ -1211,7 +1220,6 @@ newSession(MXS_ROUTER *instance, MXS_SESSION *session)
slave->lastEventReceived = 0; slave->lastEventReceived = 0;
slave->encryption_ctx = NULL; slave->encryption_ctx = NULL;
slave->mariadb_gtid = NULL; slave->mariadb_gtid = NULL;
slave->gtid_maps = NULL; slave->gtid_maps = NULL;
memset(&slave->f_info, 0 , sizeof (MARIADB_GTID_INFO)); memset(&slave->f_info, 0 , sizeof (MARIADB_GTID_INFO));
@ -2573,7 +2581,7 @@ int
blr_send_custom_error(DCB *dcb, blr_send_custom_error(DCB *dcb,
int packet_number, int packet_number,
int affected_rows, int affected_rows,
char *msg, const char *msg,
char *statemsg, char *statemsg,
unsigned int errcode) unsigned int errcode)
{ {

View File

@ -105,6 +105,9 @@ MXS_BEGIN_DECLS
*/ */
#define BINLOG_FILE_EXTRA_INFO GTID_MAX_LEN #define BINLOG_FILE_EXTRA_INFO GTID_MAX_LEN
/* Default MariaDB GTID Domain Id */
#define BLR_DEFAULT_GTID_DOMAIN_ID 0
enum binlog_storage_type enum binlog_storage_type
{ {
BLR_BINLOG_STORAGE_FLAT, BLR_BINLOG_STORAGE_FLAT,
@ -362,6 +365,8 @@ typedef struct master_server_config
char *ssl_ca; char *ssl_ca;
int ssl_enabled; int ssl_enabled;
char *ssl_version; char *ssl_version;
/* MariaDB 10 GTID */
char *use_mariadb10_gtid;
} MASTER_SERVER_CFG; } MASTER_SERVER_CFG;
/* Config struct for CHANGE MASTER TO options */ /* Config struct for CHANGE MASTER TO options */
@ -379,6 +384,8 @@ typedef struct change_master_options
char *ssl_ca; char *ssl_ca;
char *ssl_enabled; char *ssl_enabled;
char *ssl_version; char *ssl_version;
/* MariaDB 10 GTID */
char *use_mariadb10_gtid;
} CHANGE_MASTER_OPTIONS; } CHANGE_MASTER_OPTIONS;
/** /**
@ -979,7 +986,7 @@ extern int blr_ping(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *);
extern int blr_send_custom_error(DCB *, extern int blr_send_custom_error(DCB *,
int, int,
int, int,
char *, const char *,
char *, char *,
unsigned int); unsigned int);
extern int blr_file_next_exists(ROUTER_INSTANCE *, extern int blr_file_next_exists(ROUTER_INSTANCE *,

View File

@ -450,13 +450,20 @@ blr_file_init(ROUTER_INSTANCE *router)
return 0; return 0;
} }
/**
* Rotate the current log file with new one
*
* @param router The router instance
* @param file The new file to create
* @param pos The binlog position (not used)
* @return 1 on succes, 0 on failure
*/
int int
blr_file_rotate(ROUTER_INSTANCE *router, char *file, uint64_t pos) blr_file_rotate(ROUTER_INSTANCE *router, char *file, uint64_t pos)
{ {
return blr_file_create(router, file); return blr_file_create(router, file);
} }
/** /**
* binlog files need an initial 4 magic bytes at the start. blr_file_add_magic() * binlog files need an initial 4 magic bytes at the start. blr_file_add_magic()
* adds them. * adds them.
@ -474,7 +481,6 @@ blr_file_add_magic(int fd)
return written == BINLOG_MAGIC_SIZE; return written == BINLOG_MAGIC_SIZE;
} }
/** /**
* Create a new binlog file for the router to use. * Create a new binlog file for the router to use.
* *
@ -511,11 +517,15 @@ blr_file_create(ROUTER_INSTANCE *router, char *file)
{ {
char prefix[BINLOG_FILE_EXTRA_INFO]; char prefix[BINLOG_FILE_EXTRA_INFO];
sprintf(prefix, sprintf(prefix,
"%" PRIu32 "/%" PRIu32 "/", "%" PRIu32 "/",
router->mariadb10_gtid_domain, router->mariadb10_gtid_domain);
router->orig_masterid);
// Add domain_id
strcat(path, prefix); strcat(path, prefix);
/**
* - 1 - Check and create $domain_id dir
*/
if (access(path, R_OK) == -1) if (access(path, R_OK) == -1)
{ {
int mkdir_rval; int mkdir_rval;
@ -523,7 +533,32 @@ blr_file_create(ROUTER_INSTANCE *router, char *file)
if (mkdir_rval == -1) if (mkdir_rval == -1)
{ {
MXS_ERROR("Service %s, Failed to create binlog" MXS_ERROR("Service %s, Failed to create binlog"
" directory tree '%s': [%d] %s", " directory tree (domain_id) '%s': [%d] %s",
router->service->name,
path,
errno,
mxs_strerror(errno));
return 0;
}
}
// Add server_id
sprintf(prefix,
"%" PRIu32 "/",
router->orig_masterid);
strcat(path, prefix);
/**
* - 2 - Check and create $server_id dir under $domain_id
*/
if (access(path, R_OK) == -1)
{
int mkdir_rval;
mkdir_rval = mkdir(path, 0700);
if (mkdir_rval == -1)
{
MXS_ERROR("Service %s, Failed to create binlog"
" directory tree (domain_id/server_id) '%s': [%d] %s",
router->service->name, router->service->name,
path, path,
errno, errno,
@ -1289,7 +1324,7 @@ blr_read_binlog(ROUTER_INSTANCE *router,
{ {
snprintf(errmsg, snprintf(errmsg,
BINLOG_ERROR_MSG_LEN, BINLOG_ERROR_MSG_LEN,
"Error reading the binlog event at %lu in binlog file '%s';" "Error reading the binlog event at %lu in binlog file '%s'; "
"(%s), expected %d bytes.", "(%s), expected %d bytes.",
pos, pos,
file->binlogname, file->binlogname,
@ -4113,14 +4148,17 @@ static int gtid_select_cb(void *data,
result->file = MXS_STRDUP_A(values[1]); result->file = MXS_STRDUP_A(values[1]);
result->start = atoll(values[2]); result->start = atoll(values[2]);
result->end = atoll(values[3]); result->end = atoll(values[3]);
if (cols > 4)
if (cols > 4 &&
(values[4] &&
values[5] &&
values[6]))
{ {
result->gtid_elms.domain_id = atoll(values[4]); result->gtid_elms.domain_id = atoll(values[4]);
result->gtid_elms.server_id = atoll(values[5]); result->gtid_elms.server_id = atoll(values[5]);
result->gtid_elms.seq_no = atoll(values[6]); result->gtid_elms.seq_no = atoll(values[6]);
} }
ss_dassert(result->start > 0 && result->start > 0);
if (result->start > 4) if (result->start > 4)
{ {
ss_dassert(result->end > result->start); ss_dassert(result->end > result->start);
@ -4149,6 +4187,14 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
char *errmsg = NULL; char *errmsg = NULL;
char select_query[GTID_SQL_BUFFER_SIZE]; char select_query[GTID_SQL_BUFFER_SIZE];
MARIADB_GTID_ELEMS gtid_elms = {}; MARIADB_GTID_ELEMS gtid_elms = {};
/* The fields in the WHERE clause belong to
* primary key but binlog_file cannot be part of
* WHERE because GTID is made of X-Y-Z, three elements.
*
* The query has ORDER BY id DESC LIMIT 1 in order
* to get the right GTID, even in case of database
* with old content.
*/
static const char select_tpl[] = "SELECT " static const char select_tpl[] = "SELECT "
"(rep_domain ||" "(rep_domain ||"
" '-' || server_id ||" " '-' || server_id ||"
@ -4162,7 +4208,8 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
"FROM gtid_maps " "FROM gtid_maps "
"WHERE (rep_domain = %" PRIu32 " AND " "WHERE (rep_domain = %" PRIu32 " AND "
"server_id = %" PRIu32 " AND " "server_id = %" PRIu32 " AND "
"sequence = %" PRIu64 ");"; "sequence = %" PRIu64 ") "
"ORDER BY id DESC LIMIT 1;";
ss_dassert(gtid != NULL); ss_dassert(gtid != NULL);
/* Parse GTID value into its components */ /* Parse GTID value into its components */
@ -4448,7 +4495,7 @@ bool blr_compare_binlogs(ROUTER_INSTANCE *router,
// domain_id, server_id and strcmp() // domain_id, server_id and strcmp()
return ((router->mariadb10_gtid_domain == info->domain_id) && return ((router->mariadb10_gtid_domain == info->domain_id) &&
(router->orig_masterid == info->server_id) && (router->orig_masterid == info->server_id) &&
strcmp(r_file, r_file) == 0); strcmp(r_file, s_file) == 0);
} }
} }

View File

@ -3107,6 +3107,13 @@ static void blr_register_mariadb_gtid_request(ROUTER_INSTANCE *router,
/** /**
* The routine hanldes a Fake ROTATE_EVENT * The routine hanldes a Fake ROTATE_EVENT
* *
* It takes care of any missing file between
* current file and the one in rotate event:
* files with 4 bytes size colud be created.
*
* The filename specified in rotate event
* is created/overwritten
*
* @param router The router instance * @param router The router instance
* @param hdr The Replication event header * @param hdr The Replication event header
* @param ptr The packet data * @param ptr The packet data
@ -3240,7 +3247,7 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
} }
else else
{ {
// Increment internal offsets // Increment the internal offsets
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
router->last_written = hdr->next_pos; router->last_written = hdr->next_pos;
@ -3275,12 +3282,14 @@ static bool blr_handle_missing_files(ROUTER_INSTANCE *router,
char buf[BLRM_BINLOG_NAME_STR_LEN]; char buf[BLRM_BINLOG_NAME_STR_LEN];
char bigbuf[PATH_MAX + 1]; char bigbuf[PATH_MAX + 1];
if ((fptr = strrchr(new_file, '.')) == NULL) if (*new_file &&
(fptr = strrchr(new_file, '.')) == NULL)
{ {
return false; return false;
} }
new_fseqno = atol(fptr + 1); new_fseqno = atol(fptr + 1);
if ((fptr = strrchr(router->binlog_name, '.')) == NULL) if (*router->binlog_name &&
(fptr = strrchr(router->binlog_name, '.')) == NULL)
{ {
return false; return false;
} }
@ -3288,7 +3297,10 @@ static bool blr_handle_missing_files(ROUTER_INSTANCE *router,
int32_t delta_seq = new_fseqno - (curr_fseqno + 1); int32_t delta_seq = new_fseqno - (curr_fseqno + 1);
/** /**
* Try creating delta_seq empty binlog files * Try creating delta_seq empty binlog files:
*
* Note: currenlty working for positive delta
* and same filestem.
*/ */
if (delta_seq > 0) if (delta_seq > 0)
{ {

View File

@ -426,7 +426,7 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue)
* If GTID master replication is set * If GTID master replication is set
* only GTID slaves can continue the registration. * only GTID slaves can continue the registration.
*/ */
char *err_msg = "MariaDB 10 Slave GTID is required" const char *err_msg = "MariaDB 10 Slave GTID is required"
" for Slave registration."; " for Slave registration.";
slave->state = BLRS_ERRORED; slave->state = BLRS_ERRORED;
/* Send error that stops slave replication */ /* Send error that stops slave replication */
@ -1091,7 +1091,7 @@ blr_slave_send_master_status(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
} }
/* /*
* Columns to send for a "SHOW SLAVE STATUS" command * Columns to send for GTID in "SHOW SLAVE STATUS" command
*/ */
static const char *slave_status_columns[] = static const char *slave_status_columns[] =
{ {
@ -1150,7 +1150,7 @@ static const char *slave_status_columns[] =
}; };
/* /*
* New columns to send for a "SHOW ALL SLAVES STATUS" command * New columns to send for GTID in "SHOW ALL SLAVES STATUS" command
*/ */
static const char *all_slaves_status_columns[] = static const char *all_slaves_status_columns[] =
{ {
@ -1220,6 +1220,7 @@ blr_slave_send_slave_status(ROUTER_INSTANCE *router,
} }
} }
/* Get the right GTID columns array */
const char **gtid_status_columns = router->mariadb10_gtid ? const char **gtid_status_columns = router->mariadb10_gtid ?
mariadb10_gtid_status_columns : mariadb10_gtid_status_columns :
mysql_gtid_status_columns; mysql_gtid_status_columns;
@ -1246,6 +1247,7 @@ blr_slave_send_slave_status(ROUTER_INSTANCE *router,
seqno++); seqno++);
} }
} }
/* Now send column definitions for slave status */ /* Now send column definitions for slave status */
for (i = 0; slave_status_columns[i]; i++) for (i = 0; slave_status_columns[i]; i++)
{ {
@ -2364,6 +2366,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
if (hdr.event_type == ROTATE_EVENT) if (hdr.event_type == ROTATE_EVENT)
{ {
unsigned long beat1 = hkheartbeat; unsigned long beat1 = hkheartbeat;
blr_close_binlog(router, file); blr_close_binlog(router, file);
if (hkheartbeat - beat1 > 1) if (hkheartbeat - beat1 > 1)
{ {
@ -2377,6 +2380,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
slave->encryption_ctx = NULL; slave->encryption_ctx = NULL;
beat1 = hkheartbeat; beat1 = hkheartbeat;
#ifdef BLFILE_IN_SLAVE #ifdef BLFILE_IN_SLAVE
if ((slave->file = blr_open_binlog(router, if ((slave->file = blr_open_binlog(router,
slave->binlogfile, slave->binlogfile,
@ -2867,7 +2871,7 @@ blr_slave_read_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
{ {
return NULL; return NULL;
} }
/* FDE is not encrypted, so we can pass NULL to last parameter */ /* FDE, at pos 4, is not encrypted, pass NULL to last parameter */
if ((record = blr_read_binlog(router, if ((record = blr_read_binlog(router,
file, file,
4, 4,
@ -3554,9 +3558,17 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
router->master_state = BLRM_UNCONNECTED; router->master_state = BLRM_UNCONNECTED;
spinlock_release(&router->lock); spinlock_release(&router->lock);
/* create a new binlog or just use current one */ /**
* Check whether to create the new binlog (router->binlog_name)
*
* File handling happens only if mariadb10_master_gtid is off:
* with Master GTID the first file will be created/opened
* by the fake Rotate Event.
*/
/* Check first for incomplete transaction */
if (strlen(router->prevbinlog) && if (strlen(router->prevbinlog) &&
strcmp(router->prevbinlog, router->binlog_name)) strcmp(router->prevbinlog, router->binlog_name) != 0)
{ {
if (router->trx_safe && if (router->trx_safe &&
router->pending_transaction.state > BLRM_NO_TRANSACTION) router->pending_transaction.state > BLRM_NO_TRANSACTION)
@ -3565,9 +3577,21 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
char file[PATH_MAX + 1] = ""; char file[PATH_MAX + 1] = "";
struct stat statb; struct stat statb;
unsigned long filelen = 0; unsigned long filelen = 0;
char t_prefix[BINLOG_FILE_EXTRA_INFO] = "";
snprintf(file, PATH_MAX, "%s/%s", // Add file prefix
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
sprintf(t_prefix,
"%" PRIu32 "/%" PRIu32 "/",
router->mariadb10_gtid_domain,
router->orig_masterid);
}
// Router current file
snprintf(file, PATH_MAX, "%s/%s%s",
router->binlogdir, router->binlogdir,
t_prefix,
router->prevbinlog); router->prevbinlog);
/* Get file size */ /* Get file size */
@ -3578,9 +3602,10 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
/* Prepare warning message */ /* Prepare warning message */
snprintf(msg, BINLOG_ERROR_MSG_LEN, snprintf(msg, BINLOG_ERROR_MSG_LEN,
"1105:Truncated partial transaction in file %s, " "1105:Truncated partial transaction in file %s%s, "
"starting at pos %lu, " "starting at pos %lu, "
"ending at pos %lu. File %s now has length %lu.", "ending at pos %lu. File %s now has length %lu.",
t_prefix,
router->prevbinlog, router->prevbinlog,
router->last_safe_pos, router->last_safe_pos,
filelen, filelen,
@ -3596,10 +3621,11 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
/* Log it */ /* Log it */
MXS_WARNING("A transaction is still opened at pos %lu" MXS_WARNING("A transaction is still opened at pos %lu"
" File %s will be truncated. " " File %s%s will be truncated. "
"Next binlog file is %s at pos %d, " "Next binlog file is %s at pos %d, "
"START SLAVE is required again.", "START SLAVE is required again.",
router->last_safe_pos, router->last_safe_pos,
t_prefix,
router->prevbinlog, router->prevbinlog,
router->binlog_name, router->binlog_name,
4); 4);
@ -3617,22 +3643,35 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
/* Send warning message to mysql command */ /* Send warning message to mysql command */
blr_slave_send_warning_message(router, slave, msg); blr_slave_send_warning_message(router, slave, msg);
}
}
/* No file has beem opened, create a new binlog file */ return 1;
}
/* No pending transaction */
else
{
/**
* If router->mariadb10_master_gtid is Off then
* handle file create/append.
* This means the domain_id and server_id
* are not taken into account for filename prefix.
*/
if (!router->mariadb10_master_gtid)
{
/* If the router file is not open, create a new binlog file */
if (router->binlog_fd == -1) if (router->binlog_fd == -1)
{ {
blr_file_new_binlog(router, router->binlog_name); blr_file_new_binlog(router, router->binlog_name);
} }
else else
{ {
/* A new binlog file has been created by CHANGE MASTER TO /* A new binlog file has been created and opened
* if no pending transaction is detected. * by CHANGE MASTER TO: use it
* use the existing one.
*/ */
blr_file_append(router, router->binlog_name); blr_file_append(router, router->binlog_name);
} }
}
}
}
/** Initialise SSL: exit on error */ /** Initialise SSL: exit on error */
if (router->ssl_enabled && router->service->dbref->server->server_ssl) if (router->ssl_enabled && router->service->dbref->server->server_ssl)
@ -3644,7 +3683,8 @@ blr_start_slave(ROUTER_INSTANCE* router, ROUTER_SLAVE* slave)
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
"Unable to initialise SSL with backend server", "Unable to initialise SSL with backend server",
(unsigned int)1210, "HY000"); 1210,
"HY000");
spinlock_acquire(&router->lock); spinlock_acquire(&router->lock);
router->master_state = BLRM_SLAVE_STOPPED; router->master_state = BLRM_SLAVE_STOPPED;
@ -3894,36 +3934,62 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
/** /**
* If MASTER_LOG_FILE is not set * If MASTER_LOG_FILE is not set
* and master connection is configured * and master connection is configured
* set master_logfile to current binlog_name * set master_logfile to current binlog_name.
* Otherwise return an error. *
* 'router->use_mariadb10_gtid' value is checked before
* returning an error
*/ */
if (master_logfile == NULL) if (master_logfile == NULL)
{ {
int change_binlog_error = 0; bool change_binlog_error = true;
const char *err_prefix = "Router is not configured "
"for master connection,";
/* Replication is not configured yet */ /* Replication is not configured yet */
if (router->master_state == BLRM_UNCONFIGURED) if (router->master_state == BLRM_UNCONFIGURED)
{ {
/* if there is another error message keep it */ /* Check MASTER_USE_GTID option */
if (!strlen(error)) if (router->mariadb10_master_gtid &&
!change_master.use_mariadb10_gtid)
{ {
snprintf(error, snprintf(error,
BINLOG_ERROR_MSG_LEN, BINLOG_ERROR_MSG_LEN,
"Router is not configured for master connection, " "%s MASTER_USE_GTID=Slave_pos is required",
"MASTER_LOG_FILE is required"); err_prefix);
}
change_binlog_error = 1;
} }
else else
{ {
/* if errors returned set error */ /* If there is another error message keep it */
if (strlen(error)) if (!strlen(error) &&
!change_master.use_mariadb10_gtid)
{ {
change_binlog_error = 1; snprintf(error,
BINLOG_ERROR_MSG_LEN,
"%s MASTER_LOG_FILE is required",
err_prefix);
}
}
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 else
{ {
/* Use current binlog file */ /* Use current binlog file */
master_logfile = MXS_STRDUP_A(router->binlog_name); master_logfile = MXS_STRDUP_A(router->binlog_name);
change_binlog_error = false;
} }
} }
@ -3941,13 +4007,44 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
return -1; 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);
MXS_ERROR("%s: %s", router->service->name, error);
/* restore previous master_host and master_port */
blr_master_restore_config(router, current_master);
blr_master_free_parsed_options(&change_master);
spinlock_release(&router->lock);
return -1;
}
}
/** /**
* If master connection is configured check new binlog name: * If master connection is configured check new binlog name:
* If binlog name has changed to next one only position 4 is allowed * If binlog name has changed to next one
* then only position 4 is allowed
*/ */
if (strcmp(master_logfile, router->binlog_name) && /**
* 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) router->master_state != BLRM_UNCONFIGURED)
{ {
int return_error = 0; int return_error = 0;
@ -4002,7 +4099,6 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
spinlock_release(&router->lock); spinlock_release(&router->lock);
return -1; return -1;
} }
else else
{ {
@ -4026,6 +4122,22 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
router->binlog_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 else
{ {
/** /**
@ -4087,7 +4199,7 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
{ {
/** /**
* no pos change, set it to 4 if BLRM_UNCONFIGURED * no pos change, set it to 4 if BLRM_UNCONFIGURED
* Also set binlog name if UNCOFIGURED * Also set binlog name if UNCONFIGURED
*/ */
if (router->master_state == BLRM_UNCONFIGURED) if (router->master_state == BLRM_UNCONFIGURED)
{ {
@ -4108,11 +4220,10 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
} }
/* Log config changes (without passwords) */ /* Log config changes (without passwords) */
MXS_NOTICE("%s: 'CHANGE MASTER TO executed'. Previous state " MXS_NOTICE("%s: 'CHANGE MASTER TO executed'. Previous state "
"MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', " "MASTER_HOST='%s', MASTER_PORT=%i, MASTER_LOG_FILE='%s', "
"MASTER_LOG_POS=%lu, MASTER_USER='%s'. New state is MASTER_HOST='%s', " "MASTER_LOG_POS=%lu, MASTER_USER='%s'. New state is MASTER_HOST='%s', "
"MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'", "MASTER_PORT=%i, MASTER_LOG_FILE='%s', MASTER_LOG_POS=%lu, MASTER_USER='%s'%s",
router->service->name, router->service->name,
current_master->host, current_master->host,
current_master->port, current_master->port,
@ -4123,7 +4234,10 @@ int blr_handle_change_master(ROUTER_INSTANCE* router,
router->service->dbref->server->port, router->service->dbref->server->port,
router->binlog_name, router->binlog_name,
router->current_pos, router->current_pos,
router->user); router->user,
change_master.use_mariadb10_gtid ?
", MASTER_USE_GTID=Slave_pos" :
"");
blr_master_free_config(current_master); blr_master_free_config(current_master);
@ -4412,6 +4526,8 @@ blr_master_free_config(MASTER_SERVER_CFG *master_cfg)
MXS_FREE(master_cfg->ssl_cert); MXS_FREE(master_cfg->ssl_cert);
MXS_FREE(master_cfg->ssl_ca); MXS_FREE(master_cfg->ssl_ca);
MXS_FREE(master_cfg->ssl_version); MXS_FREE(master_cfg->ssl_version);
/* MariaDB 10 GTID */
MXS_FREE(master_cfg->use_mariadb10_gtid);
MXS_FREE(master_cfg); MXS_FREE(master_cfg);
} }
@ -4454,6 +4570,11 @@ blr_master_set_empty_config(ROUTER_INSTANCE *router)
router->binlog_position = 4; router->binlog_position = 4;
router->current_safe_event = 4; router->current_safe_event = 4;
strcpy(router->binlog_name, ""); strcpy(router->binlog_name, "");
strcpy(router->prevbinlog, "");
/* Set Empty master id */
router->orig_masterid = 0;
/* Set Default GTID domain */
router->mariadb10_gtid_domain = BLR_DEFAULT_GTID_DOMAIN_ID;
} }
/** /**
@ -4921,6 +5042,10 @@ static char
{ {
return &config->ssl_version; return &config->ssl_version;
} }
else if (strcasecmp(option, "master_use_gtid") == 0)
{
return &config->use_mariadb10_gtid;
}
else else
{ {
return NULL; return NULL;
@ -6547,6 +6672,7 @@ static GWBUF *blr_build_fake_rotate_event(ROUTER_SLAVE *slave,
* @param req_pos The requested file pos * @param req_pos The requested file pos
* @return False if GTID is not found and slave * @return False if GTID is not found and slave
* is connectig with gtid_strict_mode=1, * is connectig with gtid_strict_mode=1,
* other errors.
* True otherwise. * True otherwise.
*/ */
static bool blr_slave_gtid_request(ROUTER_INSTANCE *router, static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
@ -6584,13 +6710,26 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
* Empty GTID: * Empty GTID:
* Sending data from the router current file and pos 4 * Sending data from the router current file and pos 4
*/ */
char t_prefix[BINLOG_FILE_EXTRA_INFO] = "";
// Add file prefix
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
sprintf(t_prefix,
"%" PRIu32 "/%" PRIu32 "/",
f_gtid.gtid_elms.domain_id,
f_gtid.gtid_elms.server_id);
}
strcpy(slave->binlogfile, router_curr_file); strcpy(slave->binlogfile, router_curr_file);
slave->binlog_pos = 4; slave->binlog_pos = 4;
MXS_INFO("Slave %lu is registering with empty GTID:" // TODO: Add prefix
" sending events from current binlog file %s," MXS_INFO("Slave %d is registering with empty GTID:"
" sending events from current binlog file %s%s,"
" pos %" PRIu32 "", " pos %" PRIu32 "",
(unsigned long)slave->serverid, slave->serverid,
t_prefix,
slave->binlogfile, slave->binlogfile,
slave->binlog_pos); slave->binlog_pos);
@ -7315,14 +7454,25 @@ static bool blr_handle_set_stmt(ROUTER_INSTANCE *router,
1198, NULL); 1198, NULL);
return false; return false;
} }
if (router->master_state != BLRM_SLAVE_STOPPED) if (router->master_state != BLRM_SLAVE_STOPPED &&
router->master_state != BLRM_UNCONFIGURED)
{ {
MXS_ERROR("Master GTID registration needs stopped replication:" const char *err_msg_u = "configured replication: Issue CHANGE MASTER TO first.";
" issue STOP SLAVE first."); const char *err_msg_s = "stopped replication: issue STOP SLAVE first.";
char error_string[BINLOG_ERROR_MSG_LEN + 1] = "";
MXS_ERROR("GTID registration without %s",
router->master_state == BLRM_SLAVE_STOPPED ?
err_msg_s : err_msg_u);
snprintf(error_string,
BINLOG_ERROR_MSG_LEN,
"Cannot use Master GTID registration without %s",
router->master_state == BLRM_SLAVE_STOPPED ?
err_msg_s :
err_msg_u);
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
"Cannot use Master GTID registration" error_string,
" with running replication;"
" run STOP SLAVE first",
1198, 1198,
NULL); NULL);
return true; return true;
@ -7518,7 +7668,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
MXS_ERROR("%s: %s", router->service->name, error_string); MXS_ERROR("%s: %s", router->service->name, error_string);
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
error_string, error_string,
(unsigned int)1201, 1201,
NULL); NULL);
return true; return true;
@ -7573,7 +7723,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
{ {
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
error_string, error_string,
(unsigned int)1201, 1201,
NULL); NULL);
} }
else else
@ -7593,7 +7743,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
"This operation cannot be performed " "This operation cannot be performed "
"with a running slave; run STOP SLAVE first", "with a running slave; run STOP SLAVE first",
(unsigned int)1198, 1198,
NULL); NULL);
} }
return true; return true;
@ -7661,7 +7811,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
{ {
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
error_string, error_string,
(unsigned int)1201, 1201,
NULL); NULL);
return true; return true;
@ -7676,7 +7826,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
/* CHANGE MASTER TO has failed */ /* CHANGE MASTER TO has failed */
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
error_string, error_string,
(unsigned int)1234, 1234,
"42000"); "42000");
blr_master_free_config(current_master); blr_master_free_config(current_master);
@ -7709,7 +7859,7 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
blr_slave_send_error_packet(slave, blr_slave_send_error_packet(slave,
error_string, error_string,
(unsigned int)1201, 1201,
NULL); NULL);
return true; return true;
@ -7730,10 +7880,13 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
/* /*
* The binlog server has just been configured * The binlog server has just been configured
* master.ini file written in router->binlogdir. * master.ini file written in router->binlogdir.
* Now create the binlogfile specified in MASTER_LOG_FILE *
* Create the binlogfile specified in MASTER_LOG_FILE
* only if MariaDB GTID 'mariadb10_master_gtid' is Off
*/ */
if (blr_file_new_binlog(router, router->binlog_name)) if (!router->mariadb10_master_gtid &&
blr_file_new_binlog(router, router->binlog_name))
{ {
MXS_INFO("%s: 'master.ini' created, binlog file '%s' created", MXS_INFO("%s: 'master.ini' created, binlog file '%s' created",
router->service->name, router->binlog_name); router->service->name, router->binlog_name);
@ -7767,10 +7920,12 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
/* /*
* The CHAMGE MASTER command might specify a new binlog file. * The CHAMGE MASTER command might specify a new binlog file.
* Let's create the binlogfile specified in MASTER_LOG_FILE * Let's create the binlogfile specified in MASTER_LOG_FILE
* only if MariaDB GTID 'mariadb10_master_gtid' is Off
*/ */
if (strlen(router->prevbinlog) && if (!router->mariadb10_master_gtid &&
strcmp(router->prevbinlog, router->binlog_name)) (strlen(router->prevbinlog) &&
strcmp(router->prevbinlog, router->binlog_name) != 0))
{ {
if (blr_file_new_binlog(router, router->binlog_name)) if (blr_file_new_binlog(router, router->binlog_name))
{ {
@ -7882,7 +8037,7 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
binlog_file); binlog_file);
// Update binlog_file name // Update binlog_file name
sprintf(binlog_file, next_file); strcpy(binlog_file, next_file);
// Get binlog file full-path // Get binlog file full-path
blr_get_file_fullpath(binlog_file, blr_get_file_fullpath(binlog_file,
@ -7950,7 +8105,7 @@ blr_show_binary_logs(ROUTER_INSTANCE *router,
"server_id " "server_id "
"FROM gtid_maps " "FROM gtid_maps "
"GROUP BY binlog_file " "GROUP BY binlog_file "
"ORDER BY binlog_file ASC;"; "ORDER BY id ASC;";
int seqno; int seqno;
char *errmsg = NULL; char *errmsg = NULL;
BINARY_LOG_DATA_RESULT result = {}; BINARY_LOG_DATA_RESULT result = {};
@ -8097,6 +8252,7 @@ GWBUF *blr_create_result_row(const char *val1,
return pkt; return pkt;
} }
/** /**
* Binary logs select callback for sqlite3 database * Binary logs select callback for sqlite3 database
* *