Merge branch 'develop' into 1.2.1-binlog_router

Conflicts:
	server/core/server.c
	server/include/server.h
	server/modules/include/blr.h
	server/modules/routing/binlog/blr.c
	server/modules/routing/binlog/blr_file.c
	server/modules/routing/binlog/blr_master.c
	server/modules/routing/binlog/blr_slave.c
This commit is contained in:
root
2015-08-04 07:59:44 -04:00
181 changed files with 9740 additions and 4538 deletions

View File

@ -35,6 +35,8 @@
* 02/04/2014 Mark Riddoch Initial implementation
* 17/02/2015 Massimiliano Pinto Addition of slave port and username in diagnostics
* 18/02/2015 Massimiliano Pinto Addition of dcb_close in closeSession
* 07/05/2015 Massimiliano Pinto Addition of MariaDB 10 compatibility support
* 12/06/2015 Massimiliano Pinto Addition of MariaDB 10 events in diagnostics()
* 29/06/2015 Massimiliano Pinto Addition of master.ini for easy startup configuration
* If not found router goes into BLRM_UNCONFIGURED state.
* Cache dir is 'cache' under router->binlogdir.
@ -117,6 +119,9 @@ static void stats_func(void *);
static bool rses_begin_locked_router_action(ROUTER_SLAVE *);
static void rses_end_locked_router_action(ROUTER_SLAVE *);
void my_uuid_init(ulong seed1, ulong seed2);
void my_uuid(char *guid);
GWBUF *blr_cache_read_response(ROUTER_INSTANCE *router, char *response);
static SPINLOCK instlock;
static ROUTER_INSTANCE *instances;
@ -184,8 +189,45 @@ char path[PATH_MAX+1] = "";
char filename[PATH_MAX+1] = "";
int master_info = 0;
int rc = 0;
char *defuuid;
if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) {
if(service->credentials.name == NULL ||
service->credentials.authdata == NULL)
{
skygw_log_write(LE,"%s: Error: Service is missing user credentials."
" Add the missing username or passwd parameter to the service.",
service->name);
return NULL;
}
if(options == NULL || options[0] == NULL)
{
skygw_log_write(LE,
"%s: Error: No router options supplied for binlogrouter",
service->name);
return NULL;
}
/*
* We only support one server behind this router, since the server is
* the master from which we replicate binlog records. Therefore check
* that only one server has been defined.
*
* A later improvement will be to define multiple servers and have the
* router use the information that is supplied by the monitor to find
* which of these servers is currently the master and replicate from
* that server.
*/
if (service->dbref == NULL || service->dbref->next != NULL)
{
skygw_log_write(LE,
"%s: Error : Exactly one database server may be "
"for use with the binlog router.",
service->name);
return NULL;
}
if ((inst = calloc(1, sizeof(ROUTER_INSTANCE))) == NULL) {
return NULL;
}
@ -215,6 +257,7 @@ int rc = 0;
inst->retry_backoff = 1;
inst->binlogdir = NULL;
inst->heartbeat = 300; // Default is every 5 minutes
inst->mariadb10_compat = false;
inst->user = strdup(service->credentials.name);
inst->password = strdup(service->credentials.authdata);
@ -234,22 +277,6 @@ int rc = 0;
defuuid[12], defuuid[13], defuuid[14], defuuid[15]);
}
/*
* We only support one server behind this router, since the server is
* the master from which we replicate binlog records. Therefore check
* that only one server has been defined.
*
*/
if (service->dbref && service->dbref->next != NULL)
{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : Exactly one database server may be "
"for use with the binlog router.")));
/* report as error whether a server is defined in the service */
}
/*
* Process the options.
* We have an array of attribute values passed to us that we must
@ -302,6 +329,10 @@ int rc = 0;
{
inst->masterid = atoi(value);
}
else if (strcmp(options[i], "mariadb10-compatibility") == 0)
{
inst->mariadb10_compat = config_truth_value(value);
}
else if (strcmp(options[i], "filestem") == 0)
{
inst->fileroot = strdup(value);
@ -376,7 +407,7 @@ int rc = 0;
else
{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR, "%s: No router options supplied for binlogrouter",
LOGFILE_ERROR, "%s: Error: No router options supplied for binlogrouter",
service->name)));
}
@ -508,6 +539,7 @@ int rc = 0;
/*
* Read any cached response messages
*/
blr_cache_read_master_data(inst);
/*
@ -627,6 +659,7 @@ ROUTER_SLAVE *slave;
strcpy(slave->binlogfile, "unassigned");
slave->connect_time = time(0);
slave->lastEventTimestamp = 0;
slave->mariadb10_compat = false;
/**
* Add this session to the list of active sessions.
@ -810,6 +843,15 @@ static char *event_names[] = {
"Anonymous GTID Event", "Previous GTIDS Event"
};
/* New MariaDB event numbers starts from 0xa0 */
static char *event_names_mariadb10[] = {
"Annotate Rows Event",
/* New MariaDB 10.x event numbers */
"Binlog Checkpoint Event",
"GTID Event",
"GTID List Event"
};
/**
* Display an entry from the spinlock statistics data
*
@ -929,14 +971,31 @@ struct tm tm;
buf);
dcb_printf(dcb, "\t (%d seconds ago)\n",
time(0) - router_inst->stats.lastReply);
dcb_printf(dcb, "\tLast event from master: 0x%x, %s",
if (!router_inst->mariadb10_compat) {
dcb_printf(dcb, "\tLast event from master: 0x%x, %s",
router_inst->lastEventReceived,
(router_inst->lastEventReceived >= 0 &&
router_inst->lastEventReceived < 0x24) ?
router_inst->lastEventReceived <= MAX_EVENT_TYPE) ?
event_names[router_inst->lastEventReceived] : "unknown");
} else {
char *ptr = NULL;
if (router_inst->lastEventReceived >= 0 && router_inst->lastEventReceived <= MAX_EVENT_TYPE) {
ptr = event_names[router_inst->lastEventReceived];
} else {
/* Check MariaDB 10 new events */
if (router_inst->lastEventReceived >= MARIADB_NEW_EVENTS_BEGIN && router_inst->lastEventReceived <= MAX_EVENT_TYPE_MARIADB10) {
ptr = event_names_mariadb10[(router_inst->lastEventReceived - MARIADB_NEW_EVENTS_BEGIN)];
}
}
dcb_printf(dcb, "\tLast event from master: 0x%x, %s",
router_inst->lastEventReceived, (ptr != NULL) ? ptr : "unknown");
}
if (router_inst->lastEventTimestamp)
{
localtime_r(&router_inst->lastEventTimestamp, &tm);
localtime_r((const time_t*)&router_inst->lastEventTimestamp, &tm);
asctime_r(&tm, buf);
dcb_printf(dcb, "\tLast binlog event timestamp: %ld (%s)\n",
router_inst->lastEventTimestamp, buf);
@ -946,11 +1005,17 @@ struct tm tm;
if (router_inst->reconnect_pending)
dcb_printf(dcb, "\tRouter pending reconnect to master\n");
dcb_printf(dcb, "\tEvents received:\n");
for (i = 0; i < 0x24; i++)
for (i = 0; i <= MAX_EVENT_TYPE; i++)
{
dcb_printf(dcb, "\t\t%-38s %u\n", event_names[i], router_inst->stats.events[i]);
}
if (router_inst->mariadb10_compat) {
/* Display MariaDB 10 new events */
for (i = MARIADB_NEW_EVENTS_BEGIN; i <= MAX_EVENT_TYPE_MARIADB10; i++)
dcb_printf(dcb, "\t\tMariaDB 10 %-38s %u\n", event_names_mariadb10[(i - MARIADB_NEW_EVENTS_BEGIN)], router_inst->stats.events[i]);
}
#if SPINLOCK_PROFILE
dcb_printf(dcb, "\tSpinlock statistics (instlock):\n");
spinlock_stats(&instlock, spin_reporter, dcb);
@ -1058,7 +1123,7 @@ struct tm tm;
if (session->lastEventTimestamp
&& router_inst->lastEventTimestamp)
{
localtime_r(&session->lastEventTimestamp, &tm);
localtime_r((const time_t*)&session->lastEventTimestamp, &tm);
asctime_r(&tm, buf);
dcb_printf(dcb, "\t\tLast binlog event timestamp %u, %s", session->lastEventTimestamp, buf);
dcb_printf(dcb, "\t\tSeconds behind master %u\n", router_inst->lastEventTimestamp - session->lastEventTimestamp);
@ -1156,7 +1221,8 @@ static void
errorReply(ROUTER *instance, void *router_session, GWBUF *message, DCB *backend_dcb, error_action_t action, bool *succp)
{
ROUTER_INSTANCE *router = (ROUTER_INSTANCE *)instance;
int error, len;
int error;
socklen_t len;
char msg[85], *errmsg;
unsigned long mysql_errno;
@ -1329,10 +1395,10 @@ unsigned long len;
snprintf(result, 1000,
"Uptime: %u Threads: %u Events: %u Slaves: %u Master State: %s",
time(0) - router->connect_time,
config_threadcount(),
router->stats.n_binlogs_ses,
router->stats.n_slaves,
(unsigned int)(time(0) - router->connect_time),
(unsigned int)config_threadcount(),
(unsigned int)router->stats.n_binlogs_ses,
(unsigned int)router->stats.n_slaves,
blrm_states[router->master_state]);
if ((ret = gwbuf_alloc(4 + strlen(result))) == NULL)
return 0;
@ -1684,5 +1750,24 @@ int mkdir_rval;
strncat(path, "/dbusers", PATH_MAX);
return dbusers_save(service->users, path);
}
/**
* Extract a numeric field from a packet of the specified number of bits
*
* @param src The raw packet source
* @param birs The number of bits to extract (multiple of 8)
*/
uint32_t
extract_field(uint8_t *src, int bits)
{
uint32_t rval = 0, shift = 0;
while (bits > 0)
{
rval |= (*src++) << shift;
shift += 8;
bits -= 8;
}
return rval;
}