Made RWSplit to use slave selection criteria also during client session. Previously the criteria was use when slaves were selected for use of client session.
This commit is contained in:
@ -57,11 +57,11 @@ typedef enum bref_state {
|
|||||||
BREF_CLOSED = 0x08
|
BREF_CLOSED = 0x08
|
||||||
} bref_state_t;
|
} bref_state_t;
|
||||||
|
|
||||||
#define BREF_IS_NOT_USED(s) (s->bref_state & ~BREF_IN_USE)
|
#define BREF_IS_NOT_USED(s) ((s)->bref_state & ~BREF_IN_USE)
|
||||||
#define BREF_IS_IN_USE(s) (s->bref_state & BREF_IN_USE)
|
#define BREF_IS_IN_USE(s) ((s)->bref_state & BREF_IN_USE)
|
||||||
#define BREF_IS_WAITING_RESULT(s) (s->bref_num_result_wait > 0)
|
#define BREF_IS_WAITING_RESULT(s) ((s)->bref_num_result_wait > 0)
|
||||||
#define BREF_IS_QUERY_ACTIVE(s) (s->bref_state & BREF_QUERY_ACTIVE)
|
#define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE)
|
||||||
#define BREF_IS_CLOSED(s) (s->bref_state & BREF_CLOSED)
|
#define BREF_IS_CLOSED(s) ((s)->bref_state & BREF_CLOSED)
|
||||||
|
|
||||||
typedef enum backend_type_t {
|
typedef enum backend_type_t {
|
||||||
BE_UNDEFINED=-1,
|
BE_UNDEFINED=-1,
|
||||||
|
@ -1867,14 +1867,13 @@ void protocol_add_srv_command(
|
|||||||
/** add to the end of list */
|
/** add to the end of list */
|
||||||
p->protocol_command.scom_next = server_command_init(NULL, cmd);
|
p->protocol_command.scom_next = server_command_init(NULL, cmd);
|
||||||
}
|
}
|
||||||
|
#if defined(EXTRA_SS_DEBUG)
|
||||||
LOGIF(LT, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_TRACE,
|
LOGFILE_TRACE,
|
||||||
"Added command %s to fd %d.",
|
"Added command %s to fd %d.",
|
||||||
STRPACKETTYPE(cmd),
|
STRPACKETTYPE(cmd),
|
||||||
p->owner_dcb->fd)));
|
p->owner_dcb->fd)));
|
||||||
|
|
||||||
#if defined(EXTRA_SS_DEBUG)
|
|
||||||
c = &p->protocol_command;
|
c = &p->protocol_command;
|
||||||
|
|
||||||
while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED)
|
while (c != NULL && c->scom_cmd != MYSQL_COM_UNDEFINED)
|
||||||
@ -1905,13 +1904,13 @@ void protocol_remove_srv_command(
|
|||||||
server_command_t* s;
|
server_command_t* s;
|
||||||
spinlock_acquire(&p->protocol_lock);
|
spinlock_acquire(&p->protocol_lock);
|
||||||
s = &p->protocol_command;
|
s = &p->protocol_command;
|
||||||
|
#if defined(EXTRA_SS_DEBUG)
|
||||||
LOGIF(LT, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_TRACE,
|
LOGFILE_TRACE,
|
||||||
"Removed command %s from fd %d.",
|
"Removed command %s from fd %d.",
|
||||||
STRPACKETTYPE(s->scom_cmd),
|
STRPACKETTYPE(s->scom_cmd),
|
||||||
p->owner_dcb->fd)));
|
p->owner_dcb->fd)));
|
||||||
|
#endif
|
||||||
if (s->scom_next == NULL)
|
if (s->scom_next == NULL)
|
||||||
{
|
{
|
||||||
p->protocol_command.scom_cmd = MYSQL_COM_UNDEFINED;
|
p->protocol_command.scom_cmd = MYSQL_COM_UNDEFINED;
|
||||||
|
@ -105,6 +105,12 @@ static route_target_t get_route_target (
|
|||||||
target_t use_sql_variables_in,
|
target_t use_sql_variables_in,
|
||||||
HINT* hint);
|
HINT* hint);
|
||||||
|
|
||||||
|
static backend_ref_t* check_candidate_bref(
|
||||||
|
backend_ref_t* candidate_bref,
|
||||||
|
backend_ref_t* new_bref,
|
||||||
|
select_criteria_t sc);
|
||||||
|
|
||||||
|
|
||||||
static uint8_t getCapabilities (ROUTER* inst, void* router_session);
|
static uint8_t getCapabilities (ROUTER* inst, void* router_session);
|
||||||
|
|
||||||
#if defined(NOT_USED)
|
#if defined(NOT_USED)
|
||||||
@ -1046,10 +1052,10 @@ static void freeSession(
|
|||||||
/**
|
/**
|
||||||
* Provide the router with a pointer to a suitable backend dcb.
|
* Provide the router with a pointer to a suitable backend dcb.
|
||||||
*
|
*
|
||||||
* As of Nov. 2014, slave which has least connections is always chosen.
|
|
||||||
*
|
|
||||||
* Detect failures in server statuses and reselect backends if necessary.
|
* Detect failures in server statuses and reselect backends if necessary.
|
||||||
* If name is specified, server name becomes primary selection criteria.
|
* If name is specified, server name becomes primary selection criteria.
|
||||||
|
* Similarly, if max replication lag is specified, skip backends which lag too
|
||||||
|
* much.
|
||||||
*
|
*
|
||||||
* @param p_dcb Address of the pointer to the resulting DCB
|
* @param p_dcb Address of the pointer to the resulting DCB
|
||||||
* @param rses Pointer to router client session
|
* @param rses Pointer to router client session
|
||||||
@ -1092,6 +1098,7 @@ static bool get_dcb(
|
|||||||
goto return_succp;
|
goto return_succp;
|
||||||
}
|
}
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
|
/** master_host is just for additional checking */
|
||||||
master_host = get_root_master(backend_ref, rses->rses_nbackends);
|
master_host = get_root_master(backend_ref, rses->rses_nbackends);
|
||||||
if (master_bref->bref_backend != master_host)
|
if (master_bref->bref_backend != master_host)
|
||||||
{
|
{
|
||||||
@ -1133,71 +1140,107 @@ static bool get_dcb(
|
|||||||
{
|
{
|
||||||
goto return_succp;
|
goto return_succp;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
btype = BE_SLAVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btype == BE_SLAVE)
|
if (btype == BE_SLAVE)
|
||||||
{
|
{
|
||||||
|
backend_ref_t* candidate_bref = NULL;
|
||||||
|
|
||||||
for (i=0; i<rses->rses_nbackends; i++)
|
for (i=0; i<rses->rses_nbackends; i++)
|
||||||
{
|
{
|
||||||
BACKEND* b = backend_ref[i].bref_backend;
|
BACKEND* b = (&backend_ref[i])->bref_backend;
|
||||||
/**
|
/**
|
||||||
* To become chosen:
|
* Unused backend or backend which is not master nor
|
||||||
* backend must be in use,
|
* slave can't be used
|
||||||
* root master node must be found,
|
*/
|
||||||
* backend is not allowed to be the master,
|
if (!BREF_IS_IN_USE(&backend_ref[i]) ||
|
||||||
* backend's role can be either slave or relay
|
(!SERVER_IS_MASTER(b->backend_server) &&
|
||||||
* server and it must have least connections
|
!SERVER_IS_SLAVE(b->backend_server)))
|
||||||
* at the moment.
|
|
||||||
*/
|
|
||||||
if (BREF_IS_IN_USE((&backend_ref[i])) &&
|
|
||||||
master_bref->bref_backend != NULL &&
|
|
||||||
b->backend_server != master_bref->bref_backend->backend_server &&
|
|
||||||
(max_rlag == MAX_RLAG_UNDEFINED ||
|
|
||||||
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
|
||||||
b->backend_server->rlag <= max_rlag)) &&
|
|
||||||
(SERVER_IS_SLAVE(b->backend_server) ||
|
|
||||||
SERVER_IS_RELAY_SERVER(b->backend_server)) &&
|
|
||||||
(smallest_nconn == -1 ||
|
|
||||||
b->backend_conn_count < smallest_nconn))
|
|
||||||
{
|
{
|
||||||
*p_dcb = backend_ref[i].bref_dcb;
|
continue;
|
||||||
smallest_nconn = b->backend_conn_count;
|
|
||||||
succp = true;
|
|
||||||
ss_dassert(backend_ref[i].bref_dcb->state != DCB_STATE_ZOMBIE);
|
|
||||||
}
|
}
|
||||||
}
|
/**
|
||||||
|
* If there are no candidates yet accept both master or
|
||||||
if (!succp) /*< No valid slave was found, search master next */
|
* slave. If candidate is master, any slave replaces it.
|
||||||
{
|
*/
|
||||||
if (rses->router->available_slaves)
|
else if (candidate_bref == NULL ||
|
||||||
|
(SERVER_IS_MASTER(candidate_bref->bref_backend->backend_server) &&
|
||||||
|
SERVER_IS_SLAVE(b->backend_server)))
|
||||||
{
|
{
|
||||||
rses->router->available_slaves = false;
|
/**
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
* Ensure that master has not changed dunring
|
||||||
LOGFILE_ERROR,
|
* session and abort if it has.
|
||||||
"Warning : No slaves available "
|
*/
|
||||||
"for the service %s.",
|
if (SERVER_IS_MASTER(b->backend_server))
|
||||||
rses->router->service->name)));
|
{
|
||||||
}
|
if (candidate_bref != master_bref)
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
{
|
||||||
LOGFILE_ERROR,
|
/** Log master failure */
|
||||||
"Warning : Using master %s:%d.",
|
succp = false;
|
||||||
master_bref->bref_backend->backend_server->name,
|
break;
|
||||||
master_bref->bref_backend->backend_server->port)));
|
}
|
||||||
btype = BE_MASTER;
|
else
|
||||||
}
|
{
|
||||||
/** Found slave, correct the status flag */
|
/** found master */
|
||||||
else if (rses->router->available_slaves == false)
|
candidate_bref = &backend_ref[i];
|
||||||
|
succp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Ensure that max replication lag is not set
|
||||||
|
* or that candidate's lag doesn't exceed the
|
||||||
|
* maximum allowed replication lag.
|
||||||
|
*/
|
||||||
|
else if (max_rlag == MAX_RLAG_UNDEFINED ||
|
||||||
|
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
||||||
|
b->backend_server->rlag <= max_rlag))
|
||||||
|
{
|
||||||
|
/** found slave */
|
||||||
|
candidate_bref = &backend_ref[i];
|
||||||
|
succp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* When candidate exists, compare it against the current
|
||||||
|
* backend and update assign it to new candidate if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
else if (max_rlag == MAX_RLAG_UNDEFINED ||
|
||||||
|
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
||||||
|
b->backend_server->rlag <= max_rlag))
|
||||||
|
{
|
||||||
|
candidate_bref = check_candidate_bref(
|
||||||
|
candidate_bref,
|
||||||
|
&backend_ref[i],
|
||||||
|
rses->rses_config.rw_slave_select_criteria);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGIF(LT, (skygw_log_write(
|
||||||
|
LOGFILE_TRACE,
|
||||||
|
"Server %s:%d is too much behind the "
|
||||||
|
"master, %d s. and can't be chosen.",
|
||||||
|
b->backend_server->name,
|
||||||
|
b->backend_server->port,
|
||||||
|
b->backend_server->rlag)));
|
||||||
|
}
|
||||||
|
} /*< for */
|
||||||
|
/** Assign selected DCB's pointer value */
|
||||||
|
if (candidate_bref != NULL)
|
||||||
{
|
{
|
||||||
rses->router->available_slaves = true;
|
*p_dcb = candidate_bref->bref_dcb;
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"At least one slave has become available for "
|
|
||||||
"the service %s.",
|
|
||||||
rses->router->service->name)));
|
|
||||||
goto return_succp;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
goto return_succp;
|
||||||
|
} /*< if (btype == BE_SLAVE) */
|
||||||
|
/**
|
||||||
|
* If target was originally master only then the execution jumps
|
||||||
|
* directly here.
|
||||||
|
*/
|
||||||
if (btype == BE_MASTER)
|
if (btype == BE_MASTER)
|
||||||
{
|
{
|
||||||
if (BREF_IS_IN_USE(master_bref) &&
|
if (BREF_IS_IN_USE(master_bref) &&
|
||||||
@ -1225,6 +1268,43 @@ return_succp:
|
|||||||
return succp;
|
return succp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find out which of the two backend servers has smaller value for select
|
||||||
|
* criteria property.
|
||||||
|
*
|
||||||
|
* @param cand previously selected candidate
|
||||||
|
* @param new challenger
|
||||||
|
* @param sc select criteria
|
||||||
|
*
|
||||||
|
* @return pointer to backend reference of that backend server which has smaller
|
||||||
|
* value in selection criteria. If either reference pointer is NULL then the
|
||||||
|
* other reference pointer value is returned.
|
||||||
|
*/
|
||||||
|
static backend_ref_t* check_candidate_bref(
|
||||||
|
backend_ref_t* cand,
|
||||||
|
backend_ref_t* new,
|
||||||
|
select_criteria_t sc)
|
||||||
|
{
|
||||||
|
int (*p)(const void *, const void *);
|
||||||
|
/** get compare function */
|
||||||
|
p = criteria_cmpfun[sc];
|
||||||
|
|
||||||
|
if (new == NULL)
|
||||||
|
{
|
||||||
|
return cand;
|
||||||
|
}
|
||||||
|
else if (cand == NULL || (p((void *)cand,(void *)new) > 0))
|
||||||
|
{
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Examine the query type, transaction state and routing hints. Find out the
|
* Examine the query type, transaction state and routing hints. Find out the
|
||||||
* target for query routing.
|
* target for query routing.
|
||||||
@ -1264,6 +1344,7 @@ static route_target_t get_route_target (
|
|||||||
*/
|
*/
|
||||||
else if (!trx_active &&
|
else if (!trx_active &&
|
||||||
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) || /*< any SELECT */
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) || /*< any SELECT */
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) || /*< 'SHOW TABLES' */
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ)|| /*< read user var */
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ)|| /*< read user var */
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) || /*< read sys var */
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) || /*< read sys var */
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) || /*< prepared stmt exec */
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) || /*< prepared stmt exec */
|
||||||
@ -1271,6 +1352,7 @@ static route_target_t get_route_target (
|
|||||||
{
|
{
|
||||||
/** First set expected targets before evaluating hints */
|
/** First set expected targets before evaluating hints */
|
||||||
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
|
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SHOW_TABLES) || /*< 'SHOW TABLES' */
|
||||||
/** Configured to allow reading variables from slaves */
|
/** Configured to allow reading variables from slaves */
|
||||||
(use_sql_variables_in == TYPE_ALL &&
|
(use_sql_variables_in == TYPE_ALL &&
|
||||||
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
|
||||||
@ -2021,9 +2103,8 @@ static int routeQuery(
|
|||||||
rlag_max)));
|
rlag_max)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TARGET_IS_SLAVE(route_target))
|
||||||
if (!succp && TARGET_IS_SLAVE(route_target))
|
|
||||||
{
|
{
|
||||||
btype = BE_SLAVE;
|
btype = BE_SLAVE;
|
||||||
|
|
||||||
@ -2040,8 +2121,8 @@ static int routeQuery(
|
|||||||
NULL,
|
NULL,
|
||||||
rlag_max);
|
rlag_max);
|
||||||
if (succp)
|
if (succp)
|
||||||
{
|
{
|
||||||
atomic_add(&inst->stats.n_slave, 1);
|
atomic_add(&inst->stats.n_slave, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2051,8 +2132,7 @@ static int routeQuery(
|
|||||||
"failed.")));
|
"failed.")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TARGET_IS_MASTER(route_target))
|
||||||
if (!succp && TARGET_IS_MASTER(route_target))
|
|
||||||
{
|
{
|
||||||
DCB* curr_master_dcb = NULL;
|
DCB* curr_master_dcb = NULL;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user