Added database list refreshing to schemarouter.

This commit is contained in:
Markus Makela
2015-06-09 16:13:06 +03:00
parent 528e69b726
commit b1c383b19e
2 changed files with 59 additions and 7 deletions

View File

@ -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 : \

View File

@ -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;
} }
} }