readwritesplit.c:get_dcb now searches for master if slave is not available
This commit is contained in:
VilhoRaatikka
2014-09-16 12:11:08 +03:00
parent 3dc44ff6fd
commit 7300e58787

View File

@ -268,6 +268,8 @@ static bool handle_error_new_connection(
GWBUF* errmsg); GWBUF* errmsg);
static bool handle_error_reply_client(SESSION* ses, GWBUF* errmsg); static bool handle_error_reply_client(SESSION* ses, GWBUF* errmsg);
static backend_ref_t* get_root_master_bref(ROUTER_CLIENT_SES* rses);
static BACKEND* get_root_master( static BACKEND* get_root_master(
backend_ref_t* servers, backend_ref_t* servers,
int router_nservers); int router_nservers);
@ -1044,6 +1046,7 @@ static bool get_dcb(
int max_rlag) int max_rlag)
{ {
backend_ref_t* backend_ref; backend_ref_t* backend_ref;
backend_ref_t* master_bref;
int smallest_nconn = -1; int smallest_nconn = -1;
int i; int i;
bool succp = false; bool succp = false;
@ -1059,16 +1062,19 @@ 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_bref = get_root_master_bref(rses);
#if defined(SS_DEBUG)
master_host = get_root_master(backend_ref, rses->rses_nbackends); master_host = get_root_master(backend_ref, rses->rses_nbackends);
ss_dassert(master_bref->bref_backend == master_host);
#endif
if (name != NULL) /*< Choose backend by name from a hint */ if (name != NULL) /*< Choose backend by name from a hint */
{ {
ss_dassert(btype != BE_MASTER); /*< Master dominates and no name should be passed with it */ ss_dassert(btype != BE_MASTER); /*< Master dominates and no name should be passed with it */
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: * To become chosen:
* backend must be in use, name must match, * backend must be in use, name must match,
@ -1081,10 +1087,10 @@ static bool get_dcb(
name, name,
b->backend_server->unique_name, b->backend_server->unique_name,
PATH_MAX) == 0) && PATH_MAX) == 0) &&
master_host != NULL && master_bref->bref_backend != NULL &&
(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)))
{ {
*p_dcb = backend_ref[i].bref_dcb; *p_dcb = backend_ref[i].bref_dcb;
succp = true; succp = true;
@ -1113,15 +1119,15 @@ static bool get_dcb(
* at the moment. * at the moment.
*/ */
if (BREF_IS_IN_USE((&backend_ref[i])) && if (BREF_IS_IN_USE((&backend_ref[i])) &&
master_host != NULL && master_bref->bref_backend != NULL &&
b->backend_server != master_host->backend_server && b->backend_server != master_bref->bref_backend->backend_server &&
(max_rlag == MAX_RLAG_UNDEFINED || (max_rlag == MAX_RLAG_UNDEFINED ||
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE && (b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
b->backend_server->rlag <= max_rlag)) && 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 ||
b->backend_conn_count < smallest_nconn)) b->backend_conn_count < smallest_nconn))
{ {
*p_dcb = backend_ref[i].bref_dcb; *p_dcb = backend_ref[i].bref_dcb;
smallest_nconn = b->backend_conn_count; smallest_nconn = b->backend_conn_count;
@ -1132,40 +1138,54 @@ static bool get_dcb(
if (!succp) /*< No valid slave was found, search master next */ if (!succp) /*< No valid slave was found, search master next */
{ {
if (rses->router->available_slaves)
{
rses->router->available_slaves = false;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Warning : No slaves available "
"for the service %s.",
rses->router->service->name)));
}
btype = BE_MASTER; btype = BE_MASTER;
if (BREF_IS_IN_USE(backend_ref))
if (BREF_IS_IN_USE(master_bref))
{ {
*p_dcb = backend_ref->bref_dcb; *p_dcb = master_bref->bref_dcb;
succp = true; succp = true;
ss_dassert(backend_ref->bref_dcb->state != DCB_STATE_ZOMBIE); ss_dassert(master_bref->bref_dcb->state != DCB_STATE_ZOMBIE);
ss_dassert( ss_dassert(
(master_host && (backend_ref->bref_backend->backend_server == master_host->backend_server)) && (master_bref->bref_backend &&
(master_bref->bref_backend->backend_server ==
master_bref->bref_backend->backend_server)) &&
smallest_nconn == -1); smallest_nconn == -1);
if (rses->router->available_slaves) LOGIF(LE, (skygw_log_write_flush(
{ LOGFILE_ERROR,
rses->router->available_slaves = false; "Using master %s:%d instead.",
LOGIF(LE, (skygw_log_write_flush( master_bref->bref_backend->backend_server->name,
LOGFILE_ERROR, master_bref->bref_backend->backend_server->port)));
"Warning : No slaves available "
"for the service %s. "
"Using master %s:%d "
"instead.",
rses->router->service->name,
backend_ref->bref_backend->backend_server->name,
backend_ref->bref_backend->backend_server->port)));
}
} }
else
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : No master is availabe either. "
"Unable to find backend server for "
"routing.")));
}
} }
else if (rses->router->available_slaves == false) else if (rses->router->available_slaves == false)
{ {
rses->router->available_slaves = true; rses->router->available_slaves = true;
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR, LOGFILE_ERROR,
"At least one slave has become avilable for " "At least one slave has become available for "
"the service %s.", "the service %s.",
rses->router->service->name))); rses->router->service->name)));
} }
@ -1179,7 +1199,9 @@ static bool get_dcb(
BACKEND* b = backend_ref[i].bref_backend; BACKEND* b = backend_ref[i].bref_backend;
if (BREF_IS_IN_USE((&backend_ref[i])) && if (BREF_IS_IN_USE((&backend_ref[i])) &&
(master_host && (b->backend_server == master_host->backend_server))) (master_bref->bref_backend &&
(b->backend_server ==
master_bref->bref_backend->backend_server)))
{ {
*p_dcb = backend_ref[i].bref_dcb; *p_dcb = backend_ref[i].bref_dcb;
succp = true; succp = true;
@ -2430,7 +2452,7 @@ static bool select_connect_backend_servers(
const int min_nslaves = 0; /*< not configurable at the time */ const int min_nslaves = 0; /*< not configurable at the time */
bool is_synced_master; bool is_synced_master;
int (*p)(const void *, const void *); int (*p)(const void *, const void *);
BACKEND *master_host = NULL; BACKEND* master_host = NULL;
if (p_master_ref == NULL || backend_ref == NULL) if (p_master_ref == NULL || backend_ref == NULL)
{ {
@ -4305,22 +4327,82 @@ static bool prep_stmt_drop(
* @return The Master found * @return The Master found
* *
*/ */
static BACKEND *get_root_master(backend_ref_t *servers, int router_nservers) { static BACKEND *get_root_master(
backend_ref_t *servers,
int router_nservers)
{
int i = 0; int i = 0;
BACKEND * master_host = NULL; BACKEND * master_host = NULL;
for (i = 0; i< router_nservers; i++) { for (i = 0; i< router_nservers; i++)
BACKEND* b = NULL; {
b = servers[i].bref_backend; BACKEND* b;
if (b && (b->backend_server->status & (SERVER_MASTER|SERVER_MAINT)) == SERVER_MASTER) {
if (master_host && b->backend_server->depth < master_host->backend_server->depth) { if (servers[i].bref_backend == NULL)
master_host = b; {
} else { continue;
if (master_host == NULL) { }
master_host = b;
} b = servers[i].bref_backend;
if ((b->backend_server->status &
(SERVER_MASTER|SERVER_MAINT)) == SERVER_MASTER)
{
if (master_host == NULL ||
(b->backend_server->depth < master_host->backend_server->depth))
{
master_host = b;
} }
} }
} }
return master_host; return master_host;
} }
/********************************
* This routine returns the root master server from MySQL replication tree
* Get the root Master rule:
*
* find server with the lowest replication depth level
* and the SERVER_MASTER bitval
* Servers are checked even if they are in 'maintenance'
*
* @param rses pointer to router session
* @return pointer to backend reference of the root master
*
*/
static backend_ref_t* get_root_master_bref(
ROUTER_CLIENT_SES* rses)
{
backend_ref_t* bref;
backend_ref_t* candidate_bref = NULL;
int i = 0;
bref = rses->rses_backend_ref;
while (i<rses->rses_nbackends)
{
if (SERVER_IS_MASTER(bref->bref_backend->backend_server))
{
if (candidate_bref == NULL ||
(bref->bref_backend->backend_server->depth <
candidate_bref->bref_backend->backend_server->depth))
{
candidate_bref = bref;
}
}
bref++;
i += 1;
}
return candidate_bref;
}