Remove unnecessary SConfig from readwritesplit

The configuration doesn't need to be contained in shared pointer as each
session holds its own version of it. This removes most of the overhead in
configuration reloading. The only thing that's left is any overhead added
by the use of thread-local storage.
This commit is contained in:
Markus Mäkelä
2018-08-01 10:25:15 +03:00
parent 403b9e09f5
commit c01840ffb3
7 changed files with 116 additions and 117 deletions

View File

@ -58,7 +58,7 @@ using namespace maxscale;
* @param options Router options
* @return True on success, false if a configuration error was found
*/
static bool rwsplit_process_router_options(SConfig config, char **options)
static bool rwsplit_process_router_options(Config& config, char **options)
{
if (options == NULL)
{
@ -94,51 +94,51 @@ static bool rwsplit_process_router_options(SConfig config, char **options)
"Allowed values are LEAST_GLOBAL_CONNECTIONS, "
"LEAST_ROUTER_CONNECTIONS, LEAST_BEHIND_MASTER,"
"and LEAST_CURRENT_OPERATIONS.",
STRCRITERIA(config->slave_selection_criteria));
STRCRITERIA(config.slave_selection_criteria));
success = false;
}
else
{
config->slave_selection_criteria = c;
config.slave_selection_criteria = c;
}
}
else if (strcmp(options[i], "max_sescmd_history") == 0)
{
config->max_sescmd_history = atoi(value);
config.max_sescmd_history = atoi(value);
}
else if (strcmp(options[i], "disable_sescmd_history") == 0)
{
config->disable_sescmd_history = config_truth_value(value);
config.disable_sescmd_history = config_truth_value(value);
}
else if (strcmp(options[i], "master_accept_reads") == 0)
{
config->master_accept_reads = config_truth_value(value);
config.master_accept_reads = config_truth_value(value);
}
else if (strcmp(options[i], "strict_multi_stmt") == 0)
{
config->strict_multi_stmt = config_truth_value(value);
config.strict_multi_stmt = config_truth_value(value);
}
else if (strcmp(options[i], "strict_sp_calls") == 0)
{
config->strict_sp_calls = config_truth_value(value);
config.strict_sp_calls = config_truth_value(value);
}
else if (strcmp(options[i], "retry_failed_reads") == 0)
{
config->retry_failed_reads = config_truth_value(value);
config.retry_failed_reads = config_truth_value(value);
}
else if (strcmp(options[i], "master_failure_mode") == 0)
{
if (strcasecmp(value, "fail_instantly") == 0)
{
config->master_failure_mode = RW_FAIL_INSTANTLY;
config.master_failure_mode = RW_FAIL_INSTANTLY;
}
else if (strcasecmp(value, "fail_on_write") == 0)
{
config->master_failure_mode = RW_FAIL_ON_WRITE;
config.master_failure_mode = RW_FAIL_ON_WRITE;
}
else if (strcasecmp(value, "error_on_write") == 0)
{
config->master_failure_mode = RW_ERROR_ON_WRITE;
config.master_failure_mode = RW_ERROR_ON_WRITE;
}
else
{
@ -159,7 +159,7 @@ static bool rwsplit_process_router_options(SConfig config, char **options)
}
// TODO: Don't process parameters in readwritesplit
static bool handle_max_slaves(SConfig config, const char *str)
static bool handle_max_slaves(Config& config, const char *str)
{
bool rval = true;
char *endptr;
@ -167,13 +167,13 @@ static bool handle_max_slaves(SConfig config, const char *str)
if (*endptr == '%' && *(endptr + 1) == '\0')
{
config->rw_max_slave_conn_percent = val;
config->max_slave_connections = 0;
config.rw_max_slave_conn_percent = val;
config.max_slave_connections = 0;
}
else if (*endptr == '\0')
{
config->max_slave_connections = val;
config->rw_max_slave_conn_percent = 0;
config.max_slave_connections = val;
config.rw_max_slave_conn_percent = 0;
}
else
{
@ -184,7 +184,7 @@ static bool handle_max_slaves(SConfig config, const char *str)
return rval;
}
RWSplit::RWSplit(SERVICE* service, SConfig config):
RWSplit::RWSplit(SERVICE* service, const Config& config):
mxs::Router<RWSplit, RWSplitSession>(service),
m_service(service),
m_config(config),
@ -194,7 +194,7 @@ RWSplit::RWSplit(SERVICE* service, SConfig config):
static void data_destroy_callback(void* data)
{
SConfig* my_config = static_cast<SConfig*>(data);
Config* my_config = static_cast<Config*>(data);
delete my_config;
}
@ -208,16 +208,17 @@ SERVICE* RWSplit::service() const
return m_service;
}
SConfig* RWSplit::get_local_config() const
Config* RWSplit::get_local_config() const
{
SConfig* my_config = static_cast<SConfig*>(mxs_rworker_get_data(m_wkey));
Config* my_config = static_cast<Config*>(mxs_rworker_get_data(m_wkey));
if (my_config == nullptr)
{
// First time we get the configuration, create and update it
my_config = new SConfig;
m_lock.lock();
my_config = new Config(m_config);
m_lock.unlock();
mxs_rworker_set_data(m_wkey, my_config, data_destroy_callback);
update_local_config();
}
ss_dassert(my_config);
@ -226,7 +227,7 @@ SConfig* RWSplit::get_local_config() const
void RWSplit::update_local_config() const
{
SConfig* my_config = get_local_config();
Config* my_config = get_local_config();
m_lock.lock();
*my_config = m_config;
@ -239,7 +240,7 @@ void RWSplit::update_config(void* data)
inst->update_local_config();
}
void RWSplit::store_config(SConfig config)
void RWSplit::store_config(const Config& config)
{
m_lock.lock();
m_config = config;
@ -249,7 +250,7 @@ void RWSplit::store_config(SConfig config)
mxs_rworker_broadcast(update_config, this);
}
SConfig RWSplit::config() const
const Config& RWSplit::config() const
{
return *get_local_config();
}
@ -266,9 +267,9 @@ const Stats& RWSplit::stats() const
int RWSplit::max_slave_count() const
{
int router_nservers = m_service->n_dbref;
int conf_max_nslaves = m_config->max_slave_connections > 0 ?
m_config->max_slave_connections :
(router_nservers * m_config->rw_max_slave_conn_percent) / 100;
int conf_max_nslaves = m_config.max_slave_connections > 0 ?
m_config.max_slave_connections :
(router_nservers * m_config.rw_max_slave_conn_percent) / 100;
return MXS_MIN(router_nservers - 1, MXS_MAX(1, conf_max_nslaves));
}
@ -278,8 +279,8 @@ bool RWSplit::have_enough_servers() const
const int min_nsrv = 1;
const int router_nsrv = m_service->n_dbref;
int n_serv = MXS_MAX(m_config->max_slave_connections,
(router_nsrv * m_config->rw_max_slave_conn_percent) / 100);
int n_serv = MXS_MAX(m_config.max_slave_connections,
(router_nsrv * m_config.rw_max_slave_conn_percent) / 100);
/** With too few servers session is not created */
if (router_nsrv < min_nsrv || n_serv < min_nsrv)
@ -292,15 +293,15 @@ bool RWSplit::have_enough_servers() const
}
else
{
int pct = m_config->rw_max_slave_conn_percent / 100;
int pct = m_config.rw_max_slave_conn_percent / 100;
int nservers = router_nsrv * pct;
if (m_config->max_slave_connections < min_nsrv)
if (m_config.max_slave_connections < min_nsrv)
{
MXS_ERROR("Unable to start %s service. There are "
"too few backend servers configured in "
"MaxScale.cnf. Found %d when %d is required.",
m_service->name, m_config->max_slave_connections, min_nsrv);
m_service->name, m_config.max_slave_connections, min_nsrv);
}
if (nservers < min_nsrv)
{
@ -309,7 +310,7 @@ bool RWSplit::have_enough_servers() const
"too few backend servers configured in "
"MaxScale.cnf. Found %d%% when at least %.0f%% "
"would be required.", m_service->name,
m_config->rw_max_slave_conn_percent, dbgpct);
m_config.rw_max_slave_conn_percent, dbgpct);
}
}
succp = false;
@ -345,7 +346,7 @@ RWSplit* RWSplit::create(SERVICE *service, MXS_CONFIG_PARAMETER* params)
return NULL;
}
SConfig config(new Config(params));
Config config(params);
if (!handle_max_slaves(config, config_get_string(params, "max_slave_connections")))
{
@ -353,25 +354,25 @@ RWSplit* RWSplit::create(SERVICE *service, MXS_CONFIG_PARAMETER* params)
}
/** These options cancel each other out */
if (config->disable_sescmd_history && config->max_sescmd_history > 0)
if (config.disable_sescmd_history && config.max_sescmd_history > 0)
{
config->max_sescmd_history = 0;
config.max_sescmd_history = 0;
}
if (config->optimistic_trx)
if (config.optimistic_trx)
{
// Optimistic transaction routing requires transaction replay
config->transaction_replay = true;
config.transaction_replay = true;
}
if (config->transaction_replay)
if (config.transaction_replay)
{
/**
* Replaying transactions requires that we are able to do delayed query
* retries and reconnect to a master.
*/
config->delayed_retry = true;
config->master_reconnection = true;
config.delayed_retry = true;
config.master_reconnection = true;
}
return new (std::nothrow) RWSplit(service, config);
@ -388,41 +389,41 @@ void RWSplit::diagnostics(DCB *dcb)
{
const char *weightby = serviceGetWeightingParameter(service());
double master_pct = 0.0, slave_pct = 0.0, all_pct = 0.0;
SConfig cnf = config();
Config cnf = config();
dcb_printf(dcb, "\n");
dcb_printf(dcb, "\tuse_sql_variables_in: %s\n",
mxs_target_to_str(cnf->use_sql_variables_in));
mxs_target_to_str(cnf.use_sql_variables_in));
dcb_printf(dcb, "\tslave_selection_criteria: %s\n",
select_criteria_to_str(cnf->slave_selection_criteria));
select_criteria_to_str(cnf.slave_selection_criteria));
dcb_printf(dcb, "\tmaster_failure_mode: %s\n",
failure_mode_to_str(cnf->master_failure_mode));
failure_mode_to_str(cnf.master_failure_mode));
dcb_printf(dcb, "\tmax_slave_replication_lag: %d\n",
cnf->max_slave_replication_lag);
cnf.max_slave_replication_lag);
dcb_printf(dcb, "\tretry_failed_reads: %s\n",
cnf->retry_failed_reads ? "true" : "false");
cnf.retry_failed_reads ? "true" : "false");
dcb_printf(dcb, "\tstrict_multi_stmt: %s\n",
cnf->strict_multi_stmt ? "true" : "false");
cnf.strict_multi_stmt ? "true" : "false");
dcb_printf(dcb, "\tstrict_sp_calls: %s\n",
cnf->strict_sp_calls ? "true" : "false");
cnf.strict_sp_calls ? "true" : "false");
dcb_printf(dcb, "\tdisable_sescmd_history: %s\n",
cnf->disable_sescmd_history ? "true" : "false");
cnf.disable_sescmd_history ? "true" : "false");
dcb_printf(dcb, "\tmax_sescmd_history: %lu\n",
cnf->max_sescmd_history);
cnf.max_sescmd_history);
dcb_printf(dcb, "\tmaster_accept_reads: %s\n",
cnf->master_accept_reads ? "true" : "false");
cnf.master_accept_reads ? "true" : "false");
dcb_printf(dcb, "\tconnection_keepalive: %d\n",
cnf->connection_keepalive);
cnf.connection_keepalive);
dcb_printf(dcb, "\tcausal_reads: %s\n",
cnf->causal_reads ? "true" : "false");
cnf.causal_reads ? "true" : "false");
dcb_printf(dcb, "\tcausal_reads_timeout: %s\n",
cnf->causal_reads_timeout.c_str());
cnf.causal_reads_timeout.c_str());
dcb_printf(dcb, "\tmaster_reconnection: %s\n",
cnf->master_reconnection ? "true" : "false");
cnf.master_reconnection ? "true" : "false");
dcb_printf(dcb, "\tdelayed_retry: %s\n",
cnf->delayed_retry ? "true" : "false");
cnf.delayed_retry ? "true" : "false");
dcb_printf(dcb, "\tdelayed_retry_timeout: %lu\n",
cnf->delayed_retry_timeout);
cnf.delayed_retry_timeout);
dcb_printf(dcb, "\n");
@ -504,11 +505,11 @@ uint64_t RWSplit::getCapabilities()
bool RWSplit::configure(MXS_CONFIG_PARAMETER* params)
{
bool rval = false;
SConfig cnf(new Config(params));
Config cnf(params);
if (handle_max_slaves(cnf, config_get_string(params, "max_slave_connections")))
{
store_config(std::move(cnf));
store_config(cnf);
rval = true;
}