Added database list refreshing to schemarouter.
This commit is contained in:
@ -241,6 +241,9 @@ typedef struct schemarouter_config_st {
|
|||||||
target_t rw_use_sql_variables_in;
|
target_t rw_use_sql_variables_in;
|
||||||
int max_sescmd_hist;
|
int max_sescmd_hist;
|
||||||
bool disable_sescmd_hist;
|
bool disable_sescmd_hist;
|
||||||
|
time_t last_refresh; /*< Last time the database list was refreshed */
|
||||||
|
double refresh_min_interval; /*< Minimum required interval between refreshes of databases */
|
||||||
|
bool refresh_databases; /*< Are databases refreshed when they are not found in the hashtable */
|
||||||
} schemarouter_config_t;
|
} schemarouter_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,6 +316,7 @@ typedef struct router_instance {
|
|||||||
struct router_instance* next; /*< Next router on the list */
|
struct router_instance* next; /*< Next router on the list */
|
||||||
bool available_slaves; /*< The router has some slaves available */
|
bool available_slaves; /*< The router has some slaves available */
|
||||||
|
|
||||||
|
|
||||||
} ROUTER_INSTANCE;
|
} ROUTER_INSTANCE;
|
||||||
|
|
||||||
#define BACKEND_TYPE(b) (SERVER_IS_MASTER((b)->backend_server) ? BE_MASTER : \
|
#define BACKEND_TYPE(b) (SERVER_IS_MASTER((b)->backend_server) ? BE_MASTER : \
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include <modutil.h>
|
#include <modutil.h>
|
||||||
#include <mysql_client_server_protocol.h>
|
#include <mysql_client_server_protocol.h>
|
||||||
|
|
||||||
|
#define DEFAULT_REFRESH_INTERVAL 30.0
|
||||||
|
|
||||||
MODULE_INFO info = {
|
MODULE_INFO info = {
|
||||||
MODULE_API_ROUTER,
|
MODULE_API_ROUTER,
|
||||||
MODULE_BETA_RELEASE,
|
MODULE_BETA_RELEASE,
|
||||||
@ -400,6 +402,12 @@ int gen_databaselist(ROUTER_INSTANCE* inst, ROUTER_CLIENT_SES* session)
|
|||||||
int i,rval = 0;
|
int i,rval = 0;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
|
for(i = 0;i<session->rses_nbackends;i++)
|
||||||
|
{
|
||||||
|
session->rses_backend_ref[i].bref_mapped = false;
|
||||||
|
session->rses_backend_ref[i].n_mapping_eof = 0;
|
||||||
|
}
|
||||||
|
|
||||||
session->init |= INIT_MAPPING;
|
session->init |= INIT_MAPPING;
|
||||||
session->init &= ~INIT_UNINT;
|
session->init &= ~INIT_UNINT;
|
||||||
len = strlen(query) + 1;
|
len = strlen(query) + 1;
|
||||||
@ -712,6 +720,9 @@ createInstance(SERVICE *service, char **options)
|
|||||||
}
|
}
|
||||||
router->service = service;
|
router->service = service;
|
||||||
router->schemarouter_config.max_sescmd_hist = 0;
|
router->schemarouter_config.max_sescmd_hist = 0;
|
||||||
|
router->schemarouter_config.last_refresh = time(NULL);
|
||||||
|
router->schemarouter_config.refresh_databases = false;
|
||||||
|
router->schemarouter_config.refresh_min_interval = DEFAULT_REFRESH_INTERVAL;
|
||||||
router->stats.longest_sescmd = 0;
|
router->stats.longest_sescmd = 0;
|
||||||
router->stats.n_hist_exceeded = 0;
|
router->stats.n_hist_exceeded = 0;
|
||||||
router->stats.n_queries = 0;
|
router->stats.n_queries = 0;
|
||||||
@ -753,6 +764,14 @@ createInstance(SERVICE *service, char **options)
|
|||||||
{
|
{
|
||||||
router->schemarouter_config.disable_sescmd_hist = config_truth_value(value);
|
router->schemarouter_config.disable_sescmd_hist = config_truth_value(value);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(options[i],"refresh_databases") == 0)
|
||||||
|
{
|
||||||
|
router->schemarouter_config.refresh_databases = config_truth_value(value);
|
||||||
|
}
|
||||||
|
else if(strcmp(options[i],"refresh_interval") == 0)
|
||||||
|
{
|
||||||
|
router->schemarouter_config.refresh_min_interval = atof(value);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error: Unknown router options for Schemarouter: %s",options[i]);
|
skygw_log_write(LOGFILE_ERROR,"Error: Unknown router options for Schemarouter: %s",options[i]);
|
||||||
@ -935,6 +954,7 @@ static void* newSession(
|
|||||||
client_rses->dcb_route->func.read = internalRoute;
|
client_rses->dcb_route->func.read = internalRoute;
|
||||||
client_rses->dcb_route->state = DCB_STATE_POLLING;
|
client_rses->dcb_route->state = DCB_STATE_POLLING;
|
||||||
client_rses->dcb_route->session = session;
|
client_rses->dcb_route->session = session;
|
||||||
|
client_rses->rses_config.last_refresh = time(NULL);
|
||||||
client_rses->init = INIT_UNINT;
|
client_rses->init = INIT_UNINT;
|
||||||
if(using_db)
|
if(using_db)
|
||||||
client_rses->init |= INIT_USE_DB;
|
client_rses->init |= INIT_USE_DB;
|
||||||
@ -2015,20 +2035,48 @@ static int routeQuery(
|
|||||||
router_cli_ses->dbhash,
|
router_cli_ses->dbhash,
|
||||||
querybuf)))
|
querybuf)))
|
||||||
{
|
{
|
||||||
|
time_t now = time(NULL);
|
||||||
|
if(router_cli_ses->rses_config.refresh_databases &&
|
||||||
|
difftime(now,router_cli_ses->rses_config.last_refresh) >
|
||||||
|
router_cli_ses->rses_config.refresh_min_interval)
|
||||||
|
{
|
||||||
|
rses_begin_locked_router_action(router_cli_ses);
|
||||||
|
router_cli_ses->rses_config.last_refresh = now;
|
||||||
|
router_cli_ses->queue = querybuf;
|
||||||
|
hashtable_free(router_cli_ses->dbhash);
|
||||||
|
if((router_cli_ses->dbhash = hashtable_alloc(100, hashkeyfun, hashcmpfun)) == NULL)
|
||||||
|
{
|
||||||
|
skygw_log_write(LE,"Error: Hashtable allocation failed.");
|
||||||
|
rses_end_locked_router_action(router_cli_ses);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
hashtable_memory_fns(router_cli_ses->dbhash,(HASHMEMORYFN)strdup,
|
||||||
|
(HASHMEMORYFN)strdup,
|
||||||
|
(HASHMEMORYFN)free,
|
||||||
|
(HASHMEMORYFN)free);
|
||||||
|
gen_databaselist(inst,router_cli_ses);
|
||||||
|
rses_end_locked_router_action(router_cli_ses);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
extract_database(querybuf,db);
|
extract_database(querybuf,db);
|
||||||
snprintf(errbuf,25+MYSQL_DATABASE_MAXLEN,"Unknown database: %s",db);
|
snprintf(errbuf,25+MYSQL_DATABASE_MAXLEN,"Unknown database: %s",db);
|
||||||
for(i = 0;i<router_cli_ses->rses_nbackends;i++)
|
GWBUF* error = modutil_create_mysql_err_msg(1, 0, 1049, "42000", errbuf);
|
||||||
|
|
||||||
|
if (error == NULL)
|
||||||
{
|
{
|
||||||
if(SERVER_IS_RUNNING(router_cli_ses->rses_backend_ref[i].bref_backend->backend_server))
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
{
|
LOGFILE_ERROR,
|
||||||
create_error_reply(errbuf,router_cli_ses->rses_backend_ref[i].bref_dcb);
|
"Error : Creating buffer for error message failed.")));
|
||||||
break;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/** Set flags that help router to identify session commands reply */
|
||||||
|
router_cli_ses->rses_client_dcb->func.write(router_cli_ses->rses_client_dcb,error);
|
||||||
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Error : Changing database failed.")));
|
"Error : Changing database failed.")));
|
||||||
|
ret = 1;
|
||||||
|
goto retblock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user