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:
@ -61,7 +61,6 @@
|
||||
*/
|
||||
|
||||
#include "blr.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -87,6 +86,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* The router entry points */
|
||||
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 void rses_end_locked_router_action(ROUTER_SLAVE *);
|
||||
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 ROUTER_INSTANCE *instances;
|
||||
@ -139,6 +141,13 @@ static const MXS_ENUM_VALUE enc_algo_values[] =
|
||||
{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
|
||||
* 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},
|
||||
{"mariadb10_slave_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},
|
||||
{"longburst", MXS_MODULE_PARAM_COUNT, DEF_LONG_BURST},
|
||||
{"burstsize", MXS_MODULE_PARAM_SIZE, DEF_BURST_SIZE},
|
||||
@ -382,6 +392,11 @@ createInstance(SERVICE *service, char **options)
|
||||
/* Set router 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)
|
||||
{
|
||||
/* Generate UUID for the router instance */
|
||||
@ -542,6 +557,13 @@ createInstance(SERVICE *service, char **options)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int ret = blr_check_encryption_algorithm(value);
|
||||
@ -672,7 +694,6 @@ createInstance(SERVICE *service, char **options)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Get the Encryption key */
|
||||
if (inst->encryption.enabled && !blr_get_encryption_key(inst))
|
||||
{
|
||||
@ -723,6 +744,24 @@ createInstance(SERVICE *service, char **options)
|
||||
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 */
|
||||
if (inst->mariadb10_compat &&
|
||||
inst->mariadb10_gtid)
|
||||
@ -889,7 +928,7 @@ createInstance(SERVICE *service, char **options)
|
||||
/* Read any cached response messages */
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
/* Check current binlog */
|
||||
MXS_NOTICE("Validating binlog file '%s' ...",
|
||||
char f_prefix[BINLOG_FILE_EXTRA_INFO] = "";
|
||||
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);
|
||||
|
||||
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",
|
||||
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 */
|
||||
if (!inst->encryption.enabled && inst->encryption_ctx)
|
||||
{
|
||||
@ -985,8 +1085,9 @@ createInstance(SERVICE *service, char **options)
|
||||
inst->master_state = BLRM_SLAVE_STOPPED;
|
||||
/* Set mysql_errno and error message */
|
||||
inst->m_errno = BINLOG_FATAL_ERROR_READING;
|
||||
inst->m_errmsg = mxs_strdup("HY000 Binlog encryption is Off but binlog file has "
|
||||
"the START_ENCRYPTION_EVENT");
|
||||
inst->m_errmsg = MXS_STRDUP_A("HY000 Binlog encryption is Off"
|
||||
" but current binlog file has"
|
||||
" the START_ENCRYPTION_EVENT");
|
||||
|
||||
return (MXS_ROUTER *)inst;
|
||||
}
|
||||
@ -998,6 +1099,11 @@ createInstance(SERVICE *service, char **options)
|
||||
return (MXS_ROUTER *)inst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the router instance
|
||||
*
|
||||
* @param instance The router instance
|
||||
*/
|
||||
static void
|
||||
free_instance(ROUTER_INSTANCE *instance)
|
||||
{
|
||||
@ -1079,6 +1185,7 @@ newSession(MXS_ROUTER *instance, MXS_SESSION *session)
|
||||
slave->mariadb_gtid = NULL;
|
||||
|
||||
slave->gtid_maps = NULL;
|
||||
memset(&slave->f_info, 0 , sizeof (MARIADB_GTID_INFO));
|
||||
|
||||
/**
|
||||
* Add this session to the list of active sessions.
|
||||
|
@ -104,6 +104,12 @@ MXS_BEGIN_DECLS
|
||||
* in SHOW FULL BINARY LOGS
|
||||
*/
|
||||
#define BINLOG_FILE_EXTRA_INFO GTID_MAX_LEN
|
||||
|
||||
enum blr_binlog_storage_type
|
||||
{
|
||||
BLR_BINLOG_STORAGE_FLAT,
|
||||
BLR_BINLOG_STORAGE_TREEE
|
||||
};
|
||||
/**
|
||||
* Supported Encryption algorithms
|
||||
*
|
||||
@ -298,6 +304,24 @@ enum blr_event_state
|
||||
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 */
|
||||
typedef struct master_server_config
|
||||
{
|
||||
@ -380,6 +404,7 @@ typedef struct blfile
|
||||
int refcnt; /*< Reference count for file */
|
||||
BLCACHE *cache; /*< Record cache for this file */
|
||||
SPINLOCK lock; /*< The file lock */
|
||||
MARIADB_GTID_ELEMS info; /*< Elements for file prefix */
|
||||
struct blfile *next; /*< Next file in list */
|
||||
} BLFILE;
|
||||
|
||||
@ -471,6 +496,7 @@ typedef struct router_slave
|
||||
bool gtid_strict_mode;/*< MariaDB 10 Slave sets gtid_strict_mode */
|
||||
char *mariadb_gtid; /*< MariaDB 10 Slave connects with GTID */
|
||||
sqlite3 *gtid_maps; /*< GTID storage client handle, read only*/
|
||||
MARIADB_GTID_INFO f_info; /*< GTID info for file name prefix */
|
||||
#if defined(SS_DEBUG)
|
||||
skygw_chk_t rses_chk_tail;
|
||||
#endif
|
||||
@ -553,35 +579,18 @@ typedef enum
|
||||
BLRM_STANDALONE_SEEN /*< Received a standalone event, ie: a DDL */
|
||||
} 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 */
|
||||
typedef struct pending_transaction
|
||||
{
|
||||
char gtid[GTID_MAX_LEN + 1]; /** MariaDB 10.x GTID */
|
||||
master_transaction_t state; /** Transaction state */
|
||||
uint64_t start_pos; /** The BEGIN pos */
|
||||
uint64_t end_pos; /** The next_pos in COMMIT event*/
|
||||
MARIADB_GTID_ELEMS gtid_elms; /* MariaDB 10.x GTID components */
|
||||
uint64_t end_pos; /** The next_pos in COMMIT event */
|
||||
MARIADB_GTID_ELEMS gtid_elms; /** MariaDB 10.x GTID components */
|
||||
bool standalone; /** Standalone event, such as DDL
|
||||
* no terminating COMMIT */
|
||||
} 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.
|
||||
*/
|
||||
@ -673,6 +682,7 @@ typedef struct router_instance
|
||||
*/
|
||||
uint32_t mariadb10_gtid_domain;/*< MariaDB 10 GTID Domain ID */
|
||||
sqlite3 *gtid_maps; /*< MariaDB 10 GTID storage */
|
||||
enum binlog_storage_type storage_type;/*< Enables hierachical binlog file storage */
|
||||
struct router_instance *next;
|
||||
} 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_file_rotate(ROUTER_INSTANCE *, char *, uint64_t);
|
||||
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 *,
|
||||
const SLAVE_ENCRYPTION_CTX *);
|
||||
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_ping(ROUTER_INSTANCE *, ROUTER_SLAVE *, GWBUF *);
|
||||
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);
|
||||
void blr_cache_read_master_data(ROUTER_INSTANCE *router);
|
||||
int blr_read_events_all_events(ROUTER_INSTANCE *, BINLOG_FILE_FIX *, int);
|
||||
|
@ -226,6 +226,16 @@ static void blr_report_checksum(REP_HEADER hdr,
|
||||
|
||||
bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
|
||||
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
|
||||
@ -254,7 +264,8 @@ typedef struct start_encryption_event
|
||||
* binlog to use and initialise it for writing, determining the
|
||||
* 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
|
||||
blr_file_init(ROUTER_INSTANCE *router)
|
||||
@ -265,6 +276,7 @@ blr_file_init(ROUTER_INSTANCE *router)
|
||||
int root_len, i;
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
int ret = 0;
|
||||
|
||||
if (router->binlogdir == NULL)
|
||||
{
|
||||
@ -303,7 +315,15 @@ blr_file_init(ROUTER_INSTANCE *router)
|
||||
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);
|
||||
if ((dirp = opendir(path)) == NULL)
|
||||
{
|
||||
@ -325,7 +345,6 @@ blr_file_init(ROUTER_INSTANCE *router)
|
||||
}
|
||||
closedir(dirp);
|
||||
|
||||
|
||||
file_found = 0;
|
||||
do
|
||||
{
|
||||
@ -358,6 +377,56 @@ blr_file_init(ROUTER_INSTANCE *router)
|
||||
blr_file_append(router, filename);
|
||||
}
|
||||
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
|
||||
@ -409,6 +478,39 @@ blr_file_create(ROUTER_INSTANCE *router, char *file)
|
||||
|
||||
strcpy(path, router->binlogdir);
|
||||
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);
|
||||
|
||||
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;
|
||||
// router->orig_masterid keeps the original ID
|
||||
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.start_pos = 4;
|
||||
// Update all the gtid_elms
|
||||
memcpy(&router->pending_transaction.gtid_elms,
|
||||
>id_elms,
|
||||
sizeof(MARIADB_GTID_ELEMS));
|
||||
@ -496,6 +600,21 @@ blr_file_append(ROUTER_INSTANCE *router, char *file)
|
||||
|
||||
strcpy(path, router->binlogdir);
|
||||
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);
|
||||
|
||||
if ((fd = open(path, flags, 0666)) == -1)
|
||||
@ -670,10 +789,19 @@ blr_file_flush(ROUTER_INSTANCE *router)
|
||||
*
|
||||
* @param router The router instance
|
||||
* @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
|
||||
*/
|
||||
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);
|
||||
if (len > BINLOG_FNAMELEN)
|
||||
@ -683,7 +811,7 @@ blr_open_binlog(ROUTER_INSTANCE *router, char *binlog)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len += (strlen(router->binlogdir) + 1); // +1 for the /.
|
||||
len += (strlen(router->binlogdir) + 1); // +1 for the '.'
|
||||
if (len > PATH_MAX)
|
||||
{
|
||||
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);
|
||||
file->refcnt = 1;
|
||||
file->cache = 0;
|
||||
|
||||
/* Store additional file informations */
|
||||
if (info)
|
||||
{
|
||||
memcpy(&file->info,
|
||||
&info->gtid_elms,
|
||||
sizeof(MARIADB_GTID_ELEMS));
|
||||
}
|
||||
|
||||
spinlock_init(&file->lock);
|
||||
|
||||
strcpy(path, router->binlogdir);
|
||||
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);
|
||||
|
||||
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(&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 "
|
||||
"'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(&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)
|
||||
{
|
||||
if (pos > router->binlog_position)
|
||||
@ -1075,7 +1233,7 @@ blr_read_binlog(ROUTER_INSTANCE *router,
|
||||
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))
|
||||
{
|
||||
@ -1083,7 +1241,7 @@ blr_read_binlog(ROUTER_INSTANCE *router,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the decrypted event as result*/
|
||||
/* Set the decrypted event as result */
|
||||
result = decrypted_event;
|
||||
}
|
||||
|
||||
@ -1143,7 +1301,7 @@ blr_close_binlog(ROUTER_INSTANCE *router, BLFILE *file)
|
||||
/**
|
||||
* 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 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 slave The slave in question
|
||||
* @param next_file The next_file buffer
|
||||
* @return 0 if the next file does not exist
|
||||
*/
|
||||
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];
|
||||
int filenum;
|
||||
char *errmsg = NULL;
|
||||
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)
|
||||
{
|
||||
next_file[0] = '\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);
|
||||
sprintf(buf, BINLOG_NAMEFMT, router->fileroot, filenum + 1);
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
@ -2137,6 +2402,7 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
|
||||
*/
|
||||
if (router->mariadb10_compat)
|
||||
{
|
||||
char f_prefix[BINLOG_FILE_EXTRA_INFO] = "";
|
||||
if (hdr.event_type == MARIADB10_GTID_GTID_LIST_EVENT)
|
||||
{
|
||||
char mariadb_gtid[GTID_MAX_LEN + 1] = "";
|
||||
@ -2164,14 +2430,22 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
|
||||
|
||||
snprintf(mariadb_gtid,
|
||||
GTID_MAX_LEN,
|
||||
"%u-%u-%lu",
|
||||
"%" PRIu32 "-%" PRIu32 "-%" PRIu64 "",
|
||||
domainid,
|
||||
serverid,
|
||||
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,
|
||||
mariadb_gtid);
|
||||
|
||||
if (router->storage_type == BLR_BINLOG_STORAGE_TREE)
|
||||
{
|
||||
sprintf(f_prefix,
|
||||
"%" PRIu32 "/%" PRIu32 "/",
|
||||
domainid,
|
||||
serverid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2187,17 +2461,41 @@ blr_read_events_all_events(ROUTER_INSTANCE *router,
|
||||
"%s",
|
||||
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.file);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set MariaDB GTID */
|
||||
if (router->mariadb10_gtid)
|
||||
{
|
||||
/* Set 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)
|
||||
{
|
||||
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, "
|
||||
"server_id, "
|
||||
"sequence, "
|
||||
@ -3452,8 +3751,16 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
|
||||
"\"%s\", "
|
||||
"%" 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 insert_sql[GTID_SQL_BUFFER_SIZE];
|
||||
char sql_stmt[GTID_SQL_BUFFER_SIZE];
|
||||
MARIADB_GTID_INFO gtid_info;
|
||||
MARIADB_GTID_ELEMS gtid_elms;
|
||||
|
||||
@ -3465,8 +3772,8 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
|
||||
&inst->pending_transaction.gtid_elms,
|
||||
sizeof(MARIADB_GTID_ELEMS));
|
||||
|
||||
/* Save GTID into repo */
|
||||
snprintf(insert_sql,
|
||||
/* Prepare INSERT SQL */
|
||||
snprintf(sql_stmt,
|
||||
GTID_SQL_BUFFER_SIZE,
|
||||
insert_tpl,
|
||||
gtid_elms.domain_id,
|
||||
@ -3477,8 +3784,47 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
|
||||
gtid_info.end);
|
||||
|
||||
/* Save GTID into repo */
|
||||
if (sqlite3_exec(inst->gtid_maps, insert_sql, NULL, NULL,
|
||||
&errmsg) != SQLITE_OK)
|
||||
if ((sql_ret = sqlite3_exec(inst->gtid_maps,
|
||||
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 "
|
||||
"into gtid_maps database: %s",
|
||||
@ -3491,13 +3837,14 @@ bool blr_save_mariadb_gtid(ROUTER_INSTANCE *inst)
|
||||
sqlite3_free(errmsg);
|
||||
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,
|
||||
inst->binlog_name,
|
||||
gtid_info.start,
|
||||
gtid_info.end,
|
||||
insert_sql);
|
||||
sql_stmt);
|
||||
|
||||
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->start = atoll(values[2]);
|
||||
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;
|
||||
@ -3555,7 +3916,10 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
|
||||
" '-' || sequence) AS gtid, "
|
||||
"binlog_file, "
|
||||
"start_pos, "
|
||||
"end_pos "
|
||||
"end_pos, "
|
||||
"rep_domain, "
|
||||
"server_id, "
|
||||
"sequence "
|
||||
"FROM gtid_maps "
|
||||
"WHERE (rep_domain = %" PRIu32 " AND "
|
||||
"server_id = %" PRIu32 " AND "
|
||||
@ -3589,7 +3953,16 @@ bool blr_fetch_mariadb_gtid(ROUTER_SLAVE *slave,
|
||||
sqlite3_free(errmsg);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -3688,7 +4061,6 @@ bool blr_parse_gtid(const char *gtid, MARIADB_GTID_ELEMS *info)
|
||||
* Get MariaDB GTID from repo
|
||||
*
|
||||
* @param router The current router instance
|
||||
* @param gtid The GTID to look for
|
||||
* @param result The (allocated) ouput data to fill
|
||||
* @return False on sqlite errors
|
||||
* True even if the gtid_maps is empty
|
||||
@ -3706,19 +4078,25 @@ bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
|
||||
" '-' || sequence) AS gtid, "
|
||||
"binlog_file, "
|
||||
"start_pos, "
|
||||
"end_pos "
|
||||
"end_pos, "
|
||||
"rep_domain, "
|
||||
"server_id, "
|
||||
"sequence "
|
||||
"FROM gtid_maps "
|
||||
"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,
|
||||
last_gtid,
|
||||
gtid_select_cb,
|
||||
result,
|
||||
&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,
|
||||
last_gtid);
|
||||
sqlite3_free(errmsg);
|
||||
@ -3727,3 +4105,127 @@ bool blr_load_last_mariadb_gtid(ROUTER_INSTANCE *router,
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -3246,6 +3246,8 @@ static void blr_handle_fake_gtid_list(ROUTER_INSTANCE *router,
|
||||
router->last_written = hdr->next_pos;
|
||||
router->last_event_pos = router->current_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);
|
||||
}
|
||||
|
@ -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);
|
||||
static int blr_slave_fake_rotate(ROUTER_INSTANCE *router,
|
||||
ROUTER_SLAVE *slave,
|
||||
BLFILE** filep);
|
||||
BLFILE** filep,
|
||||
const char *new_file);
|
||||
static uint32_t blr_slave_send_fde(ROUTER_INSTANCE *router,
|
||||
ROUTER_SLAVE *slave,
|
||||
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,
|
||||
const char *root_dir,
|
||||
char *full_path);
|
||||
char *full_path,
|
||||
const char *f_prefix);
|
||||
static int blr_show_binary_logs(ROUTER_INSTANCE *router,
|
||||
ROUTER_SLAVE *slave,
|
||||
const char *extra_data);
|
||||
@ -332,6 +334,12 @@ static bool blr_handle_complex_select(ROUTER_INSTANCE *router,
|
||||
ROUTER_SLAVE *slave,
|
||||
const char *col1,
|
||||
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.
|
||||
*
|
||||
@ -1808,7 +1816,7 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue
|
||||
|
||||
spinlock_acquire(&router->binlog_lock);
|
||||
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))
|
||||
{
|
||||
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
|
||||
* 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
|
||||
* the slave->binlog_pos is set to 4 and
|
||||
* slave->binlogname set to new filename.
|
||||
@ -2046,6 +2055,9 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
int rotating = 0;
|
||||
long burst_size;
|
||||
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';
|
||||
|
||||
@ -2068,7 +2080,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
|
||||
/* check for a pending transaction and safe position */
|
||||
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))
|
||||
{
|
||||
do_return = 1;
|
||||
@ -2098,7 +2110,9 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
if (file == NULL)
|
||||
{
|
||||
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];
|
||||
err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
|
||||
@ -2244,9 +2258,13 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
|
||||
beat1 = hkheartbeat;
|
||||
#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
|
||||
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||
if ((file = blr_open_binlog(router,
|
||||
slave->binlogfile,
|
||||
f_tree)) == NULL)
|
||||
#endif
|
||||
{
|
||||
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 */
|
||||
blr_send_custom_error(slave->dcb,
|
||||
(slave->seqno - 1),
|
||||
slave->seqno,
|
||||
0,
|
||||
err_msg,
|
||||
"HY000",
|
||||
BINLOG_FATAL_ERROR_READING);
|
||||
|
||||
gwbuf_free(record);
|
||||
record = NULL;
|
||||
|
||||
slave->state = BLRS_ERRORED;
|
||||
dcb_close(slave->dcb);
|
||||
break;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef BLFILE_IN_SLAVE
|
||||
file = slave->file;
|
||||
@ -2440,7 +2463,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
poll_fake_write_event(slave->dcb);
|
||||
}
|
||||
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(&slave->catch_lock);
|
||||
@ -2450,7 +2473,7 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
* and slave->catch_lock.
|
||||
*/
|
||||
if (slave->binlog_pos != router->binlog_position ||
|
||||
strcmp(slave->binlogfile, router->binlog_name) != 0)
|
||||
!blr_is_current_binlog(router, slave))
|
||||
{
|
||||
slave->cstate |= CS_EXPECTCB;
|
||||
spinlock_release(&slave->catch_lock);
|
||||
@ -2473,10 +2496,11 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slave->binlog_pos >= blr_file_size(file)
|
||||
&& router->rotating == 0
|
||||
&& strcmp(router->binlog_name, slave->binlogfile) != 0
|
||||
&& blr_file_next_exists(router, slave))
|
||||
char next_file[BINLOG_FNAMELEN + 1] = "";
|
||||
if (slave->binlog_pos >= blr_file_size(file) &&
|
||||
router->rotating == 0 &&
|
||||
(!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
|
||||
* binlog file.
|
||||
@ -2501,10 +2525,11 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
MXS_FREE(slave->encryption_ctx);
|
||||
slave->encryption_ctx = NULL;
|
||||
|
||||
/* Now pass the next_file to blr_slave_fake_rotate() */
|
||||
#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
|
||||
if (blr_slave_fake_rotate(router, slave, &file))
|
||||
if (blr_slave_fake_rotate(router, slave, &file, next_file))
|
||||
#endif
|
||||
{
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
@ -2516,6 +2541,10 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
{
|
||||
slave->state = BLRS_ERRORED;
|
||||
dcb_close(slave->dcb);
|
||||
#ifndef BLFILE_IN_SLAVE
|
||||
blr_close_binlog(router, file);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2604,6 +2633,7 @@ blr_slave_callback(DCB *dcb, DCB_REASON reason, void *data)
|
||||
/**
|
||||
* Rotate the slave to the new binlog file
|
||||
*
|
||||
* @param router The router instance
|
||||
* @param slave The slave instance
|
||||
* @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
|
||||
* 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 slave The slave to rotate
|
||||
@ -2641,26 +2671,30 @@ blr_slave_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint8_t *ptr)
|
||||
static int
|
||||
blr_slave_fake_rotate(ROUTER_INSTANCE *router,
|
||||
ROUTER_SLAVE *slave,
|
||||
BLFILE** filep)
|
||||
BLFILE** filep,
|
||||
const char *new_file)
|
||||
{
|
||||
char *sptr;
|
||||
int filenum;
|
||||
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;
|
||||
}
|
||||
blr_close_binlog(router, *filep);
|
||||
filenum = atoi(sptr + 1);
|
||||
sprintf(slave->binlogfile,
|
||||
BINLOG_NAMEFMT,
|
||||
router->fileroot,
|
||||
filenum + 1);
|
||||
|
||||
/* Set 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;
|
||||
}
|
||||
@ -2668,7 +2702,7 @@ blr_slave_fake_rotate(ROUTER_INSTANCE *router,
|
||||
/* Build Fake Rotate Event */
|
||||
r_event = blr_build_fake_rotate_event(slave,
|
||||
slave->binlog_pos,
|
||||
slave->binlogfile,
|
||||
new_file,
|
||||
router->masterid);
|
||||
|
||||
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;
|
||||
uint32_t chksum;
|
||||
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';
|
||||
|
||||
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;
|
||||
}
|
||||
@ -5899,13 +5938,18 @@ blr_slave_read_ste(ROUTER_INSTANCE *router,
|
||||
uint8_t *ptr;
|
||||
uint32_t chksum;
|
||||
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';
|
||||
|
||||
memset(&hdr, 0, BINLOG_EVENT_HDR_LEN);
|
||||
|
||||
BLFILE *file;
|
||||
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||
if ((file = blr_open_binlog(router,
|
||||
slave->binlogfile,
|
||||
f_tree)) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -6374,6 +6418,26 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
|
||||
bool req_file,
|
||||
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'",
|
||||
(unsigned long)slave->serverid,
|
||||
slave->mariadb_gtid);
|
||||
@ -6384,15 +6448,22 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
|
||||
* Empty GTID:
|
||||
* 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:"
|
||||
" sending events from current binlog file %s, pos %lu",
|
||||
" sending events from current binlog file %s,"
|
||||
" pos %" PRIu32 "",
|
||||
(unsigned long)slave->serverid,
|
||||
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
|
||||
{
|
||||
MARIADB_GTID_INFO f_gtid = {};
|
||||
char dbpath[PATH_MAX + 1];
|
||||
snprintf(dbpath, sizeof(dbpath), "/%s/%s",
|
||||
router->binlogdir, GTID_MAPS_DB);
|
||||
@ -6412,6 +6483,7 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
|
||||
sqlite3_errmsg(slave->gtid_maps));
|
||||
|
||||
slave->gtid_maps = NULL;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6447,16 +6519,34 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
|
||||
}
|
||||
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
|
||||
{
|
||||
/* 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,
|
||||
(unsigned long)slave->serverid,
|
||||
slave->serverid,
|
||||
f_gtid.gtid_elms.domain_id,
|
||||
f_gtid.gtid_elms.server_id,
|
||||
f_gtid.file,
|
||||
f_gtid.start,
|
||||
f_gtid.end);
|
||||
|
||||
/**
|
||||
@ -6487,6 +6577,9 @@ static bool blr_slave_gtid_request(ROUTER_INSTANCE *router,
|
||||
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 */
|
||||
MXS_FREE(f_gtid.gtid);
|
||||
MXS_FREE(f_gtid.file);
|
||||
@ -7074,7 +7167,7 @@ static bool blr_handle_set_stmt(ROUTER_INSTANCE *router,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (strstr(word, "@@global.gtid_slave_pos") != NULL)
|
||||
else if (strcasecmp(word, "@@global.gtid_slave_pos") == 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.
|
||||
*/
|
||||
MXS_FREE(slave->mariadb_gtid);
|
||||
slave->mariadb_gtid = MXS_STRDUP(heading);
|
||||
slave->mariadb_gtid = MXS_STRDUP_A(heading);
|
||||
|
||||
blr_slave_send_ok(router, slave);
|
||||
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,
|
||||
ROUTER_SLAVE *slave)
|
||||
{
|
||||
char binlog_file[BLRM_BINLOG_NAME_STR_LEN + 1];
|
||||
char router_curr_file[BLRM_BINLOG_NAME_STR_LEN + 1];
|
||||
char binlog_file[BINLOG_FNAMELEN + 1];
|
||||
char router_curr_file[BINLOG_FNAMELEN + 1];
|
||||
char file_path[PATH_MAX + 1] = "";
|
||||
unsigned int seqno;
|
||||
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
|
||||
spinlock_acquire(&router->binlog_lock);
|
||||
@ -7612,18 +7710,32 @@ static void blr_slave_skip_empty_files(ROUTER_INSTANCE *router,
|
||||
// Set the starting filename
|
||||
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
|
||||
blr_get_file_fullpath(binlog_file,
|
||||
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.
|
||||
* Stop if the new file is the urrent binlog file.
|
||||
* Get the next file in sequence or next by GTID maps
|
||||
* 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 &&
|
||||
(seqno = blr_file_get_next_seqno(binlog_file)) > 0)
|
||||
blr_file_next_exists(router, slave, next_file))
|
||||
{
|
||||
// Log skipped file
|
||||
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),
|
||||
binlog_file);
|
||||
|
||||
// Set next in sequence binlog file name
|
||||
sprintf(binlog_file, BINLOG_NAMEFMT, router->fileroot, seqno);
|
||||
// Update binlog_file name
|
||||
sprintf(binlog_file, next_file);
|
||||
|
||||
// Get binlog file full-path
|
||||
blr_get_file_fullpath(binlog_file,
|
||||
router->binlogdir,
|
||||
file_path);
|
||||
file_path,
|
||||
t_prefix[0] ? t_prefix: NULL);
|
||||
|
||||
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 full_path The output fullpahth name:
|
||||
* 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,
|
||||
const char *root_dir,
|
||||
char *full_path)
|
||||
char *full_path,
|
||||
const char *t_prefix)
|
||||
{
|
||||
strcpy(full_path, root_dir);
|
||||
strcat(full_path, "/");
|
||||
if (t_prefix)
|
||||
{
|
||||
strcat(full_path, t_prefix);
|
||||
}
|
||||
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.
|
||||
* If not then add the new row.
|
||||
*/
|
||||
// TODO: check whether to FIX with prefix
|
||||
if (strcmp(current_file, result.last_file) != 0)
|
||||
{
|
||||
char pos[40];
|
||||
@ -7871,6 +7992,12 @@ static int binary_logs_select_cb(void *data,
|
||||
char filename[1 +
|
||||
strlen(values[0]) +
|
||||
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]);
|
||||
|
||||
@ -7890,7 +8017,8 @@ static int binary_logs_select_cb(void *data,
|
||||
//Get binlog filename full-path
|
||||
blr_get_file_fullpath(values[0],
|
||||
data_set->binlogdir,
|
||||
file_path);
|
||||
file_path,
|
||||
t_prefix);
|
||||
//Get the file size
|
||||
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)
|
||||
{
|
||||
sprintf(filename,
|
||||
"%s/%s/%s",
|
||||
values[2], // domain ID
|
||||
values[3], // server ID
|
||||
"%s%s",
|
||||
t_prefix,
|
||||
values[0]); // filename
|
||||
}
|
||||
else
|
||||
|
Reference in New Issue
Block a user