config.h: Added enumerated types MAX_RLAG_AVAILABLE and MAX_RLAG_UNDEFINED to be used instead of magic numbers as max_slave_replication_lag values.

readwritesplit.h: Added TARGET_RLAG_MAX to the list of hint targets. It is used in case of hint max_slave_replication_lag=<value>
readwritesplit.c: get_dcb is called when readwritesplit router chooses target backend for a query. Backend is selected from those the router has connection to. get_dcb now takes additional parameters, name and max_rlag. Name is used if there is a hint route to server <server name>. max_rlag is used for hint max_slave_replication_lag=<value> or if it doesn't exist, then for configure parameter max_slave_replication_lag=<configured value> or if both are absent, ignored.
This commit is contained in:
VilhoRaatikka
2014-08-01 16:33:29 +03:00
parent 4f3d746f4e
commit 65b121889b
3 changed files with 74 additions and 20 deletions

View File

@ -46,6 +46,8 @@ typedef enum {
BOOL_TYPE = 0x08 BOOL_TYPE = 0x08
} config_param_type_t; } config_param_type_t;
enum {MAX_RLAG_NOT_AVAILABLE=-1, MAX_RLAG_UNDEFINED=-2};
#define PARAM_IS_TYPE(p,t) ((p) & (t)) #define PARAM_IS_TYPE(p,t) ((p) & (t))
/** /**

View File

@ -75,13 +75,15 @@ typedef enum {
TARGET_MASTER = 0x01, TARGET_MASTER = 0x01,
TARGET_SLAVE = 0x02, TARGET_SLAVE = 0x02,
TARGET_NAMED_SERVER = 0x04, TARGET_NAMED_SERVER = 0x04,
TARGET_ALL = 0x08 TARGET_ALL = 0x08,
TARGET_RLAG_MAX = 0x10
} route_target_t; } route_target_t;
#define TARGET_IS_MASTER(t) (t & TARGET_MASTER) #define TARGET_IS_MASTER(t) (t & TARGET_MASTER)
#define TARGET_IS_SLAVE(t) (t & TARGET_SLAVE) #define TARGET_IS_SLAVE(t) (t & TARGET_SLAVE)
#define TARGET_IS_NAMED_SERVER(t) (t & TARGET_NAMED_SERVER) #define TARGET_IS_NAMED_SERVER(t) (t & TARGET_NAMED_SERVER)
#define TARGET_IS_ALL(t) (t & TARGET_ALL) #define TARGET_IS_ALL(t) (t & TARGET_ALL)
#define TARGET_IS_RLAG_MAX(t) (t & TARGET_RLAG_MAX)
typedef struct rses_property_st rses_property_t; typedef struct rses_property_st rses_property_t;
typedef struct router_client_session ROUTER_CLIENT_SES; typedef struct router_client_session ROUTER_CLIENT_SES;

View File

@ -160,7 +160,8 @@ static bool get_dcb(
DCB** dcb, DCB** dcb,
ROUTER_CLIENT_SES* rses, ROUTER_CLIENT_SES* rses,
backend_type_t btype, backend_type_t btype,
char* name); char* name,
int max_rlag);
static void rwsplit_process_router_options( static void rwsplit_process_router_options(
ROUTER_INSTANCE* router, ROUTER_INSTANCE* router,
@ -388,7 +389,7 @@ static void refreshInstance(
* used in slave selection. * used in slave selection.
*/ */
if (!rlag_enabled) if (!rlag_enabled)
{ {
if (rlag_limited) if (rlag_limited)
{ {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
@ -934,7 +935,8 @@ static bool get_dcb(
DCB** p_dcb, DCB** p_dcb,
ROUTER_CLIENT_SES* rses, ROUTER_CLIENT_SES* rses,
backend_type_t btype, backend_type_t btype,
char* name) char* name,
int max_rlag)
{ {
backend_ref_t* backend_ref; backend_ref_t* backend_ref;
int smallest_nconn = -1; int smallest_nconn = -1;
@ -951,7 +953,7 @@ static bool get_dcb(
} }
backend_ref = rses->rses_backend_ref; backend_ref = rses->rses_backend_ref;
/* get root master from available servers */ /** get root master from available servers */
master_host = get_root_master(backend_ref, rses->rses_nbackends); master_host = get_root_master(backend_ref, rses->rses_nbackends);
if (btype == BE_SLAVE) if (btype == BE_SLAVE)
@ -975,6 +977,9 @@ static bool get_dcb(
b->backend_server->unique_name, b->backend_server->unique_name,
MIN(strlen(b->backend_server->unique_name), PATH_MAX)) == 0) && MIN(strlen(b->backend_server->unique_name), PATH_MAX)) == 0) &&
master_host != NULL && master_host != NULL &&
(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_SLAVE(b->backend_server) ||
SERVER_IS_RELAY_SERVER(b->backend_server) || SERVER_IS_RELAY_SERVER(b->backend_server) ||
SERVER_IS_MASTER(b->backend_server))) SERVER_IS_MASTER(b->backend_server)))
@ -1004,6 +1009,9 @@ static bool get_dcb(
if (BREF_IS_IN_USE((&backend_ref[i])) && if (BREF_IS_IN_USE((&backend_ref[i])) &&
master_host != NULL && master_host != NULL &&
b->backend_server != master_host->backend_server && b->backend_server != master_host->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_SLAVE(b->backend_server) ||
SERVER_IS_RELAY_SERVER(b->backend_server)) && SERVER_IS_RELAY_SERVER(b->backend_server)) &&
(smallest_nconn == -1 || (smallest_nconn == -1 ||
@ -1100,8 +1108,25 @@ static route_target_t get_route_target (
{ {
/** not implemented */ /** not implemented */
} }
else if (hint->type == HINT_PARAMETER)
{
if (strncasecmp(
(char *)hint->data,
"max_replication_lag",
strlen("max_replication_lag")) == 0)
{
target |= TARGET_RLAG_MAX;
}
else
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Warning : Unknown routing parameter hint : %s",
(char *)hint->data)));
}
}
hint = hint->next; hint = hint->next;
} } /*< while (hint != NULL) */
} }
else else
{ {
@ -1343,6 +1368,7 @@ static int routeQuery(
bool succp = true; bool succp = true;
HINT* hint; HINT* hint;
char* named_server = NULL; char* named_server = NULL;
int rlag_max = MAX_RLAG_UNDEFINED;
if (router_cli_ses->rses_transaction_active) /*< all to master */ if (router_cli_ses->rses_transaction_active) /*< all to master */
{ {
@ -1362,25 +1388,45 @@ static int routeQuery(
if (TARGET_IS_SLAVE(route_target)) if (TARGET_IS_SLAVE(route_target))
{ {
if (TARGET_IS_NAMED_SERVER(route_target)) if (TARGET_IS_NAMED_SERVER(route_target) ||
TARGET_IS_RLAG_MAX(route_target))
{ {
hint = querybuf->hint; hint = querybuf->hint;
while (hint != NULL && while (hint != NULL)
hint->type != HINT_ROUTE_TO_NAMED_SERVER)
{ {
if (hint->type == HINT_ROUTE_TO_NAMED_SERVER)
{
named_server = hint->data;
}
else if (hint->type == HINT_PARAMETER &&
(strncasecmp(
(char *)hint->data,
"max_replication_lag",
strlen("max_replication_lag")) == 0))
{
int val = (int) strtol((char *)hint->data,
(char **)NULL, 10);
if (val != 0 || errno == 0)
{
rlag_max = val;
}
}
hint = hint->next; hint = hint->next;
} }
if (hint != NULL)
{
named_server = hint->data;
}
} }
if (rlag_max == MAX_RLAG_UNDEFINED) /*< no rlag max hint, use config */
{
rlag_max = rses_get_max_replication_lag(router_cli_ses);
}
succp = get_dcb(&target_dcb, succp = get_dcb(&target_dcb,
router_cli_ses, router_cli_ses,
BE_SLAVE, BE_SLAVE,
named_server); named_server,
rlag_max);
} }
else if (TARGET_IS_MASTER(route_target)) else if (TARGET_IS_MASTER(route_target))
{ {
@ -1389,7 +1435,8 @@ static int routeQuery(
succp = get_dcb(&master_dcb, succp = get_dcb(&master_dcb,
router_cli_ses, router_cli_ses,
BE_MASTER, BE_MASTER,
NULL); NULL,
MAX_RLAG_UNDEFINED);
} }
target_dcb = master_dcb; target_dcb = master_dcb;
} }
@ -1964,7 +2011,9 @@ static bool select_connect_backend_servers(
#endif #endif
/* assert with master_host */ /* assert with master_host */
ss_dassert(!master_connected || ss_dassert(!master_connected ||
(master_host && ((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) && SERVER_MASTER)); (master_host &&
((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) &&
SERVER_MASTER));
/** /**
* Sort the pointer list to servers according to connection counts. As * Sort the pointer list to servers according to connection counts. As
* a consequence those backends having least connections are in the * a consequence those backends having least connections are in the
@ -2024,7 +2073,8 @@ static bool select_connect_backend_servers(
} }
} }
} }
} } /*< log only */
/** /**
* Choose at least 1+min_nslaves (master and slave) and at most 1+max_nslaves * Choose at least 1+min_nslaves (master and slave) and at most 1+max_nslaves
* servers from the sorted list. First master found is selected. * servers from the sorted list. First master found is selected.
@ -2041,8 +2091,8 @@ static bool select_connect_backend_servers(
{ {
/* check also for relay servers and don't take the master_host */ /* check also for relay servers and don't take the master_host */
if (slaves_found < max_nslaves && if (slaves_found < max_nslaves &&
(max_slave_rlag == -2 || (max_slave_rlag == MAX_RLAG_UNDEFINED ||
(b->backend_server->rlag != -1 && /*< information currently not available */ (b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
b->backend_server->rlag <= max_slave_rlag)) && b->backend_server->rlag <= max_slave_rlag)) &&
(SERVER_IS_SLAVE(b->backend_server) || SERVER_IS_RELAY_SERVER(b->backend_server)) && (SERVER_IS_SLAVE(b->backend_server) || SERVER_IS_RELAY_SERVER(b->backend_server)) &&
(master_host != NULL && (b->backend_server != master_host->backend_server))) (master_host != NULL && (b->backend_server != master_host->backend_server)))