Added createInstance and newSession, cleaned up things related to other routers.
This commit is contained in:
@ -878,7 +878,7 @@ static int gw_error_backend_event(DCB *dcb)
|
|||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Backend error event handling.")));
|
"Backend error event handling.")));
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <router.h>
|
#include <router.h>
|
||||||
#include <readwritesplit.h>
|
#include <dbshard.h>
|
||||||
|
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
@ -96,8 +96,6 @@ static void handleError(
|
|||||||
|
|
||||||
static void print_error_packet(ROUTER_CLIENT_SES* rses, GWBUF* buf, DCB* dcb);
|
static void print_error_packet(ROUTER_CLIENT_SES* rses, GWBUF* buf, DCB* dcb);
|
||||||
static int router_get_servercount(ROUTER_INSTANCE* router);
|
static int router_get_servercount(ROUTER_INSTANCE* router);
|
||||||
static int rses_get_max_slavecount(ROUTER_CLIENT_SES* rses, int router_nservers);
|
|
||||||
static int rses_get_max_replication_lag(ROUTER_CLIENT_SES* rses);
|
|
||||||
static backend_ref_t* get_bref_from_dcb(ROUTER_CLIENT_SES* rses, DCB* dcb);
|
static backend_ref_t* get_bref_from_dcb(ROUTER_CLIENT_SES* rses, DCB* dcb);
|
||||||
|
|
||||||
static route_target_t get_route_target (
|
static route_target_t get_route_target (
|
||||||
@ -142,26 +140,9 @@ int bref_cmp_current_load(
|
|||||||
const void* bref1,
|
const void* bref1,
|
||||||
const void* bref2);
|
const void* bref2);
|
||||||
|
|
||||||
/**
|
|
||||||
* The order of functions _must_ match with the order the select criteria are
|
|
||||||
* listed in select_criteria_t definition in readwritesplit.h
|
|
||||||
*/
|
|
||||||
int (*criteria_cmpfun[LAST_CRITERIA])(const void*, const void*)=
|
|
||||||
{
|
|
||||||
NULL,
|
|
||||||
bref_cmp_global_conn,
|
|
||||||
bref_cmp_router_conn,
|
|
||||||
bref_cmp_behind_master,
|
|
||||||
bref_cmp_current_load
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool select_connect_backend_servers(
|
static bool select_connect_backend_servers(
|
||||||
backend_ref_t** p_master_ref,
|
|
||||||
backend_ref_t* backend_ref,
|
backend_ref_t* backend_ref,
|
||||||
int router_nservers,
|
int router_nservers,
|
||||||
int max_nslaves,
|
|
||||||
int max_rlag,
|
|
||||||
select_criteria_t select_criteria,
|
|
||||||
SESSION* session,
|
SESSION* session,
|
||||||
ROUTER_INSTANCE* router);
|
ROUTER_INSTANCE* router);
|
||||||
|
|
||||||
@ -177,7 +158,6 @@ static void rwsplit_process_router_options(
|
|||||||
char** options);
|
char** options);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static ROUTER_OBJECT MyObject = {
|
static ROUTER_OBJECT MyObject = {
|
||||||
createInstance,
|
createInstance,
|
||||||
newSession,
|
newSession,
|
||||||
@ -286,11 +266,6 @@ static BACKEND* get_root_master(
|
|||||||
backend_ref_t* servers,
|
backend_ref_t* servers,
|
||||||
int router_nservers);
|
int router_nservers);
|
||||||
|
|
||||||
static bool have_enough_servers(
|
|
||||||
ROUTER_CLIENT_SES** rses,
|
|
||||||
const int nsrv,
|
|
||||||
int router_nsrv,
|
|
||||||
ROUTER_INSTANCE* router);
|
|
||||||
|
|
||||||
static SPINLOCK instlock;
|
static SPINLOCK instlock;
|
||||||
static ROUTER_INSTANCE* instances;
|
static ROUTER_INSTANCE* instances;
|
||||||
@ -598,7 +573,7 @@ createInstance(SERVICE *service, char **options)
|
|||||||
* Read config version number from service to inform what configuration
|
* Read config version number from service to inform what configuration
|
||||||
* is used if any.
|
* is used if any.
|
||||||
*/
|
*/
|
||||||
router->rwsplit_version = service->svc_config_version;
|
router->dbshard_version = service->svc_config_version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get hashtable which includes dbname,backend pairs
|
* Get hashtable which includes dbname,backend pairs
|
||||||
@ -632,13 +607,10 @@ static void* newSession(
|
|||||||
SESSION* session)
|
SESSION* session)
|
||||||
{
|
{
|
||||||
backend_ref_t* backend_ref; /*< array of backend references (DCB,BACKEND,cursor) */
|
backend_ref_t* backend_ref; /*< array of backend references (DCB,BACKEND,cursor) */
|
||||||
backend_ref_t* master_ref = NULL; /*< pointer to selected master */
|
|
||||||
ROUTER_CLIENT_SES* client_rses = NULL;
|
ROUTER_CLIENT_SES* client_rses = NULL;
|
||||||
ROUTER_INSTANCE* router = (ROUTER_INSTANCE *)router_inst;
|
ROUTER_INSTANCE* router = (ROUTER_INSTANCE *)router_inst;
|
||||||
bool succp;
|
bool succp;
|
||||||
int router_nservers = 0; /*< # of servers in total */
|
int router_nservers = 0; /*< # of servers in total */
|
||||||
int max_nslaves; /*< max # of slaves used in this session */
|
|
||||||
int max_slave_rlag; /*< max allowed replication lag for any slave */
|
|
||||||
int i;
|
int i;
|
||||||
const int min_nservers = 1; /*< hard-coded for now */
|
const int min_nservers = 1; /*< hard-coded for now */
|
||||||
|
|
||||||
@ -661,27 +633,35 @@ static void* newSession(
|
|||||||
*/
|
*/
|
||||||
spinlock_acquire(&router->lock);
|
spinlock_acquire(&router->lock);
|
||||||
|
|
||||||
if (router->service->svc_config_version > router->rwsplit_version)
|
/**
|
||||||
|
* ??? tarvitaanko
|
||||||
|
*/
|
||||||
|
if (router->service->svc_config_version > router->dbshard_version)
|
||||||
{
|
{
|
||||||
/** re-read all parameters to rwsplit config structure */
|
/** re-read all parameters to rwsplit config structure */
|
||||||
refreshInstance(router, NULL); /*< scan through all parameters */
|
refreshInstance(router, NULL); /*< scan through all parameters */
|
||||||
/** increment rwsplit router's config version number */
|
/** increment rwsplit router's config version number */
|
||||||
router->rwsplit_version = router->service->svc_config_version;
|
router->dbshard_version = router->service->svc_config_version;
|
||||||
/** Read options */
|
/** Read options */
|
||||||
rwsplit_process_router_options(router, router->service->routerOptions);
|
dbshard_process_router_options(router, router->service->routerOptions);
|
||||||
}
|
}
|
||||||
/** Copy config struct from router instance */
|
/** Copy config struct from router instance */
|
||||||
client_rses->rses_config = router->rwsplit_config;
|
client_rses->rses_config = router->dbshard_config;
|
||||||
|
|
||||||
spinlock_release(&router->lock);
|
spinlock_release(&router->lock);
|
||||||
/**
|
/**
|
||||||
* Set defaults to session variables.
|
* Set defaults to session variables.
|
||||||
|
* ??? tarvitaanko
|
||||||
*/
|
*/
|
||||||
client_rses->rses_autocommit_enabled = true;
|
client_rses->rses_autocommit_enabled = true;
|
||||||
client_rses->rses_transaction_active = false;
|
client_rses->rses_transaction_active = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instead of calling this, ensure that there is at least one
|
||||||
|
* responding server.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
router_nservers = router_get_servercount(router);
|
router_nservers = router_get_servercount(router);
|
||||||
|
|
||||||
if (!have_enough_servers(&client_rses,
|
if (!have_enough_servers(&client_rses,
|
||||||
min_nservers,
|
min_nservers,
|
||||||
router_nservers,
|
router_nservers,
|
||||||
@ -689,6 +669,7 @@ static void* newSession(
|
|||||||
{
|
{
|
||||||
goto return_rses;
|
goto return_rses;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* Create backend reference objects for this session.
|
* Create backend reference objects for this session.
|
||||||
*/
|
*/
|
||||||
@ -723,8 +704,6 @@ static void* newSession(
|
|||||||
&client_rses->rses_properties[RSES_PROP_TYPE_SESCMD];
|
&client_rses->rses_properties[RSES_PROP_TYPE_SESCMD];
|
||||||
backend_ref[i].bref_sescmd_cur.scmd_cur_cmd = NULL;
|
backend_ref[i].bref_sescmd_cur.scmd_cur_cmd = NULL;
|
||||||
}
|
}
|
||||||
max_nslaves = rses_get_max_slavecount(client_rses, router_nservers);
|
|
||||||
max_slave_rlag = rses_get_max_replication_lag(client_rses);
|
|
||||||
|
|
||||||
spinlock_init(&client_rses->rses_lock);
|
spinlock_init(&client_rses->rses_lock);
|
||||||
client_rses->rses_backend_ref = backend_ref;
|
client_rses->rses_backend_ref = backend_ref;
|
||||||
@ -733,7 +712,6 @@ static void* newSession(
|
|||||||
* Find a backend servers to connect to.
|
* Find a backend servers to connect to.
|
||||||
* This command requires that rsession's lock is held.
|
* This command requires that rsession's lock is held.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
succp = rses_begin_locked_router_action(client_rses);
|
succp = rses_begin_locked_router_action(client_rses);
|
||||||
|
|
||||||
if(!succp)
|
if(!succp)
|
||||||
@ -743,14 +721,10 @@ static void* newSession(
|
|||||||
client_rses = NULL;
|
client_rses = NULL;
|
||||||
goto return_rses;
|
goto return_rses;
|
||||||
}
|
}
|
||||||
succp = select_connect_backend_servers(&master_ref,
|
succp = connect_backend_servers(backend_ref,
|
||||||
backend_ref,
|
router_nservers,
|
||||||
router_nservers,
|
session,
|
||||||
max_nslaves,
|
router);
|
||||||
max_slave_rlag,
|
|
||||||
client_rses->rses_config.rw_slave_select_criteria,
|
|
||||||
session,
|
|
||||||
router);
|
|
||||||
|
|
||||||
rses_end_locked_router_action(client_rses);
|
rses_end_locked_router_action(client_rses);
|
||||||
|
|
||||||
@ -764,9 +738,6 @@ static void* newSession(
|
|||||||
goto return_rses;
|
goto return_rses;
|
||||||
}
|
}
|
||||||
/** Copy backend pointers to router session. */
|
/** Copy backend pointers to router session. */
|
||||||
client_rses->rses_master_ref = master_ref;
|
|
||||||
/* assert with master_host */
|
|
||||||
ss_dassert(master_ref && (master_ref->bref_backend->backend_server && SERVER_MASTER));
|
|
||||||
client_rses->rses_capabilities = RCAP_TYPE_STMT_INPUT;
|
client_rses->rses_capabilities = RCAP_TYPE_STMT_INPUT;
|
||||||
client_rses->rses_backend_ref = backend_ref;
|
client_rses->rses_backend_ref = backend_ref;
|
||||||
client_rses->rses_nbackends = router_nservers; /*< # of backend servers */
|
client_rses->rses_nbackends = router_nservers; /*< # of backend servers */
|
||||||
@ -2599,13 +2570,9 @@ static void bref_set_state(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @node Search suitable backend servers from those of router instance.
|
* @node Search all RUNNING backend servers and connect
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* @param p_master_ref - in, use, out
|
|
||||||
* Pointer to location where master's backend reference is to be stored.
|
|
||||||
* NULL is not allowed.
|
|
||||||
*
|
|
||||||
* @param backend_ref - in, use, out
|
* @param backend_ref - in, use, out
|
||||||
* Pointer to backend server reference object array.
|
* Pointer to backend server reference object array.
|
||||||
* NULL is not allowed.
|
* NULL is not allowed.
|
||||||
@ -2628,80 +2595,22 @@ static void bref_set_state(
|
|||||||
* @return true, if at least one master and one slave was found.
|
* @return true, if at least one master and one slave was found.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @details It is assumed that there is only one master among servers of
|
* @details It is assumed that there is only one available server.
|
||||||
* a router instance. As a result, the first master found is chosen.
|
* There will be exactly as many backend references than there are
|
||||||
* There will possibly be more backend references than connected backends
|
* connections because all servers are supposed to be operational. It is,
|
||||||
* because only those in correct state are connected to.
|
* however, possible that there are less available servers than expected.
|
||||||
*/
|
*/
|
||||||
static bool select_connect_backend_servers(
|
static bool connect_backend_servers(
|
||||||
backend_ref_t** p_master_ref,
|
|
||||||
backend_ref_t* backend_ref,
|
backend_ref_t* backend_ref,
|
||||||
int router_nservers,
|
int router_nservers,
|
||||||
int max_nslaves,
|
|
||||||
int max_slave_rlag,
|
|
||||||
select_criteria_t select_criteria,
|
|
||||||
SESSION* session,
|
SESSION* session,
|
||||||
ROUTER_INSTANCE* router)
|
ROUTER_INSTANCE* router)
|
||||||
{
|
{
|
||||||
bool succp = true;
|
bool succp = true;
|
||||||
bool master_found;
|
int servers_found = 0;
|
||||||
bool master_connected;
|
int servers_connected = 0;
|
||||||
int slaves_found = 0;
|
|
||||||
int slaves_connected = 0;
|
|
||||||
int i;
|
int i;
|
||||||
const int min_nslaves = 0; /*< not configurable at the time */
|
|
||||||
bool is_synced_master;
|
|
||||||
int (*p)(const void *, const void *);
|
|
||||||
BACKEND* master_host;
|
|
||||||
|
|
||||||
if (p_master_ref == NULL || backend_ref == NULL)
|
|
||||||
{
|
|
||||||
ss_dassert(FALSE);
|
|
||||||
succp = false;
|
|
||||||
goto return_succp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the root Master */
|
|
||||||
master_host = get_root_master(backend_ref, router_nservers);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Existing session : master is already chosen and connected.
|
|
||||||
* The function was called because new slave must be selected to replace
|
|
||||||
* failed one.
|
|
||||||
*/
|
|
||||||
if (*p_master_ref != NULL)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Ensure that backend reference is in use, stored master is
|
|
||||||
* still current root master.
|
|
||||||
*/
|
|
||||||
if (!BREF_IS_IN_USE((*p_master_ref)) ||
|
|
||||||
!SERVER_IS_MASTER((*p_master_ref)->bref_backend->backend_server) ||
|
|
||||||
master_host != (*p_master_ref)->bref_backend)
|
|
||||||
{
|
|
||||||
succp = false;
|
|
||||||
goto return_succp;
|
|
||||||
}
|
|
||||||
master_found = true;
|
|
||||||
master_connected = true;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* New session : select master and slaves
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
master_found = false;
|
|
||||||
master_connected = false;
|
|
||||||
}
|
|
||||||
/** Check slave selection criteria and set compare function */
|
|
||||||
p = criteria_cmpfun[select_criteria];
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
{
|
|
||||||
succp = false;
|
|
||||||
goto return_succp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (router->bitvalue != 0) /*< 'synced' is the only bitvalue in rwsplit */
|
if (router->bitvalue != 0) /*< 'synced' is the only bitvalue in rwsplit */
|
||||||
{
|
{
|
||||||
is_synced_master = true;
|
is_synced_master = true;
|
||||||
@ -2719,8 +2628,7 @@ static bool select_connect_backend_servers(
|
|||||||
BACKEND* b = backend_ref[i].bref_backend;
|
BACKEND* b = backend_ref[i].bref_backend;
|
||||||
|
|
||||||
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
||||||
"master bref %p bref %p %d %s %d:%d",
|
"bref %p %d %s %d:%d",
|
||||||
*p_master_ref,
|
|
||||||
&backend_ref[i],
|
&backend_ref[i],
|
||||||
backend_ref[i].bref_state,
|
backend_ref[i].bref_state,
|
||||||
b->backend_server->name,
|
b->backend_server->name,
|
||||||
@ -2728,12 +2636,6 @@ static bool select_connect_backend_servers(
|
|||||||
b->backend_conn_count)));
|
b->backend_conn_count)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/**
|
|
||||||
* Sort the pointer list to servers according to connection counts. As
|
|
||||||
* a consequence those backends having least connections are in the
|
|
||||||
* beginning of the list.
|
|
||||||
*/
|
|
||||||
qsort(backend_ref, (size_t)router_nservers, sizeof(backend_ref_t), p);
|
|
||||||
|
|
||||||
if (LOG_IS_ENABLED(LOGFILE_TRACE))
|
if (LOG_IS_ENABLED(LOGFILE_TRACE))
|
||||||
{
|
{
|
||||||
@ -2743,197 +2645,98 @@ static bool select_connect_backend_servers(
|
|||||||
select_criteria == LEAST_CURRENT_OPERATIONS)
|
select_criteria == LEAST_CURRENT_OPERATIONS)
|
||||||
{
|
{
|
||||||
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
||||||
"Servers and %s connection counts:",
|
"Servers and connection counts:")));
|
||||||
select_criteria == LEAST_GLOBAL_CONNECTIONS ?
|
|
||||||
"all MaxScale" : "router")));
|
|
||||||
|
|
||||||
for (i=0; i<router_nservers; i++)
|
for (i=0; i<router_nservers; i++)
|
||||||
{
|
{
|
||||||
BACKEND* b = backend_ref[i].bref_backend;
|
BACKEND* b = backend_ref[i].bref_backend;
|
||||||
|
|
||||||
switch(select_criteria) {
|
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
||||||
case LEAST_GLOBAL_CONNECTIONS:
|
"MaxScale connections : %d (%d) in \t%s:%d %s",
|
||||||
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
b->backend_conn_count,
|
||||||
"MaxScale connections : %d in \t%s:%d %s",
|
b->backend_server->stats.n_current,
|
||||||
b->backend_server->stats.n_current,
|
b->backend_server->name,
|
||||||
b->backend_server->name,
|
b->backend_server->port,
|
||||||
b->backend_server->port,
|
STRSRVSTATUS(b->backend_server))));
|
||||||
STRSRVSTATUS(b->backend_server))));
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case LEAST_ROUTER_CONNECTIONS:
|
|
||||||
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
|
||||||
"RWSplit connections : %d in \t%s:%d %s",
|
|
||||||
b->backend_conn_count,
|
|
||||||
b->backend_server->name,
|
|
||||||
b->backend_server->port,
|
|
||||||
STRSRVSTATUS(b->backend_server))));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LEAST_CURRENT_OPERATIONS:
|
|
||||||
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
|
||||||
"current operations : %d in \t%s:%d %s",
|
|
||||||
b->backend_server->stats.n_current_ops,
|
|
||||||
b->backend_server->name,
|
|
||||||
b->backend_server->port,
|
|
||||||
STRSRVSTATUS(b->backend_server))));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LEAST_BEHIND_MASTER:
|
|
||||||
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
|
||||||
"replication lag : %d in \t%s:%d %s",
|
|
||||||
b->backend_server->rlag,
|
|
||||||
b->backend_server->name,
|
|
||||||
b->backend_server->port,
|
|
||||||
STRSRVSTATUS(b->backend_server))));
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} /*< log only */
|
} /*< log only */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Choose at least 1+min_nslaves (master and slave) and at most 1+max_nslaves
|
* Choose at least onr server from the list.
|
||||||
* servers from the sorted list. First master found is selected.
|
|
||||||
*/
|
*/
|
||||||
for (i=0;
|
for (i=0;
|
||||||
i<router_nservers &&
|
i<router_nservers &&
|
||||||
(slaves_connected < max_nslaves || !master_connected);
|
(server_connected < max_nservers || !master_connected);
|
||||||
i++)
|
i++)
|
||||||
{
|
{
|
||||||
BACKEND* b = backend_ref[i].bref_backend;
|
BACKEND* b = backend_ref[i].bref_backend;
|
||||||
|
|
||||||
if (router->servers[i]->weight == 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SERVER_IS_RUNNING(b->backend_server) &&
|
if (SERVER_IS_RUNNING(b->backend_server) &&
|
||||||
((b->backend_server->status & router->bitmask) ==
|
((b->backend_server->status & router->bitmask) ==
|
||||||
router->bitvalue))
|
router->bitvalue))
|
||||||
{
|
{
|
||||||
/* check also for relay servers and don't take the master_host */
|
servers_found += 1;
|
||||||
if (slaves_found < max_nslaves &&
|
|
||||||
(max_slave_rlag == MAX_RLAG_UNDEFINED ||
|
|
||||||
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
|
||||||
b->backend_server->rlag <= max_slave_rlag)) &&
|
|
||||||
(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;
|
|
||||||
|
|
||||||
/** Slave is already connected */
|
/** Server is already connected */
|
||||||
if (BREF_IS_IN_USE((&backend_ref[i])))
|
if (BREF_IS_IN_USE((&backend_ref[i])))
|
||||||
{
|
{
|
||||||
slaves_connected += 1;
|
slaves_connected += 1;
|
||||||
}
|
}
|
||||||
/** New slave connection is taking place */
|
/** New server connection */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
backend_ref[i].bref_dcb = dcb_connect(
|
backend_ref[i].bref_dcb = dcb_connect(
|
||||||
b->backend_server,
|
b->backend_server,
|
||||||
session,
|
session,
|
||||||
b->backend_server->protocol);
|
b->backend_server->protocol);
|
||||||
|
|
||||||
if (backend_ref[i].bref_dcb != NULL)
|
if (backend_ref[i].bref_dcb != NULL)
|
||||||
{
|
{
|
||||||
slaves_connected += 1;
|
servers_connected += 1;
|
||||||
/**
|
/**
|
||||||
* Start executing session command
|
* Start executing session command
|
||||||
* history.
|
* history.
|
||||||
*/
|
*/
|
||||||
execute_sescmd_history(&backend_ref[i]);
|
execute_sescmd_history(&backend_ref[i]);
|
||||||
/**
|
|
||||||
* When server fails, this callback
|
/**
|
||||||
* is called.
|
* When server fails, this callback
|
||||||
*/
|
* is called.
|
||||||
dcb_add_callback(
|
* !!! Todo, routine which removes
|
||||||
backend_ref[i].bref_dcb,
|
* corresponding entries from the hash
|
||||||
DCB_REASON_NOT_RESPONDING,
|
* table.
|
||||||
&router_handle_state_switch,
|
*/
|
||||||
(void *)&backend_ref[i]);
|
#if 0
|
||||||
backend_ref[i].bref_state = 0;
|
dcb_add_callback(
|
||||||
bref_set_state(&backend_ref[i],
|
backend_ref[i].bref_dcb,
|
||||||
BREF_IN_USE);
|
DCB_REASON_NOT_RESPONDING,
|
||||||
/**
|
&router_handle_state_switch,
|
||||||
* Increase backend connection counter.
|
(void *)&backend_ref[i]);
|
||||||
* Server's stats are _increased_ in
|
#endif
|
||||||
* dcb.c:dcb_alloc !
|
backend_ref[i].bref_state = 0;
|
||||||
* But decreased in the calling function
|
bref_set_state(&backend_ref[i],
|
||||||
* of dcb_close.
|
BREF_IN_USE);
|
||||||
*/
|
/**
|
||||||
atomic_add(&b->backend_conn_count, 1);
|
* Increase backend connection counter.
|
||||||
}
|
* Server's stats are _increased_ in
|
||||||
else
|
* dcb.c:dcb_alloc !
|
||||||
{
|
* But decreased in the calling function
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
* of dcb_close.
|
||||||
LOGFILE_ERROR,
|
*/
|
||||||
"Error : Unable to establish "
|
atomic_add(&b->backend_conn_count, 1);
|
||||||
"connection with slave %s:%d",
|
}
|
||||||
b->backend_server->name,
|
else
|
||||||
b->backend_server->port)));
|
{
|
||||||
/* handle connect error */
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
}
|
LOGFILE_ERROR,
|
||||||
}
|
"Error : Unable to establish "
|
||||||
}
|
"connection with slave %s:%d",
|
||||||
/* take the master_host for master */
|
b->backend_server->name,
|
||||||
else if (master_host &&
|
b->backend_server->port)));
|
||||||
(b->backend_server == master_host->backend_server))
|
/* handle connect error */
|
||||||
{
|
}
|
||||||
/**
|
}
|
||||||
* *p_master_ref must be assigned with this
|
}
|
||||||
* backend_ref pointer because its original value
|
|
||||||
* may have been lost when backend references were
|
|
||||||
* sorted (qsort).
|
|
||||||
*/
|
|
||||||
*p_master_ref = &backend_ref[i];
|
|
||||||
|
|
||||||
if (master_connected)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
master_found = true;
|
|
||||||
|
|
||||||
backend_ref[i].bref_dcb = dcb_connect(
|
|
||||||
b->backend_server,
|
|
||||||
session,
|
|
||||||
b->backend_server->protocol);
|
|
||||||
|
|
||||||
if (backend_ref[i].bref_dcb != NULL)
|
|
||||||
{
|
|
||||||
master_connected = true;
|
|
||||||
/**
|
|
||||||
* When server fails, this callback
|
|
||||||
* is called.
|
|
||||||
*/
|
|
||||||
dcb_add_callback(
|
|
||||||
backend_ref[i].bref_dcb,
|
|
||||||
DCB_REASON_NOT_RESPONDING,
|
|
||||||
&router_handle_state_switch,
|
|
||||||
(void *)&backend_ref[i]);
|
|
||||||
|
|
||||||
backend_ref[i].bref_state = 0;
|
|
||||||
bref_set_state(&backend_ref[i],
|
|
||||||
BREF_IN_USE);
|
|
||||||
/** Increase backend connection counters */
|
|
||||||
atomic_add(&b->backend_conn_count, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
succp = false;
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unable to establish "
|
|
||||||
"connection with master %s:%d",
|
|
||||||
b->backend_server->name,
|
|
||||||
b->backend_server->port)));
|
|
||||||
/** handle connect error */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} /*< for */
|
} /*< for */
|
||||||
|
|
||||||
#if defined(EXTRA_SS_DEBUG)
|
#if defined(EXTRA_SS_DEBUG)
|
||||||
@ -2943,178 +2746,66 @@ static bool select_connect_backend_servers(
|
|||||||
{
|
{
|
||||||
BACKEND* b = backend_ref[i].bref_backend;
|
BACKEND* b = backend_ref[i].bref_backend;
|
||||||
|
|
||||||
LOGIF(LT, (skygw_log_write_flush(LOGFILE_TRACE,
|
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
||||||
"master bref %p bref %p %d %s %d:%d",
|
"bref %p %d %s %d:%d",
|
||||||
*p_master_ref,
|
&backend_ref[i],
|
||||||
&backend_ref[i],
|
backend_ref[i].bref_state,
|
||||||
backend_ref[i].bref_state,
|
b->backend_server->name,
|
||||||
b->backend_server->name,
|
b->backend_server->port,
|
||||||
b->backend_server->port,
|
b->backend_conn_count)));
|
||||||
b->backend_conn_count)));
|
|
||||||
}
|
}
|
||||||
/* assert with master_host */
|
#endif
|
||||||
ss_dassert(!master_connected ||
|
|
||||||
(master_host && ((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) &&
|
|
||||||
SERVER_MASTER));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Successful cases
|
* Successful cases
|
||||||
*/
|
*/
|
||||||
if (master_connected &&
|
if (servers_connected > 0)
|
||||||
slaves_connected >= min_nslaves &&
|
|
||||||
slaves_connected <= max_nslaves)
|
|
||||||
{
|
{
|
||||||
succp = true;
|
if (servers_connected == 0)
|
||||||
|
{
|
||||||
if (slaves_connected == 0 && slaves_found > 0)
|
/** Failure case */
|
||||||
|
succp = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
succp = true;
|
||||||
|
|
||||||
|
if (LOG_IS_ENABLED(LT))
|
||||||
|
{
|
||||||
|
for (i=0; i<router_nservers; i++)
|
||||||
|
{
|
||||||
|
BACKEND* b = backend_ref[i].bref_backend;
|
||||||
|
|
||||||
|
if (BREF_IS_IN_USE((&backend_ref[i])))
|
||||||
|
{
|
||||||
|
LOGIF(LT, (skygw_log_write(
|
||||||
|
LOGFILE_TRACE,
|
||||||
|
"Connected %s in \t%s:%d",
|
||||||
|
STRSRVSTATUS(b->backend_server),
|
||||||
|
b->backend_server->name,
|
||||||
|
b->backend_server->port)));
|
||||||
|
}
|
||||||
|
} /* for */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servers_connected < router_nservers)
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write(
|
LOGIF(LE, (skygw_log_write(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Warning : Couldn't connect to any of the %d "
|
"Warning : Couldn't connect to all available "
|
||||||
"slaves. Routing to %s only.",
|
"servers. Routing to %d out of %d only.",
|
||||||
slaves_found,
|
servers_found,
|
||||||
(is_synced_master ? "Galera nodes" : "Master"))));
|
router_nservers)));
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
LOGIF(LE, (skygw_log_write(
|
||||||
LOGFILE_MESSAGE,
|
LOGFILE_ERROR,
|
||||||
"* Warning : Couldn't connect to any of the %d "
|
"* Warning : Couldn't connect to all available "
|
||||||
"slaves. Routing to %s only.",
|
"servers. Routing to %d out of %d only.",
|
||||||
slaves_found,
|
servers_found,
|
||||||
(is_synced_master ? "Galera nodes" : "Master"))));
|
router_nservers)));
|
||||||
}
|
}
|
||||||
else if (slaves_found == 0)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Warning : Couldn't find any slaves from existing "
|
|
||||||
"%d servers. Routing to %s only.",
|
|
||||||
router_nservers,
|
|
||||||
(is_synced_master ? "Galera nodes" : "Master"))));
|
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
|
||||||
LOGFILE_MESSAGE,
|
|
||||||
"* Warning : Couldn't find any slaves from existing "
|
|
||||||
"%d servers. Routing to %s only.",
|
|
||||||
router_nservers,
|
|
||||||
(is_synced_master ? "Galera nodes" : "Master"))));
|
|
||||||
}
|
|
||||||
else if (slaves_connected < max_nslaves)
|
|
||||||
{
|
|
||||||
LOGIF(LT, (skygw_log_write_flush(
|
|
||||||
LOGFILE_TRACE,
|
|
||||||
"Note : Couldn't connect to maximum number of "
|
|
||||||
"slaves. Connected successfully to %d slaves "
|
|
||||||
"of %d of them.",
|
|
||||||
slaves_connected,
|
|
||||||
slaves_found)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOG_IS_ENABLED(LT))
|
|
||||||
{
|
|
||||||
for (i=0; i<router_nservers; i++)
|
|
||||||
{
|
|
||||||
BACKEND* b = backend_ref[i].bref_backend;
|
|
||||||
|
|
||||||
if (BREF_IS_IN_USE((&backend_ref[i])))
|
|
||||||
{
|
|
||||||
LOGIF(LT, (skygw_log_write(
|
|
||||||
LOGFILE_TRACE,
|
|
||||||
"Selected %s in \t%s:%d",
|
|
||||||
STRSRVSTATUS(b->backend_server),
|
|
||||||
b->backend_server->name,
|
|
||||||
b->backend_server->port)));
|
|
||||||
}
|
|
||||||
} /* for */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Failure cases
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
succp = false;
|
|
||||||
|
|
||||||
if (!master_found)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Couldn't find suitable %s from %d "
|
|
||||||
"candidates.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
router_nservers)));
|
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
|
||||||
LOGFILE_MESSAGE,
|
|
||||||
"Error : Couldn't find suitable %s from %d "
|
|
||||||
"candidates.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
router_nservers)));
|
|
||||||
|
|
||||||
LOGIF(LT, (skygw_log_write(
|
|
||||||
LOGFILE_TRACE,
|
|
||||||
"Error : Couldn't find suitable %s from %d "
|
|
||||||
"candidates.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
router_nservers)));
|
|
||||||
}
|
|
||||||
else if (!master_connected)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Couldn't connect to any %s although "
|
|
||||||
"there exists at least one %s node in the "
|
|
||||||
"cluster.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
(is_synced_master ? "Galera node" : "Master"))));
|
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
|
||||||
LOGFILE_MESSAGE,
|
|
||||||
"Error : Couldn't connect to any %s although "
|
|
||||||
"there exists at least one %s node in the "
|
|
||||||
"cluster.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
(is_synced_master ? "Galera node" : "Master"))));
|
|
||||||
|
|
||||||
LOGIF(LT, (skygw_log_write(
|
|
||||||
LOGFILE_TRACE,
|
|
||||||
"Error : Couldn't connect to any %s although "
|
|
||||||
"there exists at least one %s node in the "
|
|
||||||
"cluster.",
|
|
||||||
(is_synced_master ? "Galera node" : "Master"),
|
|
||||||
(is_synced_master ? "Galera node" : "Master"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (slaves_connected < min_nslaves)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Couldn't establish required amount of "
|
|
||||||
"slave connections for router session.")));
|
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
|
||||||
LOGFILE_MESSAGE,
|
|
||||||
"Error : Couldn't establish required amount of "
|
|
||||||
"slave connections for router session.")));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clean up connections */
|
|
||||||
for (i=0; i<router_nservers; i++)
|
|
||||||
{
|
|
||||||
if (BREF_IS_IN_USE((&backend_ref[i])))
|
|
||||||
{
|
|
||||||
ss_dassert(backend_ref[i].bref_backend->backend_conn_count > 0);
|
|
||||||
|
|
||||||
/** disconnect opened connections */
|
|
||||||
dcb_close(backend_ref[i].bref_dcb);
|
|
||||||
bref_clear_state(&backend_ref[i], BREF_IN_USE);
|
|
||||||
/** Decrease backend's connection counter. */
|
|
||||||
atomic_add(&backend_ref[i].bref_backend->backend_conn_count, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master_connected = false;
|
|
||||||
slaves_connected = 0;
|
|
||||||
}
|
|
||||||
return_succp:
|
return_succp:
|
||||||
|
|
||||||
return succp;
|
return succp;
|
||||||
@ -4048,30 +3739,15 @@ static void handleError (
|
|||||||
*succp = false;
|
*succp = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
if (rses->rses_master_ref->bref_dcb == backend_dcb &&
|
* This is called in hope of getting replacement for
|
||||||
!SERVER_IS_MASTER(rses->rses_master_ref->bref_backend->backend_server))
|
* failed slave(s).
|
||||||
{
|
*/
|
||||||
/** Master failed, can't recover */
|
*succp = handle_error_new_connection(inst,
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
rses,
|
||||||
LOGFILE_ERROR,
|
backend_dcb,
|
||||||
"Error : Master node have failed. "
|
errmsgbuf);
|
||||||
"Session will be closed.")));
|
rses_end_locked_router_action(rses);
|
||||||
|
|
||||||
*succp = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This is called in hope of getting replacement for
|
|
||||||
* failed slave(s).
|
|
||||||
*/
|
|
||||||
*succp = handle_error_new_connection(inst,
|
|
||||||
rses,
|
|
||||||
backend_dcb,
|
|
||||||
errmsgbuf);
|
|
||||||
}
|
|
||||||
rses_end_locked_router_action(rses);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4126,8 +3802,7 @@ static void handle_error_reply_client(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if there is backend reference pointing at failed DCB, and reset its
|
* Check if there is backend reference pointing at failed DCB, and reset its
|
||||||
* flags. Then clear DCB's callback and finally : try to find replacement(s)
|
* flags. Then clear DCB's callback and finally try to reconnect.
|
||||||
* for failed slave(s).
|
|
||||||
*
|
*
|
||||||
* This must be called with router lock.
|
* This must be called with router lock.
|
||||||
*
|
*
|
||||||
@ -4161,7 +3836,8 @@ static bool handle_error_new_connection(
|
|||||||
*/
|
*/
|
||||||
if ((bref = get_bref_from_dcb(rses, backend_dcb)) == NULL)
|
if ((bref = get_bref_from_dcb(rses, backend_dcb)) == NULL)
|
||||||
{
|
{
|
||||||
succp = true;
|
ss_dassert(bref != NULL);
|
||||||
|
succp = false;
|
||||||
goto return_succp;
|
goto return_succp;
|
||||||
}
|
}
|
||||||
CHK_BACKEND_REF(bref);
|
CHK_BACKEND_REF(bref);
|
||||||
@ -4202,19 +3878,13 @@ static bool handle_error_new_connection(
|
|||||||
(void *)bref);
|
(void *)bref);
|
||||||
|
|
||||||
router_nservers = router_get_servercount(inst);
|
router_nservers = router_get_servercount(inst);
|
||||||
max_nslaves = rses_get_max_slavecount(rses, router_nservers);
|
|
||||||
max_slave_rlag = rses_get_max_replication_lag(rses);
|
|
||||||
/**
|
/**
|
||||||
* Try to get replacement slave or at least the minimum
|
* Try to get replacement slave or at least the minimum
|
||||||
* number of slave connections for router session.
|
* number of slave connections for router session.
|
||||||
*/
|
*/
|
||||||
succp = select_connect_backend_servers(
|
succp = select_connect_backend_servers(
|
||||||
&rses->rses_master_ref,
|
|
||||||
rses->rses_backend_ref,
|
rses->rses_backend_ref,
|
||||||
router_nservers,
|
router_nservers,
|
||||||
max_nslaves,
|
|
||||||
max_slave_rlag,
|
|
||||||
rses->rses_config.rw_slave_select_criteria,
|
|
||||||
ses,
|
ses,
|
||||||
inst);
|
inst);
|
||||||
|
|
||||||
@ -4288,70 +3958,6 @@ static int router_get_servercount(
|
|||||||
return router_nservers;
|
return router_nservers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool have_enough_servers(
|
|
||||||
ROUTER_CLIENT_SES** p_rses,
|
|
||||||
const int min_nsrv,
|
|
||||||
int router_nsrv,
|
|
||||||
ROUTER_INSTANCE* router)
|
|
||||||
{
|
|
||||||
bool succp;
|
|
||||||
|
|
||||||
/** With too few servers session is not created */
|
|
||||||
if (router_nsrv < min_nsrv ||
|
|
||||||
MAX((*p_rses)->rses_config.rw_max_slave_conn_count,
|
|
||||||
(router_nsrv*(*p_rses)->rses_config.rw_max_slave_conn_percent)/100)
|
|
||||||
< min_nsrv)
|
|
||||||
{
|
|
||||||
if (router_nsrv < min_nsrv)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unable to start %s service. There are "
|
|
||||||
"too few backend servers available. Found %d "
|
|
||||||
"when %d is required.",
|
|
||||||
router->service->name,
|
|
||||||
router_nsrv,
|
|
||||||
min_nsrv)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int pct = (*p_rses)->rses_config.rw_max_slave_conn_percent/100;
|
|
||||||
int nservers = router_nsrv*pct;
|
|
||||||
|
|
||||||
if ((*p_rses)->rses_config.rw_max_slave_conn_count < min_nsrv)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unable to start %s service. There are "
|
|
||||||
"too few backend servers configured in "
|
|
||||||
"MaxScale.cnf. Found %d when %d is required.",
|
|
||||||
router->service->name,
|
|
||||||
(*p_rses)->rses_config.rw_max_slave_conn_count,
|
|
||||||
min_nsrv)));
|
|
||||||
}
|
|
||||||
if (nservers < min_nsrv)
|
|
||||||
{
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unable to start %s service. There are "
|
|
||||||
"too few backend servers configured in "
|
|
||||||
"MaxScale.cnf. Found %d%% when at least %d%% "
|
|
||||||
"would be required.",
|
|
||||||
router->service->name,
|
|
||||||
(*p_rses)->rses_config.rw_max_slave_conn_percent,
|
|
||||||
min_nsrv/(router_nsrv/100))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(*p_rses);
|
|
||||||
*p_rses = NULL;
|
|
||||||
succp = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
succp = true;
|
|
||||||
}
|
|
||||||
return succp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find out the number of read backend servers.
|
* Find out the number of read backend servers.
|
||||||
|
Reference in New Issue
Block a user