Merge branch 'develop' into MAX-90

Conflicts:
	server/core/server.c
	server/include/server.h
	server/modules/routing/readconnroute.c
This commit is contained in:
Mark Riddoch
2014-06-27 16:04:39 +01:00
17 changed files with 818 additions and 258 deletions

View File

@ -65,6 +65,7 @@
* or take different actions such as open a new backend connection
* 20/02/2014 Massimiliano Pinto If router_options=slave, route traffic to master if no slaves available
* 06/03/2014 Massimiliano Pinto Server connection counter is now updated in closeSession
* 24/06/2014 Massimiliano Pinto New rules for selecting the Master server
* 27/06/2014 Mark Riddoch Addition of server weighting
*
* @endverbatim
@ -140,6 +141,9 @@ static bool rses_begin_locked_router_action(
static void rses_end_locked_router_action(
ROUTER_CLIENT_SES* rses);
static BACKEND *get_root_master(
BACKEND **servers);
static SPINLOCK instlock;
static ROUTER_INSTANCE *instances;
@ -345,7 +349,7 @@ ROUTER_INSTANCE *inst = (ROUTER_INSTANCE *)instance;
ROUTER_CLIENT_SES *client_rses;
BACKEND *candidate = NULL;
int i;
int master_host = -1;
BACKEND *master_host = NULL;
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
@ -367,6 +371,11 @@ int master_host = -1;
client_rses->rses_chk_tail = CHK_NUM_ROUTER_SES;
#endif
/**
* Find the Master host from available servers
*/
master_host = get_root_master(inst->servers);
/**
* Find a backend server to connect to. This is the extent of the
* load balancing algorithm we need to implement for this simple
@ -402,21 +411,32 @@ int master_host = -1;
if (SERVER_IN_MAINT(inst->servers[i]->server))
continue;
/*
* If router_options=slave, get the running master
* It will be used if there are no running slaves at all
*/
if (inst->bitvalue == SERVER_SLAVE) {
if (master_host < 0 && (SERVER_IS_MASTER(inst->servers[i]->server))) {
master_host = i;
}
}
/* Check server status bits against bitvalue from router_options */
if (inst->servers[i] &&
SERVER_IS_RUNNING(inst->servers[i]->server) &&
(inst->servers[i]->server->status & inst->bitmask) ==
inst->bitvalue)
SERVER_IS_RUNNING(inst->servers[i]->server) &&
(inst->servers[i]->server->status & inst->bitmask & inst->bitvalue))
{
if (master_host) {
if (inst->servers[i] == master_host && (inst->bitvalue & SERVER_SLAVE)) {
/* skip root Master here, as it could also be slave of an external server
* that is not in the configuration.
* Intermediate masters (Relay Servers) are also slave and will be selected
* as Slave(s)
*/
continue;
}
if (inst->servers[i] == master_host && (inst->bitvalue & SERVER_MASTER)) {
/* If option is "master" return only the root Master as there
* could be intermediate masters (Relay Servers)
* and they must not be selected.
*/
candidate = master_host;
break;
}
}
/* If no candidate set, set first running server as
our initial candidate server */
if (candidate == NULL)
@ -453,8 +473,8 @@ int master_host = -1;
* Otherwise, just clean up and return NULL
*/
if (!candidate) {
if (master_host >= 0) {
candidate = inst->servers[master_host];
if (master_host) {
candidate = master_host;
} else {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
@ -855,3 +875,50 @@ static uint8_t getCapabilities(
{
return 0;
}
/********************************
* This routine return the root master server from MySQL replication tree
* Get the root Master rule:
*
* (1) find server(s) with lowest replication depth level
* (2) check for SERVER_MASTER bitvalue in those servers
*
* @param servers The list of servers
* @return The Master found
*
*/
static BACKEND *get_root_master(BACKEND **servers) {
int i = 0;
BACKEND * master_host = NULL;
/* (1) find root server(s) with lowest replication depth level */
for (i = 0; servers[i]; i++) {
if (servers[i] && SERVER_IS_RUNNING(servers[i]->server)) {
if (master_host && servers[i]->server->depth < master_host->server->depth) {
master_host = servers[i];
} else {
if (master_host == NULL) {
master_host = servers[i];
}
}
}
}
/* (2) get the status of server(s) with lowest replication level and check it against SERVER_MASTER bitvalue */
if (master_host) {
int found = 0;
for (i = 0; servers[i]; i++) {
if (servers[i] && SERVER_IS_RUNNING(servers[i]->server) && (servers[i]->server->depth == master_host->server->depth)) {
if (servers[i]->server->status & SERVER_MASTER) {
master_host = servers[i];
found = 1;
}
}
}
if (!found)
master_host = NULL;
}
return master_host;
}

View File

@ -244,6 +244,10 @@ static bool handle_error_new_connection(
GWBUF* errmsg);
static bool handle_error_reply_client(SESSION* ses, GWBUF* errmsg);
static BACKEND *get_root_master(
backend_ref_t *servers,
int router_nservers);
static SPINLOCK instlock;
static ROUTER_INSTANCE* instances;
@ -619,7 +623,8 @@ static void* newSession(
}
/** Copy backend pointers to router session. */
client_rses->rses_master_ref = master_ref;
ss_dassert(SERVER_IS_MASTER(master_ref->bref_backend->backend_server));
/* assert with master_host */
ss_dassert(master_ref && (master_ref->bref_backend->backend_server && SERVER_MASTER));
client_rses->rses_backend_ref = backend_ref;
client_rses->rses_nbackends = router_nservers; /*< # of backend servers */
client_rses->rses_capabilities = RCAP_TYPE_STMT_INPUT;
@ -800,6 +805,7 @@ static bool get_dcb(
int smallest_nconn = -1;
int i;
bool succp = false;
BACKEND *master_host = NULL;
CHK_CLIENT_RSES(rses);
ss_dassert(p_dcb != NULL && *(p_dcb) == NULL);
@ -810,13 +816,18 @@ static bool get_dcb(
}
backend_ref = rses->rses_backend_ref;
/* get root master from availbal servers */
master_host = get_root_master(backend_ref, rses->rses_nbackends);
if (btype == BE_SLAVE)
{
for (i=0; i<rses->rses_nbackends; i++)
{
BACKEND* b = backend_ref[i].bref_backend;
/* check slave bit, also for relay servers (Master & Servers) */
if (BREF_IS_IN_USE((&backend_ref[i])) &&
SERVER_IS_SLAVE(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) &&
(smallest_nconn == -1 ||
b->backend_conn_count < smallest_nconn))
{
@ -835,11 +846,12 @@ static bool get_dcb(
{
*p_dcb = backend_ref->bref_dcb;
succp = true;
ss_dassert(backend_ref->bref_dcb->state != DCB_STATE_ZOMBIE);
ss_dassert(
SERVER_IS_MASTER(backend_ref->bref_backend->backend_server) &&
smallest_nconn == -1);
(master_host && (backend_ref->bref_backend->backend_server == master_host->backend_server)) &&
smallest_nconn == -1);
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
@ -858,8 +870,9 @@ static bool get_dcb(
{
BACKEND* b = backend_ref[i].bref_backend;
/* removed SERVER_IS_MASTER and use master_host */
if (BREF_IS_IN_USE((&backend_ref[i])) &&
(SERVER_IS_MASTER(b->backend_server)))
(master_host && (b->backend_server == master_host->backend_server)))
{
*p_dcb = backend_ref[i].bref_dcb;
succp = true;
@ -1550,6 +1563,7 @@ static bool select_connect_backend_servers(
const int min_nslaves = 0; /*< not configurable at the time */
bool is_synced_master;
int (*p)(const void *, const void *);
BACKEND *master_host = NULL;
if (p_master_ref == NULL || backend_ref == NULL)
{
@ -1557,7 +1571,10 @@ static bool select_connect_backend_servers(
succp = false;
goto return_succp;
}
/* get the root Master */
master_host = get_root_master(backend_ref, router_nservers);
/** Master is already chosen and connected. This is slave failure case */
if (*p_master_ref != NULL &&
BREF_IS_IN_USE((*p_master_ref)))
@ -1571,7 +1588,8 @@ static bool select_connect_backend_servers(
master_found = true;
master_connected = true;
ss_dassert(SERVER_IS_MASTER((*p_master_ref)->bref_backend->backend_server));
/* assert with master_host */
ss_dassert(master_host && ((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) && SERVER_MASTER);
}
/** New session or master failure case */
else
@ -1622,8 +1640,9 @@ static bool select_connect_backend_servers(
b->backend_conn_count)));
}
#endif
/* assert with master_host */
ss_dassert(!master_connected ||
SERVER_IS_MASTER((*p_master_ref)->bref_backend->backend_server));
(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
* a consequence those backends having least connections are in the
@ -1688,13 +1707,15 @@ static bool select_connect_backend_servers(
STRSRVSTATUS(b->backend_server),
b->backend_conn_count,
router->bitmask)));
if (SERVER_IS_RUNNING(b->backend_server) &&
((b->backend_server->status & router->bitmask) ==
router->bitvalue))
{
/* check also for relay servers and don't take the master_host */
if (slaves_found < max_nslaves &&
SERVER_IS_SLAVE(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)))
{
slaves_found += 1;
@ -1752,7 +1773,8 @@ static bool select_connect_backend_servers(
}
}
}
else if (SERVER_IS_MASTER(b->backend_server))
/* take the master_host for master */
else if (master_host && (b->backend_server == master_host->backend_server))
{
*p_master_ref = &backend_ref[i];
@ -1819,8 +1841,9 @@ static bool select_connect_backend_servers(
b->backend_server->port,
b->backend_conn_count)));
}
/* assert with master_host */
ss_dassert(!master_connected ||
SERVER_IS_MASTER((*p_master_ref)->bref_backend->backend_server));
(master_host && ((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) && SERVER_MASTER));
#endif
/**
@ -3175,7 +3198,6 @@ return_rc:
return rc;
}
static sescmd_cursor_t* backend_ref_get_sescmd_cursor (
backend_ref_t* bref)
{
@ -3242,3 +3264,44 @@ static bool prep_stmt_drop(
return true;
}
#endif /*< PREP_STMT_CACHING */
static BACKEND *get_root_master(backend_ref_t *servers, int router_nservers) {
int i = 0;
BACKEND * master_host = NULL;
/* (1) find root server(s) with lowest replication depth level */
for (i = 0; i< router_nservers; i++) {
BACKEND* b = NULL;
b = servers[i].bref_backend;
if (b && SERVER_IS_RUNNING(b->backend_server)) {
if (master_host && b->backend_server->depth < master_host->backend_server->depth) {
master_host = b;
} else {
if (master_host == NULL) {
master_host = b;
}
}
}
}
/* (2) get the status of server(s) with lowest replication level and check it against SERVER_MASTER bitvalue */
if (master_host) {
int found = 0;
for (i = 0; i<router_nservers; i++) {
BACKEND* b = NULL;
b = servers[i].bref_backend;
if (b && SERVER_IS_RUNNING(b->backend_server) && (b->backend_server->depth == master_host->backend_server->depth)) {
if (b->backend_server->status & SERVER_MASTER) {
master_host = b;
found = 1;
}
}
}
if (!found)
master_host = NULL;
}
return master_host;
}