MXS-1266: Allow save and read binlog files from a binlog cache directory tree

MXS-1266: Allow save and read binlog files from a binlog cache
directory tree
This commit is contained in:
MassimilianoPinto
2017-06-07 08:56:52 +02:00
parent a79a492601
commit 8f94b27fd5
5 changed files with 927 additions and 175 deletions

View File

@ -61,7 +61,6 @@
*/ */
#include "blr.h" #include "blr.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -87,6 +86,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <uuid/uuid.h> #include <uuid/uuid.h>
#include <maxscale/alloc.h> #include <maxscale/alloc.h>
#include <inttypes.h>
/* The router entry points */ /* The router entry points */
static MXS_ROUTER *createInstance(SERVICE *service, char **options); static MXS_ROUTER *createInstance(SERVICE *service, char **options);
@ -126,6 +126,8 @@ static void stats_func(void *);
static bool rses_begin_locked_router_action(ROUTER_SLAVE *); static bool rses_begin_locked_router_action(ROUTER_SLAVE *);
static void rses_end_locked_router_action(ROUTER_SLAVE *); static void rses_end_locked_router_action(ROUTER_SLAVE *);
GWBUF *blr_cache_read_response(ROUTER_INSTANCE *router, char *response); GWBUF *blr_cache_read_response(ROUTER_INSTANCE *router, char *response);
extern bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
MARIADB_GTID_INFO *result);
static SPINLOCK instlock; static SPINLOCK instlock;
static ROUTER_INSTANCE *instances; static ROUTER_INSTANCE *instances;
@ -139,6 +141,13 @@ static const MXS_ENUM_VALUE enc_algo_values[] =
{NULL} {NULL}
}; };
static const MXS_ENUM_VALUE binlog_storage_values[] =
{
{"flat", BLR_BINLOG_STORAGE_FLAT},
{"tree", BLR_BINLOG_STORAGE_TREE},
{NULL}
};
/** /**
* The module entry point routine. It is this routine that * The module entry point routine. It is this routine that
* must populate the structure that is referred to as the * must populate the structure that is referred to as the
@ -200,6 +209,7 @@ MXS_MODULE* MXS_CREATE_MODULE()
{"encryption_key_file", MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK}, {"encryption_key_file", MXS_MODULE_PARAM_PATH, NULL, MXS_MODULE_OPT_PATH_R_OK},
{"mariadb10_slave_gtid", MXS_MODULE_PARAM_BOOL, "false"}, {"mariadb10_slave_gtid", MXS_MODULE_PARAM_BOOL, "false"},
{"mariadb10_master_gtid", MXS_MODULE_PARAM_BOOL, "false"}, {"mariadb10_master_gtid", MXS_MODULE_PARAM_BOOL, "false"},
{"binlog_structure", MXS_MODULE_PARAM_ENUM, "flat", MXS_MODULE_OPT_NONE, binlog_storage_values},
{"shortburst", MXS_MODULE_PARAM_COUNT, DEF_SHORT_BURST}, {"shortburst", MXS_MODULE_PARAM_COUNT, DEF_SHORT_BURST},
{"longburst", MXS_MODULE_PARAM_COUNT, DEF_LONG_BURST}, {"longburst", MXS_MODULE_PARAM_COUNT, DEF_LONG_BURST},
{"burstsize", MXS_MODULE_PARAM_SIZE, DEF_BURST_SIZE}, {"burstsize", MXS_MODULE_PARAM_SIZE, DEF_BURST_SIZE},
@ -382,6 +392,11 @@ createInstance(SERVICE *service, char **options)
/* Set router uuid */ /* Set router uuid */
inst->uuid = config_copy_string(params, "uuid"); inst->uuid = config_copy_string(params, "uuid");
/* Enable Flat or Tree storage of binlog files */
inst->storage_type = config_get_enum(params,
"binlog_structure",
binlog_storage_values);
if (inst->uuid == NULL) if (inst->uuid == NULL)
{ {
/* Generate UUID for the router instance */ /* Generate UUID for the router instance */
@ -542,6 +557,13 @@ createInstance(SERVICE *service, char **options)
{ {
inst->mariadb10_master_gtid = config_truth_value(value); inst->mariadb10_master_gtid = config_truth_value(value);
} }
else if (strcmp(options[i], "binlog_structure") == 0)
{
/* Enable Flat or Tree storage of binlog files */
inst->storage_type = strcasecmp(value, "tree") == 0 ?
BLR_BINLOG_STORAGE_TREE :
BLR_BINLOG_STORAGE_FLAT;
}
else if (strcmp(options[i], "encryption_algorithm") == 0) else if (strcmp(options[i], "encryption_algorithm") == 0)
{ {
int ret = blr_check_encryption_algorithm(value); int ret = blr_check_encryption_algorithm(value);
@ -672,7 +694,6 @@ createInstance(SERVICE *service, char **options)
return NULL; return NULL;
} }
/* Get the Encryption key */ /* Get the Encryption key */
if (inst->encryption.enabled && !blr_get_encryption_key(inst)) if (inst->encryption.enabled && !blr_get_encryption_key(inst))
{ {
@ -723,6 +744,24 @@ createInstance(SERVICE *service, char **options)
inst->mariadb10_gtid = true; inst->mariadb10_gtid = true;
} }
if (!inst->mariadb10_master_gtid &&
inst->storage_type == BLR_BINLOG_STORAGE_TREE)
{
MXS_ERROR("%s: binlog_structure 'tree' mode can be enabled only"
" with MariaDB Master GTID registration feature."
" Please enable it with option"
" 'mariadb10_master_gtid = on'",
service->name);
free_instance(inst);
return NULL;
}
/* Log binlog structure storage mode */
MXS_NOTICE("%s: storing binlog files in %s",
service->name,
inst->storage_type == BLR_BINLOG_STORAGE_FLAT ?
"'flat' mode" :
"'tree' mode using GTID domain_id and server_id");
/* Enable MariaDB the GTID maps store */ /* Enable MariaDB the GTID maps store */
if (inst->mariadb10_compat && if (inst->mariadb10_compat &&
inst->mariadb10_gtid) inst->mariadb10_gtid)
@ -889,7 +928,7 @@ 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 or create a new one (000001) */ /* Find latest binlog file */
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",
@ -955,8 +994,18 @@ createInstance(SERVICE *service, char **options)
*/ */
if (inst->master_state == BLRM_UNCONNECTED) if (inst->master_state == BLRM_UNCONNECTED)
{ {
/* Check current binlog */ char f_prefix[BINLOG_FILE_EXTRA_INFO] = "";
MXS_NOTICE("Validating binlog file '%s' ...", if (inst->storage_type == BLR_BINLOG_STORAGE_TREE)
{
sprintf(f_prefix,
"%" PRIu32 "/%" PRIu32 "/",
inst->mariadb10_gtid_domain,
inst->orig_masterid);
}
/* Log current binlog, possibly with tree prefix */
MXS_NOTICE("Validating last binlog file '%s%s' ...",
f_prefix,
inst->binlog_name); inst->binlog_name);
if (!blr_check_binlog(inst)) if (!blr_check_binlog(inst))
@ -974,6 +1023,57 @@ createInstance(SERVICE *service, char **options)
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\n",
inst->binlog_name, inst->binlog_position, inst->current_pos); inst->binlog_name, inst->binlog_position, inst->current_pos);
/**
* Try loading last found GTID if the file size is <= 4 bytes
*/
if (inst->mariadb10_gtid &&
inst->current_pos <= 4)
{
MARIADB_GTID_INFO last_gtid = {};
/* Get last MariaDB GTID from repo */
if (blr_load_last_mariadb_gtid(inst, &last_gtid) &&
last_gtid.gtid != NULL)
{
/* Set MariaDB GTID */
strcpy(inst->last_mariadb_gtid, last_gtid.gtid);
MXS_FREE(last_gtid.gtid);
MXS_FREE(last_gtid.file);
}
else
{
/**
* In case of no GTID, inst->last_mariadb_gtid is empty.
*
* If connecting to master with GTID = "" the server
* will send data from its first binlog and
* this might overwrite existing data.
*
* Binlog server will not connect to master.
*
* It's needed to connect to MySQL admin interface
* and explicitely issue:
* SET @@GLOBAL.GTID_SLAVE_POS =''
* and START SLAVE
*/
/* Force STOPPED state */
inst->master_state = BLRM_SLAVE_STOPPED;
/* Set mysql_errno and error message */
inst->m_errno = BINLOG_FATAL_ERROR_READING;
inst->m_errmsg = MXS_STRDUP_A("HY000 Cannot find any GTID"
" in the GTID maps repo."
" Please issue SET @@GLOBAL.GTID_SLAVE_POS =''"
" and START SLAVE."
" Existing binlogs might be overwritten.");
MXS_ERROR("%s: %s",
inst->service->name,
inst->m_errmsg);
return (MXS_ROUTER *)inst;
}
}
/* 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)
{ {
@ -985,8 +1085,9 @@ createInstance(SERVICE *service, char **options)
inst->master_state = BLRM_SLAVE_STOPPED; inst->master_state = BLRM_SLAVE_STOPPED;
/* Set mysql_errno and error message */ /* Set mysql_errno and error message */
inst->m_errno = BINLOG_FATAL_ERROR_READING; inst->m_errno = BINLOG_FATAL_ERROR_READING;
inst->m_errmsg = mxs_strdup("HY000 Binlog encryption is Off but binlog file has " inst->m_errmsg = MXS_STRDUP_A("HY000 Binlog encryption is Off"
"the START_ENCRYPTION_EVENT"); " but current binlog file has"
" the START_ENCRYPTION_EVENT");
return (MXS_ROUTER *)inst; return (MXS_ROUTER *)inst;
} }
@ -998,6 +1099,11 @@ createInstance(SERVICE *service, char **options)
return (MXS_ROUTER *)inst; return (MXS_ROUTER *)inst;
} }
/**
* Free the router instance
*
* @param instance The router instance
*/
static void static void
free_instance(ROUTER_INSTANCE *instance) free_instance(ROUTER_INSTANCE *instance)
{ {
@ -1079,6 +1185,7 @@ newSession(MXS_ROUTER *instance, MXS_SESSION *session)
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));
/** /**
* Add this session to the list of active sessions. * Add this session to the list of active sessions.

View File

@ -104,6 +104,12 @@ MXS_BEGIN_DECLS
* in SHOW FULL BINARY LOGS * in SHOW FULL BINARY LOGS
*/ */
#define BINLOG_FILE_EXTRA_INFO GTID_MAX_LEN #define BINLOG_FILE_EXTRA_INFO GTID_MAX_LEN
enum blr_binlog_storage_type
{
BLR_BINLOG_STORAGE_FLAT,
BLR_BINLOG_STORAGE_TREEE
};
/** /**
* Supported Encryption algorithms * Supported Encryption algorithms
* *
@ -298,6 +304,24 @@ enum blr_event_state
BLR_EVENT_DONE, /*< The complete event was received */ BLR_EVENT_DONE, /*< The complete event was received */
}; };
/** MariaDB GTID elements */
typedef struct mariadb_gtid_elems
{
uint32_t domain_id; /*< The replication domain */
uint32_t server_id; /*< The serverid */
uint64_t seq_no; /*< The sequence number */
} MARIADB_GTID_ELEMS;
/** MariaDB GTID info */
typedef struct mariadb_gtid_info
{
char *gtid; /** MariaDB 10.x GTID, string value */
char *file; /** The binlog file */
uint64_t start; /** The BEGIN pos: i.e the GTID event */
uint64_t end; /** The next_pos in COMMIT event */
MARIADB_GTID_ELEMS gtid_elms; /** MariaDB 10.x GTID components */
} MARIADB_GTID_INFO;
/* Master Server configuration struct */ /* Master Server configuration struct */
typedef struct master_server_config typedef struct master_server_config
{ {
@ -380,6 +404,7 @@ typedef struct blfile
int refcnt; /*< Reference count for file */ int refcnt; /*< Reference count for file */
BLCACHE *cache; /*< Record cache for this file */ BLCACHE *cache; /*< Record cache for this file */
SPINLOCK lock; /*< The file lock */ SPINLOCK lock; /*< The file lock */
MARIADB_GTID_ELEMS info; /*< Elements for file prefix */
struct blfile *next; /*< Next file in list */ struct blfile *next; /*< Next file in list */
} BLFILE; } BLFILE;
@ -471,6 +496,7 @@ typedef struct router_slave
bool gtid_strict_mode;/*< MariaDB 10 Slave sets gtid_strict_mode */ bool gtid_strict_mode;/*< MariaDB 10 Slave sets gtid_strict_mode */
char *mariadb_gtid; /*< MariaDB 10 Slave connects with GTID */ char *mariadb_gtid; /*< MariaDB 10 Slave connects with GTID */
sqlite3 *gtid_maps; /*< GTID storage client handle, read only*/ sqlite3 *gtid_maps; /*< GTID storage client handle, read only*/
MARIADB_GTID_INFO f_info; /*< GTID info for file name prefix */
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t rses_chk_tail; skygw_chk_t rses_chk_tail;
#endif #endif
@ -553,35 +579,18 @@ typedef enum
BLRM_STANDALONE_SEEN /*< Received a standalone event, ie: a DDL */ BLRM_STANDALONE_SEEN /*< Received a standalone event, ie: a DDL */
} master_transaction_t; } master_transaction_t;
/** MariaDB GTID elements */
typedef struct mariadb_gtid_elems
{
uint32_t domain_id; /*< The replication domain */
uint32_t server_id; /*< The serverid */
uint64_t seq_no; /*< The sequence number */
} MARIADB_GTID_ELEMS;
/** Transaction Details */ /** Transaction Details */
typedef struct pending_transaction typedef struct pending_transaction
{ {
char gtid[GTID_MAX_LEN + 1]; /** MariaDB 10.x GTID */ char gtid[GTID_MAX_LEN + 1]; /** MariaDB 10.x GTID */
master_transaction_t state; /** Transaction state */ master_transaction_t state; /** Transaction state */
uint64_t start_pos; /** The BEGIN pos */ uint64_t start_pos; /** The BEGIN pos */
uint64_t end_pos; /** The next_pos in COMMIT event*/ uint64_t end_pos; /** The next_pos in COMMIT event */
MARIADB_GTID_ELEMS gtid_elms; /* MariaDB 10.x GTID components */ MARIADB_GTID_ELEMS gtid_elms; /** MariaDB 10.x GTID components */
bool standalone; /** Standalone event, such as DDL bool standalone; /** Standalone event, such as DDL
* no terminating COMMIT */ * no terminating COMMIT */
} PENDING_TRANSACTION; } PENDING_TRANSACTION;
/** MariaDB GTID info */
typedef struct mariadb_gtid_info
{
char *gtid; /** MariaDB 10.x GTID, string value */
char *file; /** The binlog file */
uint64_t start; /** The BEGIN pos: i.e the GTID event */
uint64_t end; /** The next_pos in COMMIT event*/
} MARIADB_GTID_INFO;
/** /**
* The per instance data for the router. * The per instance data for the router.
*/ */
@ -673,6 +682,7 @@ typedef struct router_instance
*/ */
uint32_t mariadb10_gtid_domain;/*< MariaDB 10 GTID Domain ID */ uint32_t mariadb10_gtid_domain;/*< MariaDB 10 GTID Domain ID */
sqlite3 *gtid_maps; /*< MariaDB 10 GTID storage */ sqlite3 *gtid_maps; /*< MariaDB 10 GTID storage */
enum binlog_storage_type storage_type;/*< Enables hierachical binlog file storage */
struct router_instance *next; struct router_instance *next;
} ROUTER_INSTANCE; } ROUTER_INSTANCE;
@ -894,7 +904,9 @@ extern int blr_file_init(ROUTER_INSTANCE *);
extern int blr_write_binlog_record(ROUTER_INSTANCE *, REP_HEADER *, uint32_t pos, uint8_t *); extern int blr_write_binlog_record(ROUTER_INSTANCE *, REP_HEADER *, uint32_t pos, uint8_t *);
extern int blr_file_rotate(ROUTER_INSTANCE *, char *, uint64_t); extern int blr_file_rotate(ROUTER_INSTANCE *, char *, uint64_t);
extern void blr_file_flush(ROUTER_INSTANCE *); extern void blr_file_flush(ROUTER_INSTANCE *);
extern BLFILE *blr_open_binlog(ROUTER_INSTANCE *, char *); extern BLFILE *blr_open_binlog(ROUTER_INSTANCE *,
const char *,
const MARIADB_GTID_INFO *);
extern GWBUF *blr_read_binlog(ROUTER_INSTANCE *, BLFILE *, unsigned long, REP_HEADER *, char *, extern GWBUF *blr_read_binlog(ROUTER_INSTANCE *, BLFILE *, unsigned long, REP_HEADER *, char *,
const SLAVE_ENCRYPTION_CTX *); const SLAVE_ENCRYPTION_CTX *);
extern void blr_close_binlog(ROUTER_INSTANCE *, BLFILE *); extern void blr_close_binlog(ROUTER_INSTANCE *, BLFILE *);
@ -902,7 +914,9 @@ extern unsigned long blr_file_size(BLFILE *);
extern int blr_statistics(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *); extern int blr_statistics(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *);
extern int blr_ping(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *); extern int blr_ping(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *);
extern int blr_send_custom_error(DCB *, int, int, char *, char *, unsigned int); extern int blr_send_custom_error(DCB *, int, int, char *, char *, unsigned int);
extern int blr_file_next_exists(ROUTER_INSTANCE *, ROUTER_SLAVE *); extern int blr_file_next_exists(ROUTER_INSTANCE *,
ROUTER_SLAVE *,
char *next_file);
uint32_t extract_field(uint8_t *src, int bits); uint32_t extract_field(uint8_t *src, int bits);
void blr_cache_read_master_data(ROUTER_INSTANCE *router); void blr_cache_read_master_data(ROUTER_INSTANCE *router);
int blr_read_events_all_events(ROUTER_INSTANCE *, BINLOG_FILE_FIX *, int); int blr_read_events_all_events(ROUTER_INSTANCE *, BINLOG_FILE_FIX *, int);

