Merge branch 'develop' into MAX-268
This commit is contained in:
@ -43,8 +43,8 @@
|
||||
* High and Low water marks for the slave dcb. These values can be overriden
|
||||
* by the router options highwater and lowwater.
|
||||
*/
|
||||
#define DEF_LOW_WATER 20000
|
||||
#define DEF_HIGH_WATER 300000
|
||||
#define DEF_LOW_WATER 2000
|
||||
#define DEF_HIGH_WATER 30000
|
||||
|
||||
/**
|
||||
* Some useful macros for examining the MySQL Response packets
|
||||
@ -194,6 +194,7 @@ typedef struct router_instance {
|
||||
char *uuid; /*< UUID for the router to use w/master */
|
||||
int masterid; /*< Server ID of the master */
|
||||
int serverid; /*< Server ID to use with master */
|
||||
int initbinlog; /*< Initial binlog file number */
|
||||
char *user; /*< User name to use with master */
|
||||
char *password; /*< Password to use with master */
|
||||
char *fileroot; /*< Root of binlog filename */
|
||||
|
||||
@ -224,6 +224,7 @@ typedef struct backend_ref_st {
|
||||
bref_state_t bref_state;
|
||||
int bref_num_result_wait;
|
||||
sescmd_cursor_t bref_sescmd_cur;
|
||||
GWBUF* bref_pending_cmd; /*< For stmt which can't be routed due active sescmd execution */
|
||||
#if defined(SS_DEBUG)
|
||||
skygw_chk_t bref_chk_tail;
|
||||
#endif
|
||||
|
||||
@ -1180,9 +1180,9 @@ int gw_MySQLAccept(DCB *listener)
|
||||
conn_open[c_sock] = true;
|
||||
#endif
|
||||
/* set nonblocking */
|
||||
sendbuf = GW_BACKEND_SO_SNDBUF;
|
||||
sendbuf = GW_CLIENT_SO_SNDBUF;
|
||||
setsockopt(c_sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, optlen);
|
||||
sendbuf = GW_BACKEND_SO_RCVBUF;
|
||||
sendbuf = GW_CLIENT_SO_RCVBUF;
|
||||
setsockopt(c_sock, SOL_SOCKET, SO_RCVBUF, &sendbuf, optlen);
|
||||
setnonblocking(c_sock);
|
||||
|
||||
|
||||
@ -766,9 +766,9 @@ int gw_do_connect_to_backend(
|
||||
/* prepare for connect */
|
||||
setipaddress(&serv_addr.sin_addr, host);
|
||||
serv_addr.sin_port = htons(port);
|
||||
bufsize = GW_CLIENT_SO_SNDBUF;
|
||||
bufsize = GW_BACKEND_SO_SNDBUF;
|
||||
setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
|
||||
bufsize = GW_CLIENT_SO_RCVBUF;
|
||||
bufsize = GW_BACKEND_SO_RCVBUF;
|
||||
setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
|
||||
/* set socket to as non-blocking here */
|
||||
setnonblocking(so);
|
||||
@ -1660,6 +1660,8 @@ void protocol_archive_srv_command(
|
||||
server_command_t* h1;
|
||||
int len = 0;
|
||||
|
||||
CHK_PROTOCOL(p);
|
||||
|
||||
spinlock_acquire(&p->protocol_lock);
|
||||
|
||||
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
||||
@ -1710,6 +1712,7 @@ void protocol_archive_srv_command(
|
||||
|
||||
retblock:
|
||||
spinlock_release(&p->protocol_lock);
|
||||
CHK_PROTOCOL(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -15,4 +15,4 @@ target_link_libraries(cli log_manager utils)
|
||||
install(TARGETS cli DESTINATION modules)
|
||||
|
||||
add_subdirectory(readwritesplit)
|
||||
add_subdirectory(binlog)
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ libcli.so: $(CLIOBJ)
|
||||
$(CC) $(LDFLAGS) $(CLIOBJ) $(LIBS) -o $@
|
||||
|
||||
libreadwritesplit.so:
|
||||
# (cd readwritesplit; touch depend.mk ; make; cp $@ ..)
|
||||
(cd readwritesplit; touch depend.mk ; make; cp $@ ..)
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
@ -172,6 +172,7 @@ int i;
|
||||
|
||||
inst->low_water = DEF_LOW_WATER;
|
||||
inst->high_water = DEF_HIGH_WATER;
|
||||
inst->initbinlog = 0;
|
||||
|
||||
/*
|
||||
* We only support one server behind this router, since the server is
|
||||
@ -244,6 +245,10 @@ int i;
|
||||
{
|
||||
inst->fileroot = strdup(value);
|
||||
}
|
||||
else if (strcmp(options[i], "initialfile") == 0)
|
||||
{
|
||||
inst->initbinlog = atoi(value);
|
||||
}
|
||||
else if (strcmp(options[i], "lowwater") == 0)
|
||||
{
|
||||
inst->low_water = atoi(value);
|
||||
@ -450,11 +455,14 @@ ROUTER_SLAVE *slave = (ROUTER_SLAVE *)router_session;
|
||||
* TODO: Handle closure of master session
|
||||
*/
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR, "Binlog router close session with master")));
|
||||
LOGFILE_ERROR,
|
||||
"Binlog router close session with master server %s",
|
||||
router->service->databases->unique_name)));
|
||||
blr_master_reconnect(router);
|
||||
return;
|
||||
}
|
||||
CHK_CLIENT_RSES(slave);
|
||||
|
||||
/**
|
||||
* Lock router client session for secure read and update.
|
||||
*/
|
||||
|
||||
@ -115,7 +115,11 @@ struct dirent *dp;
|
||||
|
||||
if (n == 0) // No binlog files found
|
||||
{
|
||||
sprintf(filename, BINLOG_NAMEFMT, router->fileroot, 1);
|
||||
if (router->initbinlog)
|
||||
sprintf(filename, BINLOG_NAMEFMT, router->fileroot,
|
||||
router->initbinlog);
|
||||
else
|
||||
sprintf(filename, BINLOG_NAMEFMT, router->fileroot, 1);
|
||||
blr_file_create(router, filename);
|
||||
}
|
||||
else
|
||||
|
||||
@ -55,21 +55,57 @@
|
||||
#include <skygw_utils.h>
|
||||
#include <log_manager.h>
|
||||
|
||||
#include <rdtsc.h>
|
||||
|
||||
/* Temporary requirement for auth data */
|
||||
#include <mysql_client_server_protocol.h>
|
||||
|
||||
#define SAMPLE_COUNT 10000
|
||||
CYCLES samples[10][SAMPLE_COUNT];
|
||||
int sample_index[10] = { 0, 0, 0 };
|
||||
|
||||
#define LOGD_SLAVE_CATCHUP1 0
|
||||
#define LOGD_SLAVE_CATCHUP2 1
|
||||
#define LOGD_DISTRIBUTE 2
|
||||
#define LOGD_FILE_FLUSH 3
|
||||
|
||||
SPINLOCK logspin = SPINLOCK_INIT;
|
||||
|
||||
void
|
||||
log_duration(int sample, CYCLES duration)
|
||||
{
|
||||
char fname[100];
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
spinlock_acquire(&logspin);
|
||||
samples[sample][sample_index[sample]++] = duration;
|
||||
if (sample_index[sample] == SAMPLE_COUNT)
|
||||
{
|
||||
sprintf(fname, "binlog_profile.%d", sample);
|
||||
if ((fp = fopen(fname, "a")) != NULL)
|
||||
{
|
||||
for (i = 0; i < SAMPLE_COUNT; i++)
|
||||
fprintf(fp, "%ld\n", samples[sample][i]);
|
||||
fclose(fp);
|
||||
}
|
||||
sample_index[sample] = 0;
|
||||
}
|
||||
spinlock_release(&logspin);
|
||||
}
|
||||
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
|
||||
static GWBUF *blr_make_query(char *statement);
|
||||
static GWBUF *blr_make_registration(ROUTER_INSTANCE *router);
|
||||
static GWBUF *blr_make_binlog_dump(ROUTER_INSTANCE *router);
|
||||
static void encode_value(unsigned char *data, unsigned int value, int len);
|
||||
static void blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt);
|
||||
void encode_value(unsigned char *data, unsigned int value, int len);
|
||||
void blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt);
|
||||
static void blr_rotate_event(ROUTER_INSTANCE *router, uint8_t *pkt, REP_HEADER *hdr);
|
||||
static void blr_distribute_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint8_t *ptr);
|
||||
void blr_distribute_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint8_t *ptr);
|
||||
static void *CreateMySQLAuthData(char *username, char *password, char *database);
|
||||
static void blr_extract_header(uint8_t *pkt, REP_HEADER *hdr);
|
||||
static uint32_t extract_field(uint8_t *src, int bits);
|
||||
void blr_extract_header(uint8_t *pkt, REP_HEADER *hdr);
|
||||
inline uint32_t extract_field(uint8_t *src, int bits);
|
||||
static void blr_log_packet(logfile_id_t file, char *msg, uint8_t *ptr, int len);
|
||||
|
||||
static int keepalive = 1;
|
||||
@ -105,7 +141,8 @@ GWBUF *buf;
|
||||
if ((router->master = dcb_connect(router->service->databases, router->session, BLR_PROTOCOL)) == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
|
||||
"Binlog router: failed to connect to master\n")));
|
||||
"Binlog router: failed to connect to master server '%s'\n",
|
||||
router->service->databases->unique_name)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -459,7 +496,7 @@ int len = 0x1b;
|
||||
* @param value The value to pack
|
||||
* @param len Number of bits to encode value into
|
||||
*/
|
||||
static void
|
||||
void
|
||||
encode_value(unsigned char *data, unsigned int value, int len)
|
||||
{
|
||||
while (len > 0)
|
||||
@ -477,7 +514,7 @@ encode_value(unsigned char *data, unsigned int value, int len)
|
||||
* @param router The router instance
|
||||
* @param pkt The binlog records
|
||||
*/
|
||||
static void
|
||||
void
|
||||
blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt)
|
||||
{
|
||||
uint8_t *msg = NULL, *ptr, *pdata;
|
||||
@ -765,7 +802,9 @@ static REP_HEADER phdr;
|
||||
{
|
||||
ss_dassert(pkt_length == 0);
|
||||
}
|
||||
{ CYCLES start = rdtsc();
|
||||
blr_file_flush(router);
|
||||
log_duration(LOGD_FILE_FLUSH, rdtsc() - start); }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -774,7 +813,7 @@ static REP_HEADER phdr;
|
||||
* @param pkt The incoming packet in a GWBUF chain
|
||||
* @param hdr The packet header to populate
|
||||
*/
|
||||
static void
|
||||
void
|
||||
blr_extract_header(uint8_t *ptr, REP_HEADER *hdr)
|
||||
{
|
||||
|
||||
@ -795,10 +834,10 @@ blr_extract_header(uint8_t *ptr, REP_HEADER *hdr)
|
||||
* @param src The raw packet source
|
||||
* @param birs The number of bits to extract (multiple of 8)
|
||||
*/
|
||||
static uint32_t
|
||||
extract_field(uint8_t *src, int bits)
|
||||
inline uint32_t
|
||||
extract_field(register uint8_t *src, int bits)
|
||||
{
|
||||
uint32_t rval = 0, shift = 0;
|
||||
register uint32_t rval = 0, shift = 0;
|
||||
|
||||
while (bits > 0)
|
||||
{
|
||||
@ -828,7 +867,7 @@ char file[BINLOG_FNAMELEN+1];
|
||||
pos = extract_field(ptr+4, 32);
|
||||
pos <<= 32;
|
||||
pos |= extract_field(ptr, 32);
|
||||
slen = len - 8;
|
||||
slen = len - (8 + 4); // Allow for position and CRC
|
||||
if (slen > BINLOG_FNAMELEN)
|
||||
slen = BINLOG_FNAMELEN;
|
||||
memcpy(file, ptr + 8, slen);
|
||||
@ -883,14 +922,16 @@ MYSQL_session *auth_info;
|
||||
* @param hdr The replication event header
|
||||
* @param ptr The raw replication event data
|
||||
*/
|
||||
static void
|
||||
void
|
||||
blr_distribute_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint8_t *ptr)
|
||||
{
|
||||
GWBUF *pkt;
|
||||
uint8_t *buf;
|
||||
ROUTER_SLAVE *slave;
|
||||
int action;
|
||||
CYCLES entry;
|
||||
|
||||
entry = rdtsc();
|
||||
spinlock_acquire(&router->lock);
|
||||
slave = router->slaves;
|
||||
while (slave)
|
||||
@ -944,12 +985,16 @@ int action;
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
if (slave->overrun)
|
||||
{
|
||||
CYCLES cycle_start, cycles;
|
||||
slave->stats.n_overrun++;
|
||||
slave->overrun = 0;
|
||||
spinlock_release(&router->lock);
|
||||
slave->cstate &= ~(CS_UPTODATE|CS_DIST);
|
||||
spinlock_release(&slave->catch_lock);
|
||||
cycle_start = rdtsc();
|
||||
blr_slave_catchup(router, slave);
|
||||
cycles = rdtsc() - cycle_start;
|
||||
log_duration(LOGD_SLAVE_CATCHUP2, cycles);
|
||||
spinlock_acquire(&router->lock);
|
||||
slave = router->slaves;
|
||||
if (slave)
|
||||
@ -982,6 +1027,7 @@ int action;
|
||||
*/
|
||||
if (slave->cstate & CS_UPTODATE)
|
||||
{
|
||||
CYCLES cycle_start, cycles;
|
||||
spinlock_release(&router->lock);
|
||||
LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG,
|
||||
"Force slave %d into catchup mode %s@%d\n",
|
||||
@ -990,7 +1036,10 @@ int action;
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
slave->cstate &= ~(CS_UPTODATE|CS_DIST);
|
||||
spinlock_release(&slave->catch_lock);
|
||||
cycle_start = rdtsc();
|
||||
blr_slave_catchup(router, slave);
|
||||
cycles = rdtsc() - cycle_start;
|
||||
log_duration(LOGD_SLAVE_CATCHUP1, cycles);
|
||||
spinlock_acquire(&router->lock);
|
||||
slave = router->slaves;
|
||||
if (slave)
|
||||
@ -1004,6 +1053,7 @@ int action;
|
||||
slave = slave->next;
|
||||
}
|
||||
spinlock_release(&router->lock);
|
||||
log_duration(LOGD_DISTRIBUTE, rdtsc() - entry);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -95,7 +95,7 @@ blr_slave_request(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue)
|
||||
return 0;
|
||||
}
|
||||
|
||||
atomic_add(&slave->stats.n_requests, 1);
|
||||
slave->stats.n_requests++;
|
||||
switch (MYSQL_COMMAND(queue))
|
||||
{
|
||||
case COM_QUERY:
|
||||
@ -796,7 +796,7 @@ doitagain:
|
||||
slave->binlogfile)));
|
||||
return 0;
|
||||
}
|
||||
atomic_add(&slave->stats.n_bursts, 1);
|
||||
slave->stats.n_bursts++;
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
slave->cstate |= CS_INNERLOOP;
|
||||
spinlock_release(&slave->catch_lock);
|
||||
@ -830,7 +830,7 @@ if (hdr.event_size > DEF_HIGH_WATER) slave->stats.n_above++;
|
||||
slave->binlog_pos = hdr.next_pos;
|
||||
}
|
||||
rval = written;
|
||||
atomic_add(&slave->stats.n_events, 1);
|
||||
slave->stats.n_events++;
|
||||
burst++;
|
||||
}
|
||||
if (record == NULL)
|
||||
@ -843,7 +843,7 @@ if (hdr.event_size > DEF_HIGH_WATER) slave->stats.n_above++;
|
||||
} while (record && DCB_BELOW_LOW_WATER(slave->dcb));
|
||||
if (record)
|
||||
{
|
||||
atomic_add(&slave->stats.n_flows, 1);
|
||||
slave->stats.n_flows++;
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
slave->cstate |= CS_EXPECTCB;
|
||||
spinlock_release(&slave->catch_lock);
|
||||
@ -854,7 +854,7 @@ if (hdr.event_size > DEF_HIGH_WATER) slave->stats.n_above++;
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
if ((slave->cstate & CS_UPTODATE) == 0)
|
||||
{
|
||||
atomic_add(&slave->stats.n_upd, 1);
|
||||
slave->stats.n_upd++;
|
||||
slave->cstate |= CS_UPTODATE;
|
||||
state_change = 1;
|
||||
}
|
||||
@ -907,7 +907,7 @@ ROUTER_INSTANCE *router = slave->router;
|
||||
if (slave->state == BLRS_DUMPING &&
|
||||
slave->binlog_pos != router->binlog_position)
|
||||
{
|
||||
atomic_add(&slave->stats.n_dcb, 1);
|
||||
slave->stats.n_dcb++;
|
||||
blr_slave_catchup(router, slave);
|
||||
}
|
||||
}
|
||||
@ -916,12 +916,12 @@ ROUTER_INSTANCE *router = slave->router;
|
||||
{
|
||||
if (slave->state == BLRS_DUMPING)
|
||||
{
|
||||
atomic_add(&slave->stats.n_cb, 1);
|
||||
slave->stats.n_cb++;
|
||||
blr_slave_catchup(router, slave);
|
||||
}
|
||||
else
|
||||
{
|
||||
atomic_add(&slave->stats.n_cbna, 1);
|
||||
slave->stats.n_cbna++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -1957,6 +1957,26 @@ static int routeQuery(
|
||||
|
||||
if (succp) /*< Have DCB of the target backend */
|
||||
{
|
||||
backend_ref_t* bref;
|
||||
sescmd_cursor_t* scur;
|
||||
|
||||
bref = get_bref_from_dcb(router_cli_ses, target_dcb);
|
||||
scur = &bref->bref_sescmd_cur;
|
||||
/**
|
||||
* Store current stmt if execution of previous session command
|
||||
* haven't completed yet. Note that according to MySQL protocol
|
||||
* there can only be one such non-sescmd stmt at the time.
|
||||
*/
|
||||
if (sescmd_cursor_is_active(scur))
|
||||
{
|
||||
ss_dassert(bref->bref_pending_cmd == NULL);
|
||||
bref->bref_pending_cmd = gwbuf_clone(querybuf);
|
||||
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
ret = 1;
|
||||
goto retblock;
|
||||
}
|
||||
|
||||
if ((ret = target_dcb->func.write(target_dcb, gwbuf_clone(querybuf))) == 1)
|
||||
{
|
||||
backend_ref_t* bref;
|
||||
@ -2295,7 +2315,34 @@ static void clientReply (
|
||||
|
||||
ss_dassert(succp);
|
||||
}
|
||||
/** Unlock router session */
|
||||
else if (bref->bref_pending_cmd != NULL) /*< non-sescmd is waiting to be routed */
|
||||
{
|
||||
int ret;
|
||||
|
||||
CHK_GWBUF(bref->bref_pending_cmd);
|
||||
|
||||
if ((ret = bref->bref_dcb->func.write(bref->bref_dcb,
|
||||
gwbuf_clone(bref->bref_pending_cmd))) == 1)
|
||||
{
|
||||
ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance;
|
||||
atomic_add(&inst->stats.n_queries, 1);
|
||||
/**
|
||||
* Add one query response waiter to backend reference
|
||||
*/
|
||||
bref_set_state(bref, BREF_QUERY_ACTIVE);
|
||||
bref_set_state(bref, BREF_WAITING_RESULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Routing query \"%s\" failed.",
|
||||
bref->bref_pending_cmd)));
|
||||
}
|
||||
gwbuf_free(bref->bref_pending_cmd);
|
||||
bref->bref_pending_cmd = NULL;
|
||||
}
|
||||
/** Unlock router session */
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
|
||||
lock_failed:
|
||||
@ -3656,6 +3703,14 @@ static bool route_session_write(
|
||||
{
|
||||
succp = false;
|
||||
}
|
||||
else if (LOG_IS_ENABLED(LOGFILE_TRACE))
|
||||
{
|
||||
LOGIF(LT, (skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"Wrote to %s:%d",
|
||||
backend_ref[i].bref_backend->backend_server->name,
|
||||
backend_ref[i].bref_backend->backend_server->port)));
|
||||
}
|
||||
}
|
||||
}
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
|
||||
Reference in New Issue
Block a user