Addition of slave heartbeat check
Addition of slave heartbeat check
This commit is contained in:
@ -316,6 +316,8 @@ typedef struct router_slave {
|
|||||||
SLAVE_STATS stats; /*< Slave statistics */
|
SLAVE_STATS stats; /*< Slave statistics */
|
||||||
time_t connect_time; /*< Connect time of slave */
|
time_t connect_time; /*< Connect time of slave */
|
||||||
char *warning_msg; /*< Warning message */
|
char *warning_msg; /*< Warning message */
|
||||||
|
int heartbeat; /*< Heartbeat in seconds */
|
||||||
|
uint8_t lastEventReceived; /*< Last event received */
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t rses_chk_tail;
|
skygw_chk_t rses_chk_tail;
|
||||||
#endif
|
#endif
|
||||||
|
@ -771,6 +771,8 @@ ROUTER_SLAVE *slave;
|
|||||||
slave->connect_time = time(0);
|
slave->connect_time = time(0);
|
||||||
slave->lastEventTimestamp = 0;
|
slave->lastEventTimestamp = 0;
|
||||||
slave->mariadb10_compat = false;
|
slave->mariadb10_compat = false;
|
||||||
|
slave->heartbeat = 0;
|
||||||
|
slave->lastEventReceived = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add this session to the list of active sessions.
|
* Add this session to the list of active sessions.
|
||||||
@ -1234,6 +1236,9 @@ struct tm tm;
|
|||||||
dcb_printf(dcb,
|
dcb_printf(dcb,
|
||||||
"\t\tNo. transitions to follow mode: %u\n",
|
"\t\tNo. transitions to follow mode: %u\n",
|
||||||
session->stats.n_bursts);
|
session->stats.n_bursts);
|
||||||
|
dcb_printf(dcb, "\t\tHeartbeat period (seconds): %lu\n",
|
||||||
|
session->heartbeat);
|
||||||
|
|
||||||
minno = session->stats.minno - 1;
|
minno = session->stats.minno - 1;
|
||||||
if (minno == -1)
|
if (minno == -1)
|
||||||
minno = 30;
|
minno = 30;
|
||||||
@ -1254,13 +1259,20 @@ struct tm tm;
|
|||||||
dcb_printf(dcb, "\t\tNo. of distribute action 3 %u\n", session->stats.n_actions[2]);
|
dcb_printf(dcb, "\t\tNo. of distribute action 3 %u\n", session->stats.n_actions[2]);
|
||||||
#endif
|
#endif
|
||||||
if (session->lastEventTimestamp
|
if (session->lastEventTimestamp
|
||||||
&& router_inst->lastEventTimestamp)
|
&& router_inst->lastEventTimestamp && session->lastEventReceived != HEARTBEAT_EVENT)
|
||||||
{
|
{
|
||||||
|
unsigned long seconds_behind;
|
||||||
time_t session_last_event = (time_t)session->lastEventTimestamp;
|
time_t session_last_event = (time_t)session->lastEventTimestamp;
|
||||||
|
|
||||||
|
if (router_inst->lastEventTimestamp > session->lastEventTimestamp)
|
||||||
|
seconds_behind = router_inst->lastEventTimestamp - session->lastEventTimestamp;
|
||||||
|
else
|
||||||
|
seconds_behind = 0;
|
||||||
|
|
||||||
localtime_r(&session_last_event, &tm);
|
localtime_r(&session_last_event, &tm);
|
||||||
asctime_r(&tm, buf);
|
asctime_r(&tm, buf);
|
||||||
dcb_printf(dcb, "\t\tLast binlog event timestamp %u, %s", session->lastEventTimestamp, 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);
|
dcb_printf(dcb, "\t\tSeconds behind master %lu\n", seconds_behind);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session->state == 0)
|
if (session->state == 0)
|
||||||
|
@ -400,13 +400,15 @@ BLFILE *file;
|
|||||||
GWBUF *
|
GWBUF *
|
||||||
blr_read_binlog(ROUTER_INSTANCE *router, BLFILE *file, unsigned int pos, REP_HEADER *hdr)
|
blr_read_binlog(ROUTER_INSTANCE *router, BLFILE *file, unsigned int pos, REP_HEADER *hdr)
|
||||||
{
|
{
|
||||||
uint8_t hdbuf[19];
|
uint8_t hdbuf[BINLOG_EVENT_HDR_LEN];
|
||||||
GWBUF *result;
|
GWBUF *result;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
int n;
|
int n;
|
||||||
unsigned long filelen = 0;
|
unsigned long filelen = 0;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
|
|
||||||
|
memset(&hdbuf, '\0', BINLOG_EVENT_HDR_LEN);
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -436,7 +438,7 @@ struct stat statb;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read the header information from the file */
|
/* Read the header information from the file */
|
||||||
if ((n = pread(file->fd, hdbuf, 19, pos)) != 19)
|
if ((n = pread(file->fd, hdbuf, BINLOG_EVENT_HDR_LEN, pos)) != BINLOG_EVENT_HDR_LEN)
|
||||||
{
|
{
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
@ -506,7 +508,7 @@ struct stat statb;
|
|||||||
"file size is %lu. Master will write %lu in %s next.",
|
"file size is %lu. Master will write %lu in %s next.",
|
||||||
pos, file->binlogname, filelen, router->binlog_position,
|
pos, file->binlogname, filelen, router->binlog_position,
|
||||||
router->binlog_name)));
|
router->binlog_name)));
|
||||||
if ((n = pread(file->fd, hdbuf, 19, pos)) != 19)
|
if ((n = pread(file->fd, hdbuf, BINLOG_EVENT_HDR_LEN, pos)) != BINLOG_EVENT_HDR_LEN)
|
||||||
{
|
{
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
@ -571,9 +573,9 @@ struct stat statb;
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
data = GWBUF_DATA(result);
|
data = GWBUF_DATA(result);
|
||||||
memcpy(data, hdbuf, 19); // Copy the header in
|
memcpy(data, hdbuf, BINLOG_EVENT_HDR_LEN); // Copy the header in
|
||||||
if ((n = pread(file->fd, &data[19], hdr->event_size - 19, pos + 19))
|
if ((n = pread(file->fd, &data[BINLOG_EVENT_HDR_LEN], hdr->event_size - BINLOG_EVENT_HDR_LEN, pos + BINLOG_EVENT_HDR_LEN))
|
||||||
!= hdr->event_size - 19) // Read the balance
|
!= hdr->event_size - BINLOG_EVENT_HDR_LEN) // Read the balance
|
||||||
{
|
{
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
@ -583,14 +585,14 @@ struct stat statb;
|
|||||||
"Error reading the event at %ld in %s. "
|
"Error reading the event at %ld in %s. "
|
||||||
"%s, expected %d bytes.",
|
"%s, expected %d bytes.",
|
||||||
pos, file->binlogname,
|
pos, file->binlogname,
|
||||||
err_msg, hdr->event_size - 19)));
|
err_msg, hdr->event_size - BINLOG_EVENT_HDR_LEN)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write(LOGFILE_ERROR,
|
LOGIF(LE, (skygw_log_write(LOGFILE_ERROR,
|
||||||
"Short read when reading the event at %ld in %s. "
|
"Short read when reading the event at %ld in %s. "
|
||||||
"Expected %d bytes got %d bytes.",
|
"Expected %d bytes got %d bytes.",
|
||||||
pos, file->binlogname, hdr->event_size - 19, n)));
|
pos, file->binlogname, hdr->event_size - BINLOG_EVENT_HDR_LEN, n)));
|
||||||
if (filelen != 0 && filelen - pos < hdr->event_size)
|
if (filelen != 0 && filelen - pos < hdr->event_size)
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write(LOGFILE_ERROR,
|
LOGIF(LE, (skygw_log_write(LOGFILE_ERROR,
|
||||||
@ -665,7 +667,7 @@ int i;
|
|||||||
|
|
||||||
bufp = buf;
|
bufp = buf;
|
||||||
bufp += sprintf(bufp, "%s: ", msg);
|
bufp += sprintf(bufp, "%s: ", msg);
|
||||||
for (i = 0; i < 19; i++)
|
for (i = 0; i < BINLOG_EVENT_HDR_LEN; i++)
|
||||||
bufp += sprintf(bufp, "0x%02x ", ptr[i]);
|
bufp += sprintf(bufp, "0x%02x ", ptr[i]);
|
||||||
skygw_log_write_flush(file, "%s", buf);
|
skygw_log_write_flush(file, "%s", buf);
|
||||||
|
|
||||||
@ -803,7 +805,7 @@ int
|
|||||||
blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug) {
|
blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug) {
|
||||||
unsigned long filelen = 0;
|
unsigned long filelen = 0;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
uint8_t hdbuf[19];
|
uint8_t hdbuf[BINLOG_EVENT_HDR_LEN];
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
GWBUF *result;
|
GWBUF *result;
|
||||||
unsigned long long pos = 4;
|
unsigned long long pos = 4;
|
||||||
@ -846,7 +848,7 @@ double average_bytes = 0;
|
|||||||
while (1){
|
while (1){
|
||||||
|
|
||||||
/* Read the header information from the file */
|
/* Read the header information from the file */
|
||||||
if ((n = pread(router->binlog_fd, hdbuf, 19, pos)) != 19) {
|
if ((n = pread(router->binlog_fd, hdbuf, BINLOG_EVENT_HDR_LEN, pos)) != BINLOG_EVENT_HDR_LEN) {
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@ -1079,10 +1081,10 @@ double average_bytes = 0;
|
|||||||
|
|
||||||
/* Copy the header in the buffer */
|
/* Copy the header in the buffer */
|
||||||
data = GWBUF_DATA(result);
|
data = GWBUF_DATA(result);
|
||||||
memcpy(data, hdbuf, 19);// Copy the header in
|
memcpy(data, hdbuf, BINLOG_EVENT_HDR_LEN);// Copy the header in
|
||||||
|
|
||||||
/* Read event data */
|
/* Read event data */
|
||||||
if ((n = pread(router->binlog_fd, &data[19], hdr.event_size - 19, pos + 19)) != hdr.event_size - 19)
|
if ((n = pread(router->binlog_fd, &data[BINLOG_EVENT_HDR_LEN], hdr.event_size - BINLOG_EVENT_HDR_LEN, pos + BINLOG_EVENT_HDR_LEN)) != hdr.event_size - BINLOG_EVENT_HDR_LEN)
|
||||||
{
|
{
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
@ -1092,14 +1094,14 @@ double average_bytes = 0;
|
|||||||
"Error reading the event at %llu in %s. "
|
"Error reading the event at %llu in %s. "
|
||||||
"%s, expected %d bytes.",
|
"%s, expected %d bytes.",
|
||||||
pos, router->binlog_name,
|
pos, router->binlog_name,
|
||||||
err_msg, hdr.event_size - 19)));
|
err_msg, hdr.event_size - BINLOG_EVENT_HDR_LEN)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||||
"Short read when reading the event at %llu in %s. "
|
"Short read when reading the event at %llu in %s. "
|
||||||
"Expected %d bytes got %d bytes.",
|
"Expected %d bytes got %d bytes.",
|
||||||
pos, router->binlog_name, hdr.event_size - 19, n)));
|
pos, router->binlog_name, hdr.event_size - BINLOG_EVENT_HDR_LEN, n)));
|
||||||
|
|
||||||
if (filelen > 0 && filelen - pos < hdr.event_size)
|
if (filelen > 0 && filelen - pos < hdr.event_size)
|
||||||
{
|
{
|
||||||
@ -1138,7 +1140,7 @@ double average_bytes = 0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get event content */
|
/* get event content */
|
||||||
ptr = data+19;
|
ptr = data+BINLOG_EVENT_HDR_LEN;
|
||||||
|
|
||||||
/* check for FORMAT DESCRIPTION EVENT */
|
/* check for FORMAT DESCRIPTION EVENT */
|
||||||
if(hdr.event_type == FORMAT_DESCRIPTION_EVENT) {
|
if(hdr.event_type == FORMAT_DESCRIPTION_EVENT) {
|
||||||
@ -1204,7 +1206,7 @@ double average_bytes = 0;
|
|||||||
uint64_t new_pos;
|
uint64_t new_pos;
|
||||||
char file[BINLOG_FNAMELEN+1];
|
char file[BINLOG_FNAMELEN+1];
|
||||||
|
|
||||||
len = hdr.event_size - 19;
|
len = hdr.event_size - BINLOG_EVENT_HDR_LEN;
|
||||||
new_pos = extract_field(ptr+4, 32);
|
new_pos = extract_field(ptr+4, 32);
|
||||||
new_pos <<= 32;
|
new_pos <<= 32;
|
||||||
new_pos |= extract_field(ptr, 32);
|
new_pos |= extract_field(ptr, 32);
|
||||||
@ -1276,7 +1278,7 @@ double average_bytes = 0;
|
|||||||
db_name_len = ptr[4 + 4];
|
db_name_len = ptr[4 + 4];
|
||||||
var_block_len = ptr[4 + 4 + 1 + 2];
|
var_block_len = ptr[4 + 4 + 1 + 2];
|
||||||
|
|
||||||
statement_len = hdr.event_size - 19 - (4+4+1+2+2+var_block_len+1+db_name_len);
|
statement_len = hdr.event_size - BINLOG_EVENT_HDR_LEN - (4+4+1+2+2+var_block_len+1+db_name_len);
|
||||||
|
|
||||||
statement_sql = calloc(1, statement_len+1);
|
statement_sql = calloc(1, statement_len+1);
|
||||||
strncpy(statement_sql, (char *)ptr+4+4+1+2+2+var_block_len+1+db_name_len, statement_len);
|
strncpy(statement_sql, (char *)ptr+4+4+1+2+2+var_block_len+1+db_name_len, statement_len);
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
* This is the current supported condition for detecting
|
* This is the current supported condition for detecting
|
||||||
* MariaDB 10 transaction start point.
|
* MariaDB 10 transaction start point.
|
||||||
* It's no longer using QUERY_EVENT with BEGIN
|
* It's no longer using QUERY_EVENT with BEGIN
|
||||||
|
* 25/09/2015 Massimiliano Pinto Addition of lastEventReceived for slaves
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -1610,6 +1611,8 @@ int action;
|
|||||||
* memory to the slave.
|
* memory to the slave.
|
||||||
*/
|
*/
|
||||||
slave->lastEventTimestamp = hdr->timestamp;
|
slave->lastEventTimestamp = hdr->timestamp;
|
||||||
|
slave->lastEventReceived = hdr->event_type;
|
||||||
|
|
||||||
pkt = gwbuf_alloc(hdr->event_size + 5);
|
pkt = gwbuf_alloc(hdr->event_size + 5);
|
||||||
buf = GWBUF_DATA(pkt);
|
buf = GWBUF_DATA(pkt);
|
||||||
encode_value(buf, hdr->event_size + 1, 24);
|
encode_value(buf, hdr->event_size + 1, 24);
|
||||||
@ -1761,6 +1764,9 @@ uint8_t *ptr;
|
|||||||
int len, ncol, collen;
|
int len, ncol, collen;
|
||||||
char *rval;
|
char *rval;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
ptr = (uint8_t *)GWBUF_DATA(buf);
|
ptr = (uint8_t *)GWBUF_DATA(buf);
|
||||||
/* First packet should be the column count */
|
/* First packet should be the column count */
|
||||||
len = EXTRACT24(ptr);
|
len = EXTRACT24(ptr);
|
||||||
|
@ -55,6 +55,9 @@
|
|||||||
* 03/09/2015 Massimiliano Pinto Added support for SHOW [GLOBAL] VARIABLES LIKE
|
* 03/09/2015 Massimiliano Pinto Added support for SHOW [GLOBAL] VARIABLES LIKE
|
||||||
* 04/09/2015 Massimiliano Pinto Added support for SHOW WARNINGS
|
* 04/09/2015 Massimiliano Pinto Added support for SHOW WARNINGS
|
||||||
* 15/09/2015 Massimiliano Pinto Added support for SHOW [GLOBAL] STATUS LIKE 'Uptime'
|
* 15/09/2015 Massimiliano Pinto Added support for SHOW [GLOBAL] STATUS LIKE 'Uptime'
|
||||||
|
* 25/09/2015 Massimiliano Pinto Addition of slave heartbeat:
|
||||||
|
* the period set during registration is checked
|
||||||
|
* and heartbeat event might be sent to the affected slave.
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -145,6 +148,8 @@ extern int MaxScaleUptime();
|
|||||||
static int blr_slave_send_status_variable(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *variable, char *value, int column_type);
|
static int blr_slave_send_status_variable(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *variable, char *value, int column_type);
|
||||||
static int blr_slave_handle_status_variables(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *stmt);
|
static int blr_slave_handle_status_variables(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *stmt);
|
||||||
static int blr_slave_send_columndef_with_status_schema(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *name, int type, int len, uint8_t seqno);
|
static int blr_slave_send_columndef_with_status_schema(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, char *name, int type, int len, uint8_t seqno);
|
||||||
|
static void blr_send_slave_heartbeat(void *inst);
|
||||||
|
static int blr_slave_send_heartbeat(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||||
|
|
||||||
void poll_fake_write_event(DCB *dcb);
|
void poll_fake_write_event(DCB *dcb);
|
||||||
|
|
||||||
@ -226,8 +231,20 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case COM_BINLOG_DUMP:
|
case COM_BINLOG_DUMP:
|
||||||
return blr_slave_binlog_dump(router, slave, queue);
|
{
|
||||||
|
char task_name[BLRM_TASK_NAME_LEN+1]="";
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
rc = blr_slave_binlog_dump(router, slave, queue);
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
snprintf(task_name, BLRM_TASK_NAME_LEN, "%s slaves heartbeat send", router->service->name);
|
||||||
|
hktask_add(task_name, blr_send_slave_heartbeat, router, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case COM_STATISTICS:
|
case COM_STATISTICS:
|
||||||
return blr_statistics(router, slave, queue);
|
return blr_statistics(router, slave, queue);
|
||||||
break;
|
break;
|
||||||
@ -613,6 +630,22 @@ extern char *strcasestr();
|
|||||||
}
|
}
|
||||||
else if (strcasecmp(word, "@master_heartbeat_period") == 0)
|
else if (strcasecmp(word, "@master_heartbeat_period") == 0)
|
||||||
{
|
{
|
||||||
|
int slave_heartbeat;
|
||||||
|
int v_len = 0;
|
||||||
|
word = strtok_r(NULL, sep, &brkb);
|
||||||
|
if (word) {
|
||||||
|
char *new_val;
|
||||||
|
v_len = strlen(word);
|
||||||
|
if (v_len > 6) {
|
||||||
|
new_val = strndup(word, v_len - 6);
|
||||||
|
slave->heartbeat = atoi(new_val) / 1000;
|
||||||
|
} else {
|
||||||
|
new_val = strndup(word, v_len);
|
||||||
|
slave->heartbeat = atoi(new_val) / 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(new_val);
|
||||||
|
}
|
||||||
free(query_text);
|
free(query_text);
|
||||||
return blr_slave_replay(router, slave, router->saved_master.heartbeat);
|
return blr_slave_replay(router, slave, router->saved_master.heartbeat);
|
||||||
}
|
}
|
||||||
@ -1708,9 +1741,9 @@ uint32_t chksum;
|
|||||||
|
|
||||||
|
|
||||||
if (slave->nocrc)
|
if (slave->nocrc)
|
||||||
len = 19 + 8 + binlognamelen;
|
len = BINLOG_EVENT_HDR_LEN + 8 + binlognamelen;
|
||||||
else
|
else
|
||||||
len = 19 + 8 + 4 + binlognamelen;
|
len = BINLOG_EVENT_HDR_LEN + 8 + 4 + binlognamelen;
|
||||||
|
|
||||||
// Build a fake rotate event
|
// Build a fake rotate event
|
||||||
resp = gwbuf_alloc(len + 5);
|
resp = gwbuf_alloc(len + 5);
|
||||||
@ -1744,6 +1777,9 @@ uint32_t chksum;
|
|||||||
encode_value(ptr, chksum, 32);
|
encode_value(ptr, chksum, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slave->lastEventTimestamp = time(0);
|
||||||
|
slave->lastEventReceived = ROTATE_EVENT;
|
||||||
|
|
||||||
rval = slave->dcb->func.write(slave->dcb, resp);
|
rval = slave->dcb->func.write(slave->dcb, resp);
|
||||||
|
|
||||||
/* Send the FORMAT_DESCRIPTION_EVENT */
|
/* Send the FORMAT_DESCRIPTION_EVENT */
|
||||||
@ -1913,15 +1949,18 @@ uint8_t *ptr;
|
|||||||
*ptr++ = 0; // OK
|
*ptr++ = 0; // OK
|
||||||
head = gwbuf_append(head, record);
|
head = gwbuf_append(head, record);
|
||||||
slave->lastEventTimestamp = hdr.timestamp;
|
slave->lastEventTimestamp = hdr.timestamp;
|
||||||
|
slave->lastEventReceived = hdr.event_type;
|
||||||
|
|
||||||
if (hdr.event_type == ROTATE_EVENT)
|
if (hdr.event_type == ROTATE_EVENT)
|
||||||
{
|
{
|
||||||
unsigned long beat1 = hkheartbeat;
|
unsigned long beat1 = hkheartbeat;
|
||||||
blr_close_binlog(router, slave->file);
|
blr_close_binlog(router, slave->file);
|
||||||
if (hkheartbeat - beat1 > 1) LOGIF(LE, (skygw_log_write(
|
if (hkheartbeat - beat1 > 1)
|
||||||
LOGFILE_ERROR, "blr_close_binlog took %d beats",
|
LOGIF(LE, (skygw_log_write(
|
||||||
hkheartbeat - beat1)));
|
LOGFILE_ERROR, "blr_close_binlog took %d maxscale beats",
|
||||||
|
hkheartbeat - beat1)));
|
||||||
blr_slave_rotate(router, slave, GWBUF_DATA(record));
|
blr_slave_rotate(router, slave, GWBUF_DATA(record));
|
||||||
beat1 = hkheartbeat;
|
beat1 = hkheartbeat;
|
||||||
if ((slave->file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
if ((slave->file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||||
{
|
{
|
||||||
if (rotating)
|
if (rotating)
|
||||||
@ -1941,9 +1980,10 @@ beat1 = hkheartbeat;
|
|||||||
dcb_close(slave->dcb);
|
dcb_close(slave->dcb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (hkheartbeat - beat1 > 1) LOGIF(LE, (skygw_log_write(
|
if (hkheartbeat - beat1 > 1)
|
||||||
LOGFILE_ERROR, "blr_open_binlog took %d beats",
|
LOGIF(LE, (skygw_log_write(
|
||||||
hkheartbeat - beat1)));
|
LOGFILE_ERROR, "blr_open_binlog took %d beats",
|
||||||
|
hkheartbeat - beat1)));
|
||||||
}
|
}
|
||||||
slave->stats.n_bytes += gwbuf_length(head);
|
slave->stats.n_bytes += gwbuf_length(head);
|
||||||
written = slave->dcb->func.write(slave->dcb, head);
|
written = slave->dcb->func.write(slave->dcb, head);
|
||||||
@ -2129,12 +2169,12 @@ blr_slave_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint8_t *ptr)
|
|||||||
{
|
{
|
||||||
int len = EXTRACT24(ptr + 9); // Extract the event length
|
int len = EXTRACT24(ptr + 9); // Extract the event length
|
||||||
|
|
||||||
len = len - (19 + 8); // Remove length of header and position
|
len = len - (BINLOG_EVENT_HDR_LEN + 8); // Remove length of header and position
|
||||||
if (router->master_chksum)
|
if (router->master_chksum)
|
||||||
len -= 4;
|
len -= 4;
|
||||||
if (len > BINLOG_FNAMELEN)
|
if (len > BINLOG_FNAMELEN)
|
||||||
len = BINLOG_FNAMELEN;
|
len = BINLOG_FNAMELEN;
|
||||||
ptr += 19; // Skip header
|
ptr += BINLOG_EVENT_HDR_LEN; // Skip header
|
||||||
slave->binlog_pos = extract_field(ptr, 32);
|
slave->binlog_pos = extract_field(ptr, 32);
|
||||||
slave->binlog_pos += (((uint64_t)extract_field(ptr+4, 32)) << 32);
|
slave->binlog_pos += (((uint64_t)extract_field(ptr+4, 32)) << 32);
|
||||||
memcpy(slave->binlogfile, ptr + 8, len);
|
memcpy(slave->binlogfile, ptr + 8, len);
|
||||||
@ -2170,7 +2210,7 @@ uint32_t chksum;
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
binlognamelen = strlen(slave->binlogfile);
|
binlognamelen = strlen(slave->binlogfile);
|
||||||
len = 19 + 8 + 4 + binlognamelen;
|
len = BINLOG_EVENT_HDR_LEN + 8 + 4 + binlognamelen;
|
||||||
/* no slave crc, remove 4 bytes */
|
/* no slave crc, remove 4 bytes */
|
||||||
if (slave->nocrc)
|
if (slave->nocrc)
|
||||||
len -= 4;
|
len -= 4;
|
||||||
@ -2226,6 +2266,8 @@ GWBUF *record, *head;
|
|||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
uint32_t chksum;
|
uint32_t chksum;
|
||||||
|
|
||||||
|
memset(&hdr, 0, BINLOG_EVENT_HDR_LEN);
|
||||||
|
|
||||||
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||||
return;
|
return;
|
||||||
if ((record = blr_read_binlog(router, file, 4, &hdr)) == NULL)
|
if ((record = blr_read_binlog(router, file, 4, &hdr)) == NULL)
|
||||||
@ -2256,6 +2298,10 @@ uint32_t chksum;
|
|||||||
chksum = crc32(0L, NULL, 0);
|
chksum = crc32(0L, NULL, 0);
|
||||||
chksum = crc32(chksum, GWBUF_DATA(record), hdr.event_size - 4);
|
chksum = crc32(chksum, GWBUF_DATA(record), hdr.event_size - 4);
|
||||||
encode_value(ptr, chksum, 32);
|
encode_value(ptr, chksum, 32);
|
||||||
|
|
||||||
|
slave->lastEventTimestamp = time(0);
|
||||||
|
slave->lastEventReceived = FORMAT_DESCRIPTION_EVENT;
|
||||||
|
|
||||||
slave->dcb->func.write(slave->dcb, head);
|
slave->dcb->func.write(slave->dcb, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3700,6 +3746,9 @@ GWBUF *pkt;
|
|||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
int len, vers_len;
|
int len, vers_len;
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
return blr_slave_send_ok(router, slave);
|
||||||
|
|
||||||
vers_len = strlen(value);
|
vers_len = strlen(value);
|
||||||
blr_slave_send_fieldcount(router, slave, 1);
|
blr_slave_send_fieldcount(router, slave, 1);
|
||||||
blr_slave_send_columndef(router, slave, variable, column_type, vers_len, 2);
|
blr_slave_send_columndef(router, slave, variable, column_type, vers_len, 2);
|
||||||
@ -3740,6 +3789,9 @@ char *p = strdup(variable);
|
|||||||
int var_len;
|
int var_len;
|
||||||
char *old_ptr = p;
|
char *old_ptr = p;
|
||||||
|
|
||||||
|
if (value == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Remove heading and trailing "'" */
|
/* Remove heading and trailing "'" */
|
||||||
if(*p == '\'')
|
if(*p == '\'')
|
||||||
p++;
|
p++;
|
||||||
@ -3922,8 +3974,9 @@ char *sep = " ,=";
|
|||||||
} else
|
} else
|
||||||
return blr_slave_replay(router, slave, router->saved_master.server_id);
|
return blr_slave_replay(router, slave, router->saved_master.server_id);
|
||||||
} else if (strcasecmp(word, "'SERVER_UUID'") == 0) {
|
} else if (strcasecmp(word, "'SERVER_UUID'") == 0) {
|
||||||
if (router->set_master_uuid)
|
if (router->set_master_uuid) {
|
||||||
return blr_slave_send_variable(router, slave, "'SERVER_UUID'", router->master_uuid, BLR_TYPE_STRING);
|
return blr_slave_send_variable(router, slave, "'SERVER_UUID'", router->master_uuid, BLR_TYPE_STRING);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return blr_slave_replay(router, slave, router->saved_master.uuid);
|
return blr_slave_replay(router, slave, router->saved_master.uuid);
|
||||||
} else if (strcasecmp(word, "'MAXSCALE%'") == 0) {
|
} else if (strcasecmp(word, "'MAXSCALE%'") == 0) {
|
||||||
@ -4243,3 +4296,121 @@ char *ptr_name_start = name;
|
|||||||
return slave->dcb->func.write(slave->dcb, pkt);
|
return slave->dcb->func.write(slave->dcb, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The heartbeat check function called from the housekeeper for registered slaves.
|
||||||
|
*
|
||||||
|
* @param router Current router instance
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
blr_send_slave_heartbeat(void *inst) {
|
||||||
|
ROUTER_SLAVE *sptr = NULL;
|
||||||
|
ROUTER_INSTANCE *router = (ROUTER_INSTANCE *) inst;
|
||||||
|
time_t t_now = time(0);
|
||||||
|
|
||||||
|
spinlock_acquire(&router->lock);
|
||||||
|
|
||||||
|
sptr = router->slaves;
|
||||||
|
|
||||||
|
while (sptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* skip servers with state = 0 */
|
||||||
|
if ( (sptr->state == BLRS_DUMPING) && (sptr->heartbeat > 0) && ((t_now + 1 - sptr->lastEventTimestamp) >= sptr->heartbeat) )
|
||||||
|
{
|
||||||
|
LOGIF(LM, (skygw_log_write(
|
||||||
|
LOGFILE_MESSAGE, "Sending Heartbeat to slave server-id %d in State %d, cstate %d. "
|
||||||
|
"Heartbeat interval is %d, last event time is %lu",
|
||||||
|
sptr->serverid, sptr->state, sptr->cstate, sptr->heartbeat,
|
||||||
|
(unsigned long)sptr->lastEventTimestamp)));
|
||||||
|
|
||||||
|
blr_slave_send_heartbeat(router, sptr);
|
||||||
|
|
||||||
|
sptr->lastEventTimestamp = t_now;
|
||||||
|
|
||||||
|
sptr->lastEventReceived = HEARTBEAT_EVENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
sptr = sptr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_release(&router->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and send an hearbeat packet to be sent to a registered slave server
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
blr_slave_send_heartbeat(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||||
|
{
|
||||||
|
REP_HEADER hdr;
|
||||||
|
GWBUF *resp;
|
||||||
|
uint8_t *ptr;
|
||||||
|
int len = BINLOG_EVENT_HDR_LEN;
|
||||||
|
uint32_t chksum;
|
||||||
|
|
||||||
|
/* Add CRC32 4 bytes */
|
||||||
|
if (!slave->nocrc)
|
||||||
|
len +=4;
|
||||||
|
|
||||||
|
/* add binlogname to data content len */
|
||||||
|
len += strlen(slave->binlogfile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alloc buffer for network binlog stream:
|
||||||
|
*
|
||||||
|
* 4 bytes header (3 for pkt len + 1 seq.no)
|
||||||
|
* 1 byte for Ok / ERR
|
||||||
|
* n bytes data content
|
||||||
|
*
|
||||||
|
* Total = 5 bytes + len
|
||||||
|
*/
|
||||||
|
resp = gwbuf_alloc(5 + len);
|
||||||
|
|
||||||
|
/* The OK/Err byte is part of payload */
|
||||||
|
hdr.payload_len = len + 1;
|
||||||
|
|
||||||
|
/* Add sequence no */
|
||||||
|
hdr.seqno = slave->seqno++;
|
||||||
|
|
||||||
|
/* Add OK */
|
||||||
|
hdr.ok = 0;
|
||||||
|
|
||||||
|
/* Add timestamp: 0 */
|
||||||
|
hdr.timestamp = 0L;
|
||||||
|
|
||||||
|
/* Set Event Type */
|
||||||
|
hdr.event_type = HEARTBEAT_EVENT;
|
||||||
|
|
||||||
|
/* Add master server id */
|
||||||
|
hdr.serverid = router->masterid;
|
||||||
|
|
||||||
|
/* Add event size */
|
||||||
|
hdr.event_size = len;
|
||||||
|
|
||||||
|
/* Add Next Pos */
|
||||||
|
hdr.next_pos = slave->binlog_pos;
|
||||||
|
|
||||||
|
/* Add flags */
|
||||||
|
hdr.flags = 0x20;
|
||||||
|
|
||||||
|
/* point just after the header */
|
||||||
|
ptr = blr_build_header(resp, &hdr);
|
||||||
|
|
||||||
|
/* Copy binlog name */
|
||||||
|
memcpy(ptr, slave->binlogfile, BINLOG_FNAMELEN);
|
||||||
|
|
||||||
|
ptr += strlen(slave->binlogfile);
|
||||||
|
|
||||||
|
/* Add the CRC32 */
|
||||||
|
if (!slave->nocrc)
|
||||||
|
{
|
||||||
|
chksum = crc32(0L, NULL, 0);
|
||||||
|
chksum = crc32(chksum, GWBUF_DATA(resp) + 5, hdr.event_size - 4);
|
||||||
|
encode_value(ptr, chksum, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the packet */
|
||||||
|
return slave->dcb->func.write(slave->dcb, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user