View File

@ -226,6 +226,16 @@ static void blr_report_checksum(REP_HEADER hdr,
bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router, bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
MARIADB_GTID_INFO *result); MARIADB_GTID_INFO *result);
bool blr_get_last_file(ROUTER_INSTANCE *router,
MARIADB_GTID_INFO *result);
static int gtid_file_select_cb(void *data,
int cols,
char** values,
char** names);
bool blr_compare_binlogs(ROUTER_INSTANCE *router,
const MARIADB_GTID_ELEMS *info,
const char *r_file,
const char *s_file);
/** /**
* MariaDB 10.1.7 Start Encryption event content * MariaDB 10.1.7 Start Encryption event content
@ -254,7 +264,8 @@ typedef struct start_encryption_event
* binlog to use and initialise it for writing, determining the * binlog to use and initialise it for writing, determining the
* next record to be fetched from the real master. * next record to be fetched from the real master.
* *
* @param router The router instance this defines the master for this replication chain * @param router The router instance
* @return 1 on success, 0 otherwise
*/ */
int int
blr_file_init(ROUTER_INSTANCE *router) blr_file_init(ROUTER_INSTANCE *router)
@ -265,6 +276,7 @@ blr_file_init(ROUTER_INSTANCE *router)
int root_len, i; int root_len, i;
DIR *dirp; DIR *dirp;
struct dirent *dp; struct dirent *dp;
int ret = 0;
if (router->binlogdir == NULL) if (router->binlogdir == NULL)
{ {
@ -303,7 +315,15 @@ blr_file_init(ROUTER_INSTANCE *router)
return 0; return 0;
} }
/* First try to find a binlog file number by reading the directory */ /**
* Find last written binary log in the binlog cache
* OR
* get it from GTID maps repo
*/
/* - 1 - try to find a binlog file number by reading the directory */
if (router->storage_type == BLR_BINLOG_STORAGE_FLAT)
{
root_len = strlen(router->fileroot); root_len = strlen(router->fileroot);
if ((dirp = opendir(path)) == NULL) if ((dirp = opendir(path)) == NULL)
{ {
@ -325,7 +345,6 @@ blr_file_init(ROUTER_INSTANCE *router)
} }
closedir(dirp); closedir(dirp);
file_found = 0; file_found = 0;
do do
{ {
@ -358,6 +377,56 @@ blr_file_init(ROUTER_INSTANCE *router)
blr_file_append(router, filename); blr_file_append(router, filename);
} }
return 1; return 1;
}
/* - 2 - Get last file in GTID maps repo */
else
{
MARIADB_GTID_INFO last_gtid = {};
char f_prefix[BINLOG_FILE_EXTRA_INFO] = "";
// SELECT LAST FILE
if (!blr_get_last_file(router, &last_gtid) ||
last_gtid.gtid == NULL)
{
MXS_INFO("%s: cannot find any GTID in GTID maps repo",
router->service->name);
return 0;
}
/** We don't care about sequence being 0
* as this is a placeholder for new file in the repo.
* In case of file without transactions
* there is no real GTID with sequence:
* there should be a GTID_LIST event which holds
* the last GTID.
* The event is parsed while reading the binlog.
* Right now we need only the domain_id, server_id
* and filename.
*/
sprintf(f_prefix,
"%" PRIu32 "/%" PRIu32 "",
last_gtid.gtid_elms.domain_id,
last_gtid.gtid_elms.server_id);
router->mariadb10_gtid_domain = last_gtid.gtid_elms.domain_id;
router->orig_masterid = last_gtid.gtid_elms.server_id;
snprintf(filename, PATH_MAX, "%s/%s/%s", path, f_prefix, last_gtid.file);
if (access(filename, R_OK) != -1)
{
blr_file_append(router, last_gtid.file);
ret = 1;
}
else
{
ret = blr_file_create(router, last_gtid.file);
}
MXS_FREE(last_gtid.gtid);
MXS_FREE(last_gtid.file);
return ret;
}
return 0;
} }
int int
@ -409,6 +478,39 @@ blr_file_create(ROUTER_INSTANCE *router, char *file)
strcpy(path, router->binlogdir); strcpy(path, router->binlogdir);
strcat(path, "/"); strcat(path, "/");
/**
* Create file using domain and server_id prefix
*/
if (router->mariadb10_compat &&
router->mariadb10_master_gtid &&
router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
char prefix[BINLOG_FILE_EXTRA_INFO];
sprintf(prefix,
"%" PRIu32 "/%" PRIu32 "/",
router->mariadb10_gtid_domain,
router->orig_masterid);
strcat(path, prefix);
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 '%s': [%d] %s",
router->service->name,
path,
errno,
mxs_strerror(errno));
return 0;
}
}
}
// Set final file name full path
strcat(path, file); strcat(path, file);
int fd = open(path, O_RDWR | O_CREAT, 0666); int fd = open(path, O_RDWR | O_CREAT, 0666);
@ -443,8 +545,10 @@ blr_file_create(ROUTER_INSTANCE *router, char *file)
gtid_elms.domain_id = router->mariadb10_gtid_domain; gtid_elms.domain_id = router->mariadb10_gtid_domain;
// router->orig_masterid keeps the original ID // router->orig_masterid keeps the original ID
gtid_elms.server_id = router->orig_masterid; gtid_elms.server_id = router->orig_masterid;
// Pos 4 only for end_pos // Pos 4 for start/end_pos
router->pending_transaction.end_pos = 4; router->pending_transaction.end_pos = 4;
router->pending_transaction.start_pos = 4;
// Update all the gtid_elms
memcpy(&router->pending_transaction.gtid_elms, memcpy(&router->pending_transaction.gtid_elms,
&gtid_elms, &gtid_elms,
sizeof(MARIADB_GTID_ELEMS)); sizeof(MARIADB_GTID_ELEMS));
@ -496,6 +600,21 @@ blr_file_append(ROUTER_INSTANCE *router, char *file)
strcpy(path, router->binlogdir); strcpy(path, router->binlogdir);
strcat(path, "/"); strcat(path, "/");
// Add file prefix
if (router->mariadb10_compat &&
router->mariadb10_master_gtid &&
router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
char prefix[BINLOG_FILE_EXTRA_INFO];
sprintf(prefix,
"%" PRIu32 "/%" PRIu32 "/",
router->mariadb10_gtid_domain,
router->orig_masterid);
strcat(path, prefix);
}
//Add filename
strcat(path, file); strcat(path, file);
if ((fd = open(path, flags, 0666)) == -1) if ((fd = open(path, flags, 0666)) == -1)
@ -670,10 +789,19 @@ blr_file_flush(ROUTER_INSTANCE *router)
* *
* @param router The router instance * @param router The router instance
* @param binlog The binlog filename * @param binlog The binlog filename
* @param info MariaDB GTID info
* with rep_domain and
* server_id.
* These two fileds are
* used as file prefix
* for binlog file name.
*
* @return a binlog file record * @return a binlog file record
*/ */
BLFILE * BLFILE *
blr_open_binlog(ROUTER_INSTANCE *router, char *binlog) blr_open_binlog(ROUTER_INSTANCE *router,
const char *binlog,
const MARIADB_GTID_INFO *info)
{ {
size_t len = strlen(binlog); size_t len = strlen(binlog);
if (len > BINLOG_FNAMELEN) if (len > BINLOG_FNAMELEN)
@ -683,7 +811,7 @@ blr_open_binlog(ROUTER_INSTANCE *router, char *binlog)
return NULL; return NULL;
} }
len += (strlen(router->binlogdir) + 1); // +1 for the /. len += (strlen(router->binlogdir) + 1); // +1 for the '.'
if (len > PATH_MAX) if (len > PATH_MAX)
{ {
MXS_ERROR("The length of %s/%s is longer than the maximum allowed length %d.", MXS_ERROR("The length of %s/%s is longer than the maximum allowed length %d.",
@ -716,10 +844,32 @@ blr_open_binlog(ROUTER_INSTANCE *router, char *binlog)
strcpy(file->binlogname, binlog); strcpy(file->binlogname, binlog);
file->refcnt = 1; file->refcnt = 1;
file->cache = 0; file->cache = 0;
/* Store additional file informations */
if (info)
{
memcpy(&file->info,
&info->gtid_elms,
sizeof(MARIADB_GTID_ELEMS));
}
spinlock_init(&file->lock); spinlock_init(&file->lock);
strcpy(path, router->binlogdir); strcpy(path, router->binlogdir);
strcat(path, "/"); strcat(path, "/");
// Add tree prefix: "domain_id/server_id"
if (info)
{
char t_prefix[BINLOG_FILE_EXTRA_INFO];
sprintf(t_prefix,
"%" PRIu32 "/%" PRIu32 "/",
info->gtid_elms.domain_id,
info->gtid_elms.server_id);
strcat(path, t_prefix);
}
// Add file name
strcat(path, binlog); strcat(path, binlog);
if ((file->fd = open(path, O_RDONLY, 0666)) == -1) if ((file->fd = open(path, O_RDONLY, 0666)) == -1)
@ -798,7 +948,11 @@ blr_read_binlog(ROUTER_INSTANCE *router,
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
spinlock_acquire(&file->lock); spinlock_acquire(&file->lock);
if (strcmp(router->binlog_name, file->binlogname) != 0) /* Check whether is current router file */
if (!blr_compare_binlogs(router,
&file->info,
router->binlog_name,
file->binlogname))
{ {
snprintf(errmsg, BINLOG_ERROR_MSG_LEN, "Requested position %lu is beyond " snprintf(errmsg, BINLOG_ERROR_MSG_LEN, "Requested position %lu is beyond "
"'closed' binlog file '%s', size %lu. Generating Error '1236'", "'closed' binlog file '%s', size %lu. Generating Error '1236'",
@ -824,7 +978,11 @@ blr_read_binlog(ROUTER_INSTANCE *router,
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
spinlock_acquire(&file->lock); spinlock_acquire(&file->lock);
if (strcmp(router->binlog_name, file->binlogname) == 0 && /* Check current router file and router position */
if (blr_compare_binlogs(router,
&file->info,
router->binlog_name,
file->binlogname) &&
pos >= router->binlog_position) pos >= router->binlog_position)
{ {
if (pos > router->binlog_position) if (pos > router->binlog_position)
@ -1075,7 +1233,7 @@ blr_read_binlog(ROUTER_INSTANCE *router,
gwbuf_free(result); gwbuf_free(result);
/** /**
* Binlog event check based on Replication Header content and pos * Binlog event check based on Rep Header content and pos
*/ */
if (!blr_binlog_event_check(router, pos, hdr, file->binlogname, errmsg)) if (!blr_binlog_event_check(router, pos, hdr, file->binlogname, errmsg))
{ {
@ -1083,7 +1241,7 @@ blr_read_binlog(ROUTER_INSTANCE *router,
return NULL; return NULL;
} }
/* Set the decrypted event as result*/ /* Set the decrypted event as result */
result = decrypted_event; result = decrypted_event;
} }
@ -1143,7 +1301,7 @@ blr_close_binlog(ROUTER_INSTANCE *router, BLFILE *file)
/** /**
* Log the event header of binlog event * Log the event header of binlog event
* *
* @param priority The syslog priority of the message (LOG_ERR, LOG_WARNING, etc.) * @param priority The syslog priority (LOG_ERR, LOG_WARNING, etc.)
* @param msg A message strign to preceed the header with * @param msg A message strign to preceed the header with
* @param ptr The event header raw data * @param ptr The event header raw data
*/ */
@ -1294,21 +1452,128 @@ blr_cache_read_response(ROUTER_INSTANCE *router, char *response)
* *
* @param router The router instance * @param router The router instance
* @param slave The slave in question * @param slave The slave in question
* @param next_file The next_file buffer
* @return 0 if the next file does not exist * @return 0 if the next file does not exist
*/ */
int int
blr_file_next_exists(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave) blr_file_next_exists(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave,
char *next_file)
{ {
char *sptr, buf[BLRM_BINLOG_NAME_STR_LEN], bigbuf[PATH_MAX + 1]; char *errmsg = NULL;
int filenum; char *sptr;
char bigbuf[PATH_MAX + 1];
char select_query[GTID_SQL_BUFFER_SIZE];
const char select_tpl[] = "SELECT "
"(rep_domain || '/' || server_id || '/' || binlog_file) AS file, "
"rep_domain, "
"server_id, "
"binlog_file "
"FROM gtid_maps "
"WHERE id = "
"(SELECT MAX(id) "
"FROM gtid_maps "
"WHERE (binlog_file='%s' AND "
"rep_domain = %" PRIu32 " AND "
"server_id = %" PRIu32 ")) + 1;";
MARIADB_GTID_INFO result = {};
MARIADB_GTID_ELEMS gtid_elms = {};
if ((sptr = strrchr(slave->binlogfile, '.')) == NULL) if ((sptr = strrchr(slave->binlogfile, '.')) == NULL)
{ {
next_file[0] = '\0';
return 0; return 0;
} }
/**
* The next file to read could be determined in two ways:
* - 1 - file sequence +1
* - 2 - next file form GTID maps repo
*/
if (router->storage_type == BLR_BINLOG_STORAGE_FLAT)
{
/**
* Next file is the one with +1 in sequence
*/
char buf[BINLOG_FNAMELEN + 1];
int filenum;
filenum = atoi(sptr + 1); filenum = atoi(sptr + 1);
sprintf(buf, BINLOG_NAMEFMT, router->fileroot, filenum + 1); sprintf(buf, BINLOG_NAMEFMT, router->fileroot, filenum + 1);
sprintf(bigbuf, "%s/%s", router->binlogdir, buf); sprintf(bigbuf, "%s/%s", router->binlogdir, buf);
// Set the new file name in the output
strncpy(next_file, buf, BINLOG_FNAMELEN);
next_file[BINLOG_FNAMELEN] = '\0';
}
else
{
/**
* Next file is selected in GTID maps repo
*/
snprintf(select_query,
GTID_SQL_BUFFER_SIZE,
select_tpl,
slave->binlogfile,
slave->f_info.gtid_elms.domain_id,
slave->f_info.gtid_elms.server_id);
/* Find the GTID */
if (sqlite3_exec(router->gtid_maps,
select_query,
gtid_file_select_cb,
&result,
&errmsg) != SQLITE_OK)
{
MXS_ERROR("Failed to select next file of %s"
" from GTID maps DB: %s, select [%s]",
slave->binlogfile,
errmsg,
select_query);
sqlite3_free(errmsg);
next_file[0] = '\0';
return 0;
}
MXS_INFO("The next Binlog file from GTID maps repo is %s",
result.file);
// Check whether the query has a result
if (result.file)
{
// Full filename path
sprintf(bigbuf,
"%s/%" PRIu32 "/%" PRIu32 "/%s",
router->binlogdir,
result.gtid_elms.domain_id,
result.gtid_elms.server_id,
result.file);
// Set the new file name in the output
strncpy(next_file, result.file, BINLOG_FNAMELEN);
next_file[BINLOG_FNAMELEN] = '\0';
/**
* Update GTID elems in the slave->f_info struct:
* file and domain_id / server_id
*/
if (slave->f_info.file)
{
MXS_FREE(slave->f_info.file);
slave->f_info.file = MXS_STRDUP_A(result.file);
}
slave->f_info.gtid_elms.domain_id = result.gtid_elms.domain_id;
slave->f_info.gtid_elms.server_id = result.gtid_elms.server_id;
MXS_FREE(result.file);
}
else
{
next_file[0] = '\0';
return 0;
}
}
// Check whether the new file exists
if (access(bigbuf, R_OK) == -1) if (access(bigbuf, R_OK) == -1)
{ {
return 0; return 0;
@ -2137,6 +2402,7 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
*/ */
if (router->mariadb10_compat) if (router->mariadb10_compat)
{ {
char f_prefix[BINLOG_FILE_EXTRA_INFO] = "";
if (hdr.event_type == MARIADB10_GTID_GTID_LIST_EVENT) if (hdr.event_type == MARIADB10_GTID_GTID_LIST_EVENT)
{ {
char mariadb_gtid[GTID_MAX_LEN + 1] = ""; char mariadb_gtid[GTID_MAX_LEN + 1] = "";
@ -2164,14 +2430,22 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
snprintf(mariadb_gtid, snprintf(mariadb_gtid,
GTID_MAX_LEN, GTID_MAX_LEN,
"%u-%u-%lu", "%" PRIu32 "-%" PRIu32 "-%" PRIu64 "",
domainid, domainid,
serverid, serverid,
n_sequence); n_sequence);
MXS_DEBUG("GTID List Event has %lu GTIDs, first is %s", MXS_DEBUG("GTID List Event has %lu GTIDs, first one is %s",
n_gtids, n_gtids,
mariadb_gtid); mariadb_gtid);
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
sprintf(f_prefix,
"%" PRIu32 "/%" PRIu32 "/",
domainid,
serverid);
}
} }
else else
{ {
@ -2187,17 +2461,41 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
"%s", "%s",
gtid_info.gtid); gtid_info.gtid);
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
sprintf(f_prefix,
"%" PRIu32 "/%" PRIu32 "/",
gtid_info.gtid_elms.domain_id,
gtid_info.gtid_elms.server_id);
}
if (router->mariadb10_gtid)
{
MXS_INFO("Last found MariaDB 10 GTID"
" in GTID maps repo was (%s). File %s%s",
mariadb_gtid,
f_prefix,
gtid_info.file);
}
MXS_FREE(gtid_info.gtid); MXS_FREE(gtid_info.gtid);
MXS_FREE(gtid_info.file); MXS_FREE(gtid_info.file);
} }
} }
/* Set MariaDB GTID */
if (router->mariadb10_gtid) if (router->mariadb10_gtid)
{ {
/* Set MariaDB GTID */
strcpy(router->last_mariadb_gtid, mariadb_gtid); strcpy(router->last_mariadb_gtid, mariadb_gtid);
MXS_INFO("Last MariaDB 10 GTID was (%s).",
router->last_mariadb_gtid); if (router->mariadb10_gtid)
{
MXS_INFO("Last MariaDB 10 GTID (GTID_LIST event)"
" is (%s). File %s%s",
mariadb_gtid,
f_prefix,
router->binlog_name);
}
} }
} }
} }
@ -3438,7 +3736,8 @@ static void blr_report_checksum(REP_HEADER hdr, const uint8_t *buffer, char *out
*/ */
bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst) bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
{ {
static const char insert_tpl[] = "INSERT OR IGNORE INTO gtid_maps(" int sql_ret;
static const char insert_tpl[] = "INSERT OR FAIL INTO gtid_maps("
"rep_domain, " "rep_domain, "
"server_id, " "server_id, "
"sequence, " "sequence, "
@ -3452,8 +3751,16 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
"\"%s\", " "\"%s\", "
"%" PRIu64 ", " "%" PRIu64 ", "
"%" PRIu64 ");"; "%" PRIu64 ");";
static const char update_tpl[] = "UPDATE gtid_maps SET "
"start_pos = %" PRIu64 ", "
"end_pos = %" PRIu64 " "
"WHERE rep_domain = %" PRIu32 " AND "
"server_id = %" PRIu32 " AND "
"sequence = %" PRIu64 " AND "
"binlog_file = \"%s\";";
char *errmsg; char *errmsg;
char insert_sql[GTID_SQL_BUFFER_SIZE]; char sql_stmt[GTID_SQL_BUFFER_SIZE];
MARIADB_GTID_INFO gtid_info; MARIADB_GTID_INFO gtid_info;
MARIADB_GTID_ELEMS gtid_elms; MARIADB_GTID_ELEMS gtid_elms;
@ -3465,8 +3772,8 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
&inst->pending_transaction.gtid_elms, &inst->pending_transaction.gtid_elms,
sizeof(MARIADB_GTID_ELEMS)); sizeof(MARIADB_GTID_ELEMS));
/* Save GTID into repo */ /* Prepare INSERT SQL */
snprintf(insert_sql, snprintf(sql_stmt,
GTID_SQL_BUFFER_SIZE, GTID_SQL_BUFFER_SIZE,
insert_tpl, insert_tpl,
gtid_elms.domain_id, gtid_elms.domain_id,
@ -3477,8 +3784,47 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
gtid_info.end); gtid_info.end);
/* Save GTID into repo */ /* Save GTID into repo */
if (sqlite3_exec(inst->gtid_maps, insert_sql, NULL, NULL, if ((sql_ret = sqlite3_exec(inst->gtid_maps,
&errmsg) != SQLITE_OK) sql_stmt,
NULL,
NULL,
&errmsg)) != SQLITE_OK)
{
if (sql_ret == SQLITE_CONSTRAINT)
{
/* Prepare UPDATE SQL */
snprintf(sql_stmt,
GTID_SQL_BUFFER_SIZE,
update_tpl,
gtid_info.start,
gtid_info.end,
gtid_elms.domain_id,
gtid_elms.server_id,
gtid_elms.seq_no,
gtid_info.file);
/* Update GTID into repo */
if ((sql_ret = sqlite3_exec(inst->gtid_maps,
sql_stmt,
NULL,
NULL,
&errmsg)) != SQLITE_OK)
{
MXS_ERROR("Service %s: failed to update GTID %s for %s:%lu,%lu "
"into gtid_maps database: %s",
inst->service->name,
gtid_info.gtid,
gtid_info.file,
gtid_info.start,
gtid_info.end,
errmsg);
sqlite3_free(errmsg);
return false;
}
/* Remove SQLITE_CONSTRAINT error message */
sqlite3_free(errmsg);
}
else
{ {
MXS_ERROR("Service %s: failed to insert GTID %s for %s:%lu,%lu " MXS_ERROR("Service %s: failed to insert GTID %s for %s:%lu,%lu "
"into gtid_maps database: %s", "into gtid_maps database: %s",
@ -3491,13 +3837,14 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
sqlite3_free(errmsg); sqlite3_free(errmsg);
return false; return false;
} }
}
MXS_DEBUG("Saved MariaDB GTID '%s', %s:%lu,%lu, insert SQL [%s]", MXS_DEBUG("Saved/udated MariaDB GTID '%s', %s:%lu,%lu, SQL [%s]",
gtid_info.gtid, gtid_info.gtid,
inst->binlog_name, inst->binlog_name,
gtid_info.start, gtid_info.start,
gtid_info.end, gtid_info.end,
insert_sql); sql_stmt);
return true; return true;
} }
@ -3527,8 +3874,22 @@ static int gtid_select_cb(void *data, int cols, char** values, char** names)
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)
{
result->gtid_elms.domain_id = atoll(values[4]);
result->gtid_elms.server_id = atoll(values[5]);
result->gtid_elms.seq_no = atoll(values[6]);
}
ss_dassert(result->start > 0 && result->end > result->start); ss_dassert(result->start > 0 && result->start > 0);
if (result->start > 4)
{
ss_dassert(result->end > result->start);
}
else
{
ss_dassert(result->start > 0 && result->start > 0);
}
} }
return 0; return 0;
@ -3555,7 +3916,10 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
" '-' || sequence) AS gtid, " " '-' || sequence) AS gtid, "
"binlog_file, " "binlog_file, "
"start_pos, " "start_pos, "
"end_pos " "end_pos, "
"rep_domain, "
"server_id, "
"sequence "
"FROM gtid_maps " "FROM gtid_maps "
"WHERE (rep_domain = %" PRIu32 " AND " "WHERE (rep_domain = %" PRIu32 " AND "
"server_id = %" PRIu32 " AND " "server_id = %" PRIu32 " AND "
@ -3589,7 +3953,16 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
sqlite3_free(errmsg); sqlite3_free(errmsg);
return false; return false;
} }
else
{
if (result->gtid)
{
MXS_INFO("Binlog file to read from is %" PRIu32 "/%" PRIu32 "/%s",
result->gtid_elms.domain_id,
result->gtid_elms.server_id,
result->file);
}
}
return result->gtid ? true : false; return result->gtid ? true : false;
} }
@ -3688,7 +4061,6 @@ bool blr_parse_gtid(const char *gtid, MARIADB_GTID_ELEMS *info)
* Get MariaDB GTID from repo * Get MariaDB GTID from repo
* *
* @param router The current router instance * @param router The current router instance
* @param gtid The GTID to look for
* @param result The (allocated) ouput data to fill * @param result The (allocated) ouput data to fill
* @return False on sqlite errors * @return False on sqlite errors
* True even if the gtid_maps is empty * True even if the gtid_maps is empty
@ -3706,19 +4078,25 @@ bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
" '-' || sequence) AS gtid, " " '-' || sequence) AS gtid, "
"binlog_file, " "binlog_file, "
"start_pos, " "start_pos, "
"end_pos " "end_pos, "
"rep_domain, "
"server_id, "
"sequence "
"FROM gtid_maps " "FROM gtid_maps "
"WHERE id = " "WHERE id = "
"(SELECT MAX(id) FROM gtid_maps);"; "(SELECT MAX(id) "
"FROM gtid_maps "
"WHERE start_pos > 4);";
/* Find the GTID */ /* Find the last GTID */
if (sqlite3_exec(router->gtid_maps, if (sqlite3_exec(router->gtid_maps,
last_gtid, last_gtid,
gtid_select_cb, gtid_select_cb,
result, result,
&errmsg) != SQLITE_OK) &errmsg) != SQLITE_OK)
{ {
MXS_ERROR("Failed to select last GTID from GTID maps DB: %s, select [%s]", MXS_ERROR("Failed to select last GTID"
" from GTID maps DB: %s, select [%s]",
errmsg, errmsg,
last_gtid); last_gtid);
sqlite3_free(errmsg); sqlite3_free(errmsg);
@ -3727,3 +4105,127 @@ bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
return true; return true;
} }
/**
* Select callback for blr_file_next_exists()
*
* @param data Data pointer from caller
* @param cols Number of columns
* @param values The values
* @param names The column names
*
* @return 0 on success, 1 otherwise
*/
static int gtid_file_select_cb(void *data,
int cols,
char** values,
char** names)
{
MARIADB_GTID_INFO *result = (MARIADB_GTID_INFO *)data;
ss_dassert(cols >= 4);
if (values[0] &&
values[1] &&
values[2] &&
values[3])
{
result->file = MXS_STRDUP_A(values[3]);
result->gtid_elms.domain_id = atoll(values[1]);
result->gtid_elms.server_id = atoll(values[2]);
}
return 0;
}
/**
* Get Last file from GTID from repo
*
* @param router The current router instance
* @param result The (allocated) ouput data to fill
* @return False on sqlite errors
* True even if the gtid_maps is empty
* The caller must check result->gtid value
*/
bool blr_get_last_file(ROUTER_INSTANCE *router,
MARIADB_GTID_INFO *result)
{
char *errmsg = NULL;
MARIADB_GTID_ELEMS gtid_elms = {};
static const char last_gtid[] = "SELECT "
"(rep_domain ||"
" '-' || server_id ||"
" '-' || sequence) AS gtid, "
"binlog_file, "
"start_pos, "
"end_pos, "
"rep_domain, "
"server_id, "
"sequence "
"FROM gtid_maps "
"WHERE id = "
"(SELECT MAX(id) FROM gtid_maps);";
/* Find the the last file */
if (sqlite3_exec(router->gtid_maps,
last_gtid,
gtid_select_cb,
result,
&errmsg) != SQLITE_OK)
{
MXS_ERROR("Failed to select last written binlog file"
" from GTID maps DB: %s, select [%s]",
errmsg,
last_gtid);
sqlite3_free(errmsg);
return false;
}
return true;
}
/**
* Compare the specified router file and slave one
*
* @param router The router instance
* @param info Additional file info
* @param r_file The router binlog file
* @param s_file The slave file
* @return True or false
*/
bool blr_compare_binlogs(ROUTER_INSTANCE *router,
const MARIADB_GTID_ELEMS *info,
const char *r_file,
const char *s_file)
{
// Just strcmp()
if (router->storage_type == BLR_BINLOG_STORAGE_FLAT)
{
return strcmp(r_file, s_file) == 0;
}
else
{
// domain_id, server_id and strcmp()
return ((router->mariadb10_gtid_domain == info->domain_id) &&
(router->orig_masterid == info->server_id) &&
strcmp(r_file, r_file) == 0);
}
}
/**
* Check whether the current slave file is the current file
* being written by the router
*
* @param router The router instance
* @param slave The connected slave
* @return True or false
*/
bool blr_is_current_binlog(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave)
{
return blr_compare_binlogs(router,
&slave->f_info.gtid_elms,
router->binlog_name,
slave->binlogfile);
}

View File

@ -3246,6 +3246,8 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
router->last_written = hdr->next_pos; router->last_written = hdr->next_pos;
router->last_event_pos = router->current_pos; router->last_event_pos = router->current_pos;
router->current_pos = hdr->next_pos; router->current_pos = hdr->next_pos;
router->binlog_position = router->current_pos;
router->current_safe_event = router->current_pos;
spinlock_release(&router->binlog_lock); spinlock_release(&router->binlog_lock);
} }

View File

@ -142,7 +142,8 @@ uint8_t *blr_build_header(GWBUF *pkt, REP_HEADER *hdr);
int blr_slave_callback(DCB *dcb, DCB_REASON reason, void *data); int blr_slave_callback(DCB *dcb, DCB_REASON reason, void *data);
static int blr_slave_fake_rotate(ROUTER_INSTANCE *router, static int blr_slave_fake_rotate(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave, ROUTER_SLAVE *slave,
BLFILE** filep); BLFILE** filep,
const char *new_file);
static uint32_t blr_slave_send_fde(ROUTER_INSTANCE *router, static uint32_t blr_slave_send_fde(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave, ROUTER_SLAVE *slave,
GWBUF *fde); GWBUF *fde);
@ -313,7 +314,8 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
static inline void blr_get_file_fullpath(const char *binlog_file, static inline void blr_get_file_fullpath(const char *binlog_file,
const char *root_dir, const char *root_dir,
char *full_path); char *full_path,
const char *f_prefix);
static int blr_show_binary_logs(ROUTER_INSTANCE *router, static int blr_show_binary_logs(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave, ROUTER_SLAVE *slave,
const char *extra_data); const char *extra_data);
@ -332,6 +334,12 @@ static bool blr_handle_complex_select(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave, ROUTER_SLAVE *slave,
const char *col1, const char *col1,
const char *coln); const char *coln);
extern bool blr_is_current_binlog(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave);
extern bool blr_compare_binlogs(ROUTER_INSTANCE *router,
MARIADB_GTID_INFO *slave,
const char *r_file,
const char *s_file);
/** /**
* Process a request packet from the slave server. * Process a request packet from the slave server.
* *
@ -1808,7 +1816,7 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
if (router->pending_transaction.state > BLRM_NO_TRANSACTION && if (router->pending_transaction.state > BLRM_NO_TRANSACTION &&
strcmp(router->binlog_name, slave->binlogfile) == 0 && blr_is_current_binlog(router, slave) &&
(slave->binlog_pos > router->binlog_position)) (slave->binlog_pos > router->binlog_position))
{ {
force_disconnect = true; force_disconnect = true;
@ -1855,7 +1863,8 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue
/** /**
* Check whether the request file is empty * Check whether the request file is empty
* and try using next file in sequence. * and try using next file in sequence or next one
* based on GTID mpas.
* If one or more files have been skipped then * If one or more files have been skipped then
* the slave->binlog_pos is set to 4 and * the slave->binlog_pos is set to 4 and
* slave->binlogname set to new filename. * slave->binlogname set to new filename.
@ -2046,6 +2055,9 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
int rotating = 0; int rotating = 0;
long burst_size; long burst_size;
char read_errmsg[BINLOG_ERROR_MSG_LEN + 1]; char read_errmsg[BINLOG_ERROR_MSG_LEN + 1];
MARIADB_GTID_INFO *f_tree = router->storage_type == BLR_BINLOG_STORAGE_TREE ?
&slave->f_info :
NULL;
read_errmsg[BINLOG_ERROR_MSG_LEN] = '\0'; read_errmsg[BINLOG_ERROR_MSG_LEN] = '\0';
@ -2068,7 +2080,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
/* check for a pending transaction and safe position */ /* check for a pending transaction and safe position */
if (router->pending_transaction.state > BLRM_NO_TRANSACTION && if (router->pending_transaction.state > BLRM_NO_TRANSACTION &&
strcmp(router->binlog_name, slave->binlogfile) == 0 && blr_is_current_binlog(router, slave) &&
(slave->binlog_pos > router->binlog_position)) (slave->binlog_pos > router->binlog_position))
{ {
do_return = 1; do_return = 1;
@ -2098,7 +2110,9 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
if (file == NULL) if (file == NULL)
{ {
rotating = router->rotating; rotating = router->rotating;
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL) if ((file = blr_open_binlog(router,
slave->binlogfile,
f_tree)) == NULL)
{ {
char err_msg[BINLOG_ERROR_MSG_LEN + 1]; char err_msg[BINLOG_ERROR_MSG_LEN + 1];
err_msg[BINLOG_ERROR_MSG_LEN] = '\0'; err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
@ -2244,9 +2258,13 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
beat1 = hkheartbeat; beat1 = hkheartbeat;
#ifdef BLFILE_IN_SLAVE #ifdef BLFILE_IN_SLAVE
if ((slave->file = blr_open_binlog(router, slave->binlogfile)) == NULL) if ((slave->file = blr_open_binlog(router,
slave->binlogfile,
f_tree)) == NULL)
#else #else
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL) if ((file = blr_open_binlog(router,
slave->binlogfile,
f_tree)) == NULL)
#endif #endif
{ {
char err_msg[BINLOG_ERROR_MSG_LEN + 1]; char err_msg[BINLOG_ERROR_MSG_LEN + 1];
@ -2276,14 +2294,19 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
/* Send error that stops slave replication */ /* Send error that stops slave replication */
blr_send_custom_error(slave->dcb, blr_send_custom_error(slave->dcb,
(slave->seqno - 1), slave->seqno,
0, 0,
err_msg, err_msg,
"HY000", "HY000",
BINLOG_FATAL_ERROR_READING); BINLOG_FATAL_ERROR_READING);
gwbuf_free(record);
record = NULL;
slave->state = BLRS_ERRORED;
dcb_close(slave->dcb); dcb_close(slave->dcb);
break;
return 0;
} }
#ifdef BLFILE_IN_SLAVE #ifdef BLFILE_IN_SLAVE
file = slave->file; file = slave->file;
@ -2440,7 +2463,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
poll_fake_write_event(slave->dcb); poll_fake_write_event(slave->dcb);
} }
else if (slave->binlog_pos == router->binlog_position && else if (slave->binlog_pos == router->binlog_position &&
strcmp(slave->binlogfile, router->binlog_name) == 0) blr_is_current_binlog(router, slave))
{ {
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
spinlock_acquire(&slave->catch_lock); spinlock_acquire(&slave->catch_lock);
@ -2450,7 +2473,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
* and slave->catch_lock. * and slave->catch_lock.
*/ */
if (slave->binlog_pos != router->binlog_position || if (slave->binlog_pos != router->binlog_position ||
strcmp(slave->binlogfile, router->binlog_name) != 0) !blr_is_current_binlog(router, slave))
{ {
slave->cstate |= CS_EXPECTCB; slave->cstate |= CS_EXPECTCB;
spinlock_release(&slave->catch_lock); spinlock_release(&slave->catch_lock);
@ -2473,10 +2496,11 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
} }
else else
{ {
if (slave->binlog_pos >= blr_file_size(file) char next_file[BINLOG_FNAMELEN + 1] = "";
&& router->rotating == 0 if (slave->binlog_pos >= blr_file_size(file) &&
&& strcmp(router->binlog_name, slave->binlogfile) != 0 router->rotating == 0 &&
&& blr_file_next_exists(router, slave)) (!blr_is_current_binlog(router, slave) &&
blr_file_next_exists(router, slave, next_file)))
{ {
/* We may have reached the end of file of a non-current /* We may have reached the end of file of a non-current
* binlog file. * binlog file.
@ -2501,10 +2525,11 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
MXS_FREE(slave->encryption_ctx); MXS_FREE(slave->encryption_ctx);
slave->encryption_ctx = NULL; slave->encryption_ctx = NULL;
/* Now pass the next_file to blr_slave_fake_rotate() */
#ifdef BLFILE_IN_SLAVE #ifdef BLFILE_IN_SLAVE
if (blr_slave_fake_rotate(router, slave, &slave->file)) if (blr_slave_fake_rotate(router, slave, &slave->file, next_file))
#else #else
if (blr_slave_fake_rotate(router, slave, &file)) if (blr_slave_fake_rotate(router, slave, &file, next_file))
#endif #endif
{ {
spinlock_acquire(&slave->catch_lock); spinlock_acquire(&slave->catch_lock);
@ -2516,6 +2541,10 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
{ {
slave->state = BLRS_ERRORED; slave->state = BLRS_ERRORED;
dcb_close(slave->dcb); dcb_close(slave->dcb);
#ifndef BLFILE_IN_SLAVE
blr_close_binlog(router, file);
#endif
return 0;
} }
} }
else else
@ -2604,6 +2633,7 @@ blr_slave_callback(DCB *dcb, DCB_REASON reason, void *data)
/** /**
* Rotate the slave to the new binlog file * Rotate the slave to the new binlog file
* *
* @param router The router instance
* @param slave The slave instance * @param slave The slave instance
* @param ptr The rotate event (minus header and OK byte) * @param ptr The rotate event (minus header and OK byte)
*/ */
@ -2632,7 +2662,7 @@ blr_slave_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint8_t *ptr)
/** /**
* Generate an internal rotate event that we can use to cause * Generate an internal rotate event that we can use to cause
* the slave to move beyond a binlog file * the slave to move beyond a binlog file
* that is missisng the rotate eent at the end. * that is missisng the rotate event at the end.
* *
* @param router The router instance * @param router The router instance
* @param slave The slave to rotate * @param slave The slave to rotate
@ -2641,26 +2671,30 @@ blr_slave_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint8_t *ptr)
static int static int
blr_slave_fake_rotate(ROUTER_INSTANCE *router, blr_slave_fake_rotate(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave, ROUTER_SLAVE *slave,
BLFILE** filep) BLFILE** filep,
const char *new_file)
{ {
char *sptr; char *sptr;
int filenum; int filenum;
GWBUF *r_event; GWBUF *r_event;
MARIADB_GTID_INFO *f_tree = router->storage_type == BLR_BINLOG_STORAGE_TREE ?
&slave->f_info :
NULL;
if ((sptr = strrchr(slave->binlogfile, '.')) == NULL) if ((sptr = strrchr(new_file, '.')) == NULL)
{ {
return 0; return 0;
} }
blr_close_binlog(router, *filep); blr_close_binlog(router, *filep);
filenum = atoi(sptr + 1);
sprintf(slave->binlogfile,
BINLOG_NAMEFMT,
router->fileroot,
filenum + 1);
/* Set Pos = 4 */ /* Set Pos = 4 */
slave->binlog_pos = 4; slave->binlog_pos = 4;
if ((*filep = blr_open_binlog(router, slave->binlogfile)) == NULL) /* Set Filename */
strcpy(slave->binlogfile, new_file);
if ((*filep = blr_open_binlog(router,
new_file,
f_tree)) == NULL)
{ {
return 0; return 0;
} }
@ -2668,7 +2702,7 @@ blr_slave_fake_rotate(ROUTER_INSTANCE *router,
/* Build Fake Rotate Event */ /* Build Fake Rotate Event */
r_event = blr_build_fake_rotate_event(slave, r_event = blr_build_fake_rotate_event(slave,
slave->binlog_pos, slave->binlog_pos,
slave->binlogfile, new_file,
router->masterid); router->masterid);
return r_event ? slave->dcb->func.write(slave->dcb, r_event) : 0; return r_event ? slave->dcb->func.write(slave->dcb, r_event) : 0;
@ -2690,12 +2724,17 @@ blr_slave_read_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
uint8_t *ptr; uint8_t *ptr;
uint32_t chksum; uint32_t chksum;
char err_msg[BINLOG_ERROR_MSG_LEN + 1]; char err_msg[BINLOG_ERROR_MSG_LEN + 1];
MARIADB_GTID_INFO *f_tree = router->storage_type == BLR_BINLOG_STORAGE_TREE ?
&slave->f_info :
NULL;
err_msg[BINLOG_ERROR_MSG_LEN] = '\0'; err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
memset(&hdr, 0, BINLOG_EVENT_HDR_LEN); memset(&hdr, 0, BINLOG_EVENT_HDR_LEN);
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL) if ((file = blr_open_binlog(router,
slave->binlogfile,
f_tree)) == NULL)
{ {
return NULL; return NULL;
} }
@ -5899,13 +5938,18 @@ blr_slave_read_ste(ROUTER_INSTANCE *router,
uint8_t *ptr; uint8_t *ptr;
uint32_t chksum; uint32_t chksum;
char err_msg[BINLOG_ERROR_MSG_LEN + 1]; char err_msg[BINLOG_ERROR_MSG_LEN + 1];
MARIADB_GTID_INFO *f_tree = router->storage_type == BLR_BINLOG_STORAGE_TREE ?
&slave->f_info :
NULL;
err_msg[BINLOG_ERROR_MSG_LEN] = '\0'; err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
memset(&hdr, 0, BINLOG_EVENT_HDR_LEN); memset(&hdr, 0, BINLOG_EVENT_HDR_LEN);
BLFILE *file; BLFILE *file;
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL) if ((file = blr_open_binlog(router,
slave->binlogfile,
f_tree)) == NULL)
{ {
return 0; return 0;
} }
@ -6374,6 +6418,26 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
bool req_file, bool req_file,
unsigned long req_pos) unsigned long req_pos)
{ {
MARIADB_GTID_INFO f_gtid = {};
uint32_t router_pos;
char router_curr_file[BINLOG_FNAMELEN + 1];
char last_gtid[GTID_MAX_LEN + 1];
spinlock_acquire(&router->binlog_lock);
// Set gtid as current router gtid
strcpy(last_gtid, router->last_mariadb_gtid);
// Set file as router current file
strcpy(router_curr_file, router->binlog_name);
// Set safe postion of current ruter file
router_pos = router->binlog_position;
// Set domain_id, server_id in case of empty/not found GTID
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
f_gtid.gtid_elms.domain_id = router->mariadb10_gtid_domain;
f_gtid.gtid_elms.server_id = router->orig_masterid;
}
spinlock_release(&router->binlog_lock);
MXS_INFO("Slave %lu is registering with MariaDB GTID '%s'", MXS_INFO("Slave %lu is registering with MariaDB GTID '%s'",
(unsigned long)slave->serverid, (unsigned long)slave->serverid,
slave->mariadb_gtid); slave->mariadb_gtid);
@ -6384,15 +6448,22 @@ 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
*/ */
strcpy(slave->binlogfile, router_curr_file);
slave->binlog_pos = 4;
MXS_INFO("Slave %lu is registering with empty GTID:" MXS_INFO("Slave %lu is registering with empty GTID:"
" sending events from current binlog file %s, pos %lu", " sending events from current binlog file %s,"
" pos %" PRIu32 "",
(unsigned long)slave->serverid, (unsigned long)slave->serverid,
slave->binlogfile, slave->binlogfile,
(unsigned long)slave->binlog_pos); slave->binlog_pos);
/* Add GTID details to slave struct */
memcpy(&slave->f_info, &f_gtid, sizeof(MARIADB_GTID_INFO));
return true;
} }
else else
{ {
MARIADB_GTID_INFO f_gtid = {};
char dbpath[PATH_MAX + 1]; char dbpath[PATH_MAX + 1];
snprintf(dbpath, sizeof(dbpath), "/%s/%s", snprintf(dbpath, sizeof(dbpath), "/%s/%s",
router->binlogdir, GTID_MAPS_DB); router->binlogdir, GTID_MAPS_DB);
@ -6412,6 +6483,7 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
sqlite3_errmsg(slave->gtid_maps)); sqlite3_errmsg(slave->gtid_maps));
slave->gtid_maps = NULL; slave->gtid_maps = NULL;
return false;
} }
else else
{ {
@ -6447,16 +6519,34 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
} }
else else
{ {
/* Right now: just use current router binlog file pos 4 */ /* No strict mode: */
// - 1 -Set request GTID as current master one
MXS_FREE(slave->mariadb_gtid);
slave->mariadb_gtid = MXS_STRDUP_A(last_gtid);
// - 2 - Use current router file and position
strcpy(slave->binlogfile, router_curr_file);
slave->binlog_pos = router_pos;
// - 3 Set GTID details for filename
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
{
memcpy(&slave->f_info, &f_gtid, sizeof(MARIADB_GTID_INFO));
}
} }
} }
else else
{ {
/* GTID has been found */ /* GTID has been found */
MXS_INFO("Found GTID '%s' for slave %lu at %s:%lu", MXS_INFO("Found GTID '%s' for slave %" PRIu32 ""
" at %" PRIu32 "/%" PRIu32 "/%s:%" PRIu64 ""
". Next event at %" PRIu64 "",
slave->mariadb_gtid, slave->mariadb_gtid,
(unsigned long)slave->serverid, slave->serverid,
f_gtid.gtid_elms.domain_id,
f_gtid.gtid_elms.server_id,
f_gtid.file, f_gtid.file,
f_gtid.start,
f_gtid.end); f_gtid.end);
/** /**
@ -6487,6 +6577,9 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
slave->binlog_pos = req_pos; slave->binlog_pos = req_pos;
} }
/* Set GTID details in f_info*/
memcpy(&slave->f_info, &f_gtid, sizeof(MARIADB_GTID_INFO));
/* Free gtid and file from result */ /* Free gtid and file from result */
MXS_FREE(f_gtid.gtid); MXS_FREE(f_gtid.gtid);
MXS_FREE(f_gtid.file); MXS_FREE(f_gtid.file);
@ -7074,7 +7167,7 @@ static bool blr_handle_set_stmt(ROUTER_INSTANCE *router,
} }
return true; return true;
} }
else if (strstr(word, "@@global.gtid_slave_pos") != NULL) else if (strcasecmp(word, "@@global.gtid_slave_pos") == 0)
{ {
if (slave->serverid != 0) if (slave->serverid != 0)
{ {
@ -7172,7 +7265,7 @@ static bool blr_handle_set_stmt(ROUTER_INSTANCE *router,
* in case of a fresh new setup. * in case of a fresh new setup.
*/ */
MXS_FREE(slave->mariadb_gtid); MXS_FREE(slave->mariadb_gtid);
slave->mariadb_gtid = MXS_STRDUP(heading); slave->mariadb_gtid = MXS_STRDUP_A(heading);
blr_slave_send_ok(router, slave); blr_slave_send_ok(router, slave);
return true; return true;
@ -7598,11 +7691,16 @@ static bool blr_handle_admin_stmt(ROUTER_INSTANCE *router,
static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router, static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
ROUTER_SLAVE *slave) ROUTER_SLAVE *slave)
{ {
char binlog_file[BLRM_BINLOG_NAME_STR_LEN + 1]; char binlog_file[BINLOG_FNAMELEN + 1];
char router_curr_file[BLRM_BINLOG_NAME_STR_LEN + 1]; char router_curr_file[BINLOG_FNAMELEN + 1];
char file_path[PATH_MAX + 1] = ""; char file_path[PATH_MAX + 1] = "";
unsigned int seqno; unsigned int seqno;
bool skipped_files = false; bool skipped_files = false;
char t_prefix[BINLOG_FILE_EXTRA_INFO] = "";
MARIADB_GTID_INFO *f_tree = router->storage_type == BLR_BINLOG_STORAGE_TREE ?
&slave->f_info :
NULL;
char next_file[BINLOG_FNAMELEN + 1] = "";
// Save the current router binlog filename // Save the current router binlog filename
spinlock_acquire(&router->binlog_lock); spinlock_acquire(&router->binlog_lock);
@ -7612,18 +7710,32 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
// Set the starting filename // Set the starting filename
strcpy(binlog_file, slave->binlogfile); strcpy(binlog_file, slave->binlogfile);
//Add tree prefix
if (f_tree)
{
sprintf(t_prefix,
"%" PRIu32 "/%" PRIu32 "/",
f_tree->gtid_elms.domain_id,
f_tree->gtid_elms.server_id);
}
// Get binlog filename full-path // Get binlog filename full-path
blr_get_file_fullpath(binlog_file, blr_get_file_fullpath(binlog_file,
router->binlogdir, router->binlogdir,
file_path); file_path,
t_prefix[0] ? t_prefix: NULL);
/** /**
* Set the next file in sequence if current file has 4 bytes size. * Get the next file in sequence or next by GTID maps
* Stop if the new file is the urrent binlog file. * if current file has 4 bytes size.
* Stop if the new file is the current binlog file.
*/ */
while (strcmp(binlog_file, router_curr_file) != 0 && while (!blr_compare_binlogs(router,
f_tree,
router_curr_file,
binlog_file) &&
blr_slave_get_file_size(file_path) == 4 && blr_slave_get_file_size(file_path) == 4 &&
(seqno = blr_file_get_next_seqno(binlog_file)) > 0) blr_file_next_exists(router, slave, next_file))
{ {
// Log skipped file // Log skipped file
MXS_INFO("Slave %s:%i, skip reading empty file '%s' (4 bytes size).", MXS_INFO("Slave %s:%i, skip reading empty file '%s' (4 bytes size).",
@ -7631,13 +7743,14 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
dcb_get_port(slave->dcb), dcb_get_port(slave->dcb),
binlog_file); binlog_file);
// Set next in sequence binlog file name // Update binlog_file name
sprintf(binlog_file, BINLOG_NAMEFMT, router->fileroot, seqno); sprintf(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,
router->binlogdir, router->binlogdir,
file_path); file_path,
t_prefix[0] ? t_prefix: NULL);
skipped_files = true; skipped_files = true;
} }
@ -7657,13 +7770,20 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
* @param root_dir The binlog storage directory * @param root_dir The binlog storage directory
* @param full_path The output fullpahth name: * @param full_path The output fullpahth name:
* the memory area must be preallocated. * the memory area must be preallocated.
* @param t_prefix The file_tree prefix with rep_domain
* and server_id.
*/ */
static inline void blr_get_file_fullpath(const char *binlog_file, static inline void blr_get_file_fullpath(const char *binlog_file,
const char *root_dir, const char *root_dir,
char *full_path) char *full_path,
const char *t_prefix)
{ {
strcpy(full_path, root_dir); strcpy(full_path, root_dir);
strcat(full_path, "/"); strcat(full_path, "/");
if (t_prefix)
{
strcat(full_path, t_prefix);
}
strcat(full_path, binlog_file); strcat(full_path, binlog_file);
} }
@ -7775,6 +7895,7 @@ blr_show_binary_logs(ROUTER_INSTANCE *router,
* Check whether the last file is the current binlog file. * Check whether the last file is the current binlog file.
* If not then add the new row. * If not then add the new row.
*/ */
// TODO: check whether to FIX with prefix
if (strcmp(current_file, result.last_file) != 0) if (strcmp(current_file, result.last_file) != 0)
{ {
char pos[40]; char pos[40];
@ -7871,6 +7992,12 @@ static int binary_logs_select_cb(void *data,
char filename[1 + char filename[1 +
strlen(values[0]) + strlen(values[0]) +
BINLOG_FILE_EXTRA_INFO]; BINLOG_FILE_EXTRA_INFO];
char t_prefix[BINLOG_FILE_EXTRA_INFO] = "";
sprintf(t_prefix,
"%s/%s/",
values[2], // domain ID
values[3]); // server ID
fsize = atoll(values[1]); fsize = atoll(values[1]);
@ -7890,7 +8017,8 @@ static int binary_logs_select_cb(void *data,
//Get binlog filename full-path //Get binlog filename full-path
blr_get_file_fullpath(values[0], blr_get_file_fullpath(values[0],
data_set->binlogdir, data_set->binlogdir,
file_path); file_path,
t_prefix);
//Get the file size //Get the file size
fsize = blr_slave_get_file_size(file_path); fsize = blr_slave_get_file_size(file_path);
@ -7900,9 +8028,8 @@ static int binary_logs_select_cb(void *data,
if (data_set->extra_info) if (data_set->extra_info)
{ {
sprintf(filename, sprintf(filename,
"%s/%s/%s", "%s%s",
values[2], // domain ID t_prefix,
values[3], // server ID
values[0]); // filename values[0]); // filename
} }
else else