Use shared configurations in readwritesplit
By using a shared pointer instead of a plain object, we can replace the router configuration without it affecting existing sessions. This is a change that is required to enable runtime reconfiguration of readwritesplit.
This commit is contained in:
@ -56,7 +56,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(Config& config, char **options)
|
||||
static bool rwsplit_process_router_options(SConfig config, char **options)
|
||||
{
|
||||
if (options == NULL)
|
||||
{
|
||||
@ -92,51 +92,51 @@ static bool rwsplit_process_router_options(Config& 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
|
||||
{
|
||||
@ -157,7 +157,7 @@ static bool rwsplit_process_router_options(Config& config, char **options)
|
||||
}
|
||||
|
||||
// TODO: Don't process parameters in readwritesplit
|
||||
static bool handle_max_slaves(Config& config, const char *str)
|
||||
static bool handle_max_slaves(SConfig config, const char *str)
|
||||
{
|
||||
bool rval = true;
|
||||
char *endptr;
|
||||
@ -165,13 +165,13 @@ static bool handle_max_slaves(Config& 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
|
||||
{
|
||||
@ -182,7 +182,7 @@ static bool handle_max_slaves(Config& config, const char *str)
|
||||
return rval;
|
||||
}
|
||||
|
||||
RWSplit::RWSplit(SERVICE* service, const Config& config):
|
||||
RWSplit::RWSplit(SERVICE* service, SConfig config):
|
||||
mxs::Router<RWSplit, RWSplitSession>(service),
|
||||
m_service(service),
|
||||
m_config(config)
|
||||
@ -198,8 +198,9 @@ SERVICE* RWSplit::service() const
|
||||
return m_service;
|
||||
}
|
||||
|
||||
const Config& RWSplit::config() const
|
||||
SConfig RWSplit::config() const
|
||||
{
|
||||
ss_dassert(m_config);
|
||||
return m_config;
|
||||
}
|
||||
|
||||
@ -215,9 +216,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));
|
||||
}
|
||||
|
||||
@ -227,8 +228,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)
|
||||
@ -241,15 +242,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)
|
||||
{
|
||||
@ -258,7 +259,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;
|
||||
@ -274,9 +275,8 @@ bool RWSplit::have_enough_servers() const
|
||||
|
||||
RWSplit* RWSplit::create(SERVICE *service, char **options)
|
||||
{
|
||||
|
||||
MXS_CONFIG_PARAMETER* params = service->svc_config_param;
|
||||
Config config(params);
|
||||
SConfig config(new Config(params));
|
||||
|
||||
if (!handle_max_slaves(config, config_get_string(params, "max_slave_connections")) ||
|
||||
(options && !rwsplit_process_router_options(config, options)))
|
||||
@ -285,25 +285,25 @@ RWSplit* RWSplit::create(SERVICE *service, char **options)
|
||||
}
|
||||
|
||||
/** 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);
|
||||
@ -320,40 +320,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();
|
||||
|
||||
dcb_printf(dcb, "\n");
|
||||
dcb_printf(dcb, "\tuse_sql_variables_in: %s\n",
|
||||
mxs_target_to_str(config().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(config().slave_selection_criteria));
|
||||
select_criteria_to_str(cnf->slave_selection_criteria));
|
||||
dcb_printf(dcb, "\tmaster_failure_mode: %s\n",
|
||||
failure_mode_to_str(config().master_failure_mode));
|
||||
failure_mode_to_str(cnf->master_failure_mode));
|
||||
dcb_printf(dcb, "\tmax_slave_replication_lag: %d\n",
|
||||
config().max_slave_replication_lag);
|
||||
cnf->max_slave_replication_lag);
|
||||
dcb_printf(dcb, "\tretry_failed_reads: %s\n",
|
||||
config().retry_failed_reads ? "true" : "false");
|
||||
cnf->retry_failed_reads ? "true" : "false");
|
||||
dcb_printf(dcb, "\tstrict_multi_stmt: %s\n",
|
||||
config().strict_multi_stmt ? "true" : "false");
|
||||
cnf->strict_multi_stmt ? "true" : "false");
|
||||
dcb_printf(dcb, "\tstrict_sp_calls: %s\n",
|
||||
config().strict_sp_calls ? "true" : "false");
|
||||
cnf->strict_sp_calls ? "true" : "false");
|
||||
dcb_printf(dcb, "\tdisable_sescmd_history: %s\n",
|
||||
config().disable_sescmd_history ? "true" : "false");
|
||||
cnf->disable_sescmd_history ? "true" : "false");
|
||||
dcb_printf(dcb, "\tmax_sescmd_history: %lu\n",
|
||||
config().max_sescmd_history);
|
||||
cnf->max_sescmd_history);
|
||||
dcb_printf(dcb, "\tmaster_accept_reads: %s\n",
|
||||
config().master_accept_reads ? "true" : "false");
|
||||
cnf->master_accept_reads ? "true" : "false");
|
||||
dcb_printf(dcb, "\tconnection_keepalive: %d\n",
|
||||
config().connection_keepalive);
|
||||
cnf->connection_keepalive);
|
||||
dcb_printf(dcb, "\tcausal_reads: %s\n",
|
||||
config().causal_reads ? "true" : "false");
|
||||
cnf->causal_reads ? "true" : "false");
|
||||
dcb_printf(dcb, "\tcausal_reads_timeout: %s\n",
|
||||
config().causal_reads_timeout.c_str());
|
||||
cnf->causal_reads_timeout.c_str());
|
||||
dcb_printf(dcb, "\tmaster_reconnection: %s\n",
|
||||
config().master_reconnection ? "true" : "false");
|
||||
cnf->master_reconnection ? "true" : "false");
|
||||
dcb_printf(dcb, "\tdelayed_retry: %s\n",
|
||||
config().delayed_retry ? "true" : "false");
|
||||
cnf->delayed_retry ? "true" : "false");
|
||||
dcb_printf(dcb, "\tdelayed_retry_timeout: %lu\n",
|
||||
config().delayed_retry_timeout);
|
||||
cnf->delayed_retry_timeout);
|
||||
|
||||
dcb_printf(dcb, "\n");
|
||||
|
||||
|
@ -200,6 +200,8 @@ struct Config
|
||||
bool optimistic_trx; /**< Enable optimistic transactions */
|
||||
};
|
||||
|
||||
typedef std::tr1::shared_ptr<Config> SConfig;
|
||||
|
||||
/**
|
||||
* The statistics for this router instance
|
||||
*/
|
||||
@ -226,11 +228,11 @@ class RWSplit: public mxs::Router<RWSplit, RWSplitSession>
|
||||
RWSplit& operator=(const RWSplit&);
|
||||
|
||||
public:
|
||||
RWSplit(SERVICE* service, const Config& config);
|
||||
RWSplit(SERVICE* service, SConfig config);
|
||||
~RWSplit();
|
||||
|
||||
SERVICE* service() const;
|
||||
const Config& config() const;
|
||||
SConfig config() const;
|
||||
Stats& stats();
|
||||
const Stats& stats() const;
|
||||
int max_slave_count() const;
|
||||
@ -298,7 +300,7 @@ public:
|
||||
|
||||
private:
|
||||
SERVICE* m_service; /**< Service where the router belongs*/
|
||||
Config m_config;
|
||||
SConfig m_config;
|
||||
Stats m_stats;
|
||||
};
|
||||
|
||||
|
@ -116,7 +116,7 @@ bool RWSplitSession::handle_target_is_all(route_target_t route_target, GWBUF *qu
|
||||
{
|
||||
// TODO: Append to the already stored session command instead of disabling history
|
||||
MXS_INFO("Large session write, have to disable session command history");
|
||||
m_config.disable_sescmd_history = true;
|
||||
m_config->disable_sescmd_history = true;
|
||||
|
||||
continue_large_session_write(querybuf, qtype);
|
||||
result = true;
|
||||
|
@ -84,7 +84,7 @@ void RWSplitSession::handle_connection_keepalive(SRWBackend& target)
|
||||
ss_dassert(target);
|
||||
ss_debug(int nserv = 0);
|
||||
/** Each heartbeat is 1/10th of a second */
|
||||
int keepalive = m_config.connection_keepalive * 10;
|
||||
int keepalive = m_config->connection_keepalive * 10;
|
||||
|
||||
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
|
||||
{
|
||||
@ -115,7 +115,7 @@ bool RWSplitSession::prepare_target(SRWBackend& target, route_target_t route_tar
|
||||
if (!target->in_use())
|
||||
{
|
||||
ss_dassert(target->can_connect() && can_recover_servers());
|
||||
ss_dassert(!TARGET_IS_MASTER(route_target) || m_config.master_reconnection);
|
||||
ss_dassert(!TARGET_IS_MASTER(route_target) || m_config->master_reconnection);
|
||||
rval = target->connect(m_client->session, &m_sescmd_list);
|
||||
MXS_INFO("Connected to '%s'", target->name());
|
||||
|
||||
@ -166,7 +166,7 @@ bool RWSplitSession::have_connected_slaves() const
|
||||
|
||||
bool RWSplitSession::should_try_trx_on_slave(route_target_t route_target) const
|
||||
{
|
||||
return m_config.optimistic_trx && // Optimistic transactions are enabled
|
||||
return m_config->optimistic_trx && // Optimistic transactions are enabled
|
||||
!is_locked_to_master() && // Not locked to master
|
||||
!m_is_replay_active && // Not replaying a transaction
|
||||
m_otrx_state == OTRX_INACTIVE && // Not yet in optimistic mode
|
||||
@ -260,7 +260,7 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
|
||||
}
|
||||
|
||||
// If delayed query retry is enabled, we need to store the current statement
|
||||
bool store_stmt = m_config.delayed_retry;
|
||||
bool store_stmt = m_config->delayed_retry;
|
||||
|
||||
if (m_qc.large_query())
|
||||
{
|
||||
@ -297,7 +297,7 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
|
||||
{
|
||||
succp = true;
|
||||
|
||||
if (m_config.retry_failed_reads &&
|
||||
if (m_config->retry_failed_reads &&
|
||||
(command == MXS_COM_QUERY || command == MXS_COM_STMT_EXECUTE))
|
||||
{
|
||||
// Only commands that can contain an SQL statement should be stored
|
||||
@ -309,8 +309,8 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
|
||||
{
|
||||
succp = handle_master_is_target(&target);
|
||||
|
||||
if (!m_config.strict_multi_stmt &&
|
||||
!m_config.strict_sp_calls &&
|
||||
if (!m_config->strict_multi_stmt &&
|
||||
!m_config->strict_sp_calls &&
|
||||
m_target_node == m_current_master)
|
||||
{
|
||||
/** Reset the forced node as we're in relaxed multi-statement mode */
|
||||
@ -363,7 +363,7 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
|
||||
}
|
||||
}
|
||||
|
||||
if (succp && m_router->config().connection_keepalive &&
|
||||
if (succp && m_config->connection_keepalive &&
|
||||
(TARGET_IS_SLAVE(route_target) || TARGET_IS_MASTER(route_target)))
|
||||
{
|
||||
handle_connection_keepalive(target);
|
||||
@ -488,7 +488,7 @@ bool RWSplitSession::route_session_write(GWBUF *querybuf, uint8_t command, uint3
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.max_sescmd_history > 0 && m_sescmd_list.size() >= m_config.max_sescmd_history)
|
||||
if (m_config->max_sescmd_history > 0 && m_sescmd_list.size() >= m_config->max_sescmd_history)
|
||||
{
|
||||
static bool warn_history_exceeded = true;
|
||||
if (warn_history_exceeded)
|
||||
@ -500,16 +500,16 @@ bool RWSplitSession::route_session_write(GWBUF *querybuf, uint8_t command, uint3
|
||||
"command history, add `disable_sescmd_history=true` to "
|
||||
"service '%s'. To increase the limit (currently %lu), add "
|
||||
"`max_sescmd_history` to the same service and increase the value.",
|
||||
m_router->service()->name, m_config.max_sescmd_history);
|
||||
m_router->service()->name, m_config->max_sescmd_history);
|
||||
warn_history_exceeded = false;
|
||||
}
|
||||
|
||||
m_config.disable_sescmd_history = true;
|
||||
m_config.max_sescmd_history = 0;
|
||||
m_config->disable_sescmd_history = true;
|
||||
m_config->max_sescmd_history = 0;
|
||||
m_sescmd_list.clear();
|
||||
}
|
||||
|
||||
if (m_config.disable_sescmd_history)
|
||||
if (m_config->disable_sescmd_history)
|
||||
{
|
||||
/** Prune stored responses */
|
||||
ResponseMap::iterator it = m_sescmd_responses.lower_bound(lowest_pos);
|
||||
@ -596,7 +596,7 @@ SRWBackend RWSplitSession::get_slave_backend(int max_rlag)
|
||||
}
|
||||
else if (backend->in_use() || counts.second < m_router->max_slave_count())
|
||||
{
|
||||
if (!m_config.master_accept_reads && rval->is_master())
|
||||
if (!m_config->master_accept_reads && rval->is_master())
|
||||
{
|
||||
// Pick slaves over masters with master_accept_reads=false
|
||||
rval = backend;
|
||||
@ -604,7 +604,7 @@ SRWBackend RWSplitSession::get_slave_backend(int max_rlag)
|
||||
else
|
||||
{
|
||||
// Compare the two servers and pick the best one
|
||||
rval = compare_backends(rval, backend, m_config.slave_selection_criteria);
|
||||
rval = compare_backends(rval, backend, m_config->slave_selection_criteria);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -622,7 +622,7 @@ SRWBackend RWSplitSession::get_master_backend()
|
||||
|
||||
if (master)
|
||||
{
|
||||
if (master->in_use() || (m_config.master_reconnection && master->can_connect()))
|
||||
if (master->in_use() || (m_config->master_reconnection && master->can_connect()))
|
||||
{
|
||||
if (master->is_master())
|
||||
{
|
||||
@ -696,9 +696,9 @@ int RWSplitSession::get_max_replication_lag()
|
||||
int conf_max_rlag;
|
||||
|
||||
/** if there is no configured value, then longest possible int is used */
|
||||
if (m_config.max_slave_replication_lag > 0)
|
||||
if (m_config->max_slave_replication_lag > 0)
|
||||
{
|
||||
conf_max_rlag = m_config.max_slave_replication_lag;
|
||||
conf_max_rlag = m_config->max_slave_replication_lag;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -878,7 +878,7 @@ void RWSplitSession::log_master_routing_failure(bool found,
|
||||
else
|
||||
{
|
||||
/** We never had a master connection, the session must be in read-only mode */
|
||||
if (m_config.master_failure_mode != RW_FAIL_INSTANTLY)
|
||||
if (m_config->master_failure_mode != RW_FAIL_INSTANTLY)
|
||||
{
|
||||
sprintf(errmsg, "Session is in read-only mode because it was created "
|
||||
"when no master was available");
|
||||
@ -899,7 +899,7 @@ void RWSplitSession::log_master_routing_failure(bool found,
|
||||
|
||||
bool RWSplitSession::should_replace_master(SRWBackend& target)
|
||||
{
|
||||
return m_config.master_reconnection &&
|
||||
return m_config->master_reconnection &&
|
||||
// We have a target server and it's not the current master
|
||||
target && target != m_current_master &&
|
||||
// We are not inside a transaction (also checks for autocommit=1)
|
||||
@ -946,7 +946,7 @@ bool RWSplitSession::handle_master_is_target(SRWBackend* dest)
|
||||
{
|
||||
succp = false;
|
||||
/** The original master is not available, we can't route the write */
|
||||
if (m_config.master_failure_mode == RW_ERROR_ON_WRITE)
|
||||
if (m_config->master_failure_mode == RW_ERROR_ON_WRITE)
|
||||
{
|
||||
succp = send_readonly_error(m_client);
|
||||
|
||||
@ -955,8 +955,8 @@ bool RWSplitSession::handle_master_is_target(SRWBackend* dest)
|
||||
m_current_master->close();
|
||||
}
|
||||
}
|
||||
else if (!m_config.delayed_retry ||
|
||||
m_retry_duration >= m_config.delayed_retry_timeout)
|
||||
else if (!m_config->delayed_retry ||
|
||||
m_retry_duration >= m_config->delayed_retry_timeout)
|
||||
{
|
||||
// Cannot retry the query, log a message that routing has failed
|
||||
log_master_routing_failure(succp, m_current_master, target);
|
||||
@ -993,7 +993,7 @@ GWBUF* RWSplitSession::add_prefix_wait_gtid(SERVER *server, GWBUF *origin)
|
||||
GWBUF* rval = origin;
|
||||
const char* wait_func = (server->server_type == SERVER_TYPE_MARIADB) ?
|
||||
MARIADB_WAIT_GTID_FUNC : MYSQL_WAIT_GTID_FUNC;
|
||||
const char *gtid_wait_timeout = m_router->config().causal_reads_timeout.c_str();
|
||||
const char *gtid_wait_timeout = m_config->causal_reads_timeout.c_str();
|
||||
const char *gtid_position = m_gtid_pos.c_str();
|
||||
|
||||
/* Create a new buffer to store prefix sql */
|
||||
@ -1051,7 +1051,7 @@ bool RWSplitSession::handle_got_target(GWBUF* querybuf, SRWBackend& target, bool
|
||||
uint8_t cmd = mxs_mysql_get_command(querybuf);
|
||||
GWBUF *send_buf = gwbuf_clone(querybuf);
|
||||
|
||||
if (cmd == COM_QUERY && m_router->config().causal_reads && !m_gtid_pos .empty())
|
||||
if (cmd == COM_QUERY && m_config->causal_reads && !m_gtid_pos .empty())
|
||||
{
|
||||
send_buf = add_prefix_wait_gtid(target->server(), send_buf);
|
||||
m_wait_gtid = WAITING_FOR_HEADER;
|
||||
|
@ -301,15 +301,16 @@ bool RWSplit::select_connect_backend_servers(MXS_SESSION *session,
|
||||
connection_type type)
|
||||
{
|
||||
SRWBackend master = get_root_master(backends);
|
||||
SConfig cnf(config());
|
||||
|
||||
if (!master && config().master_failure_mode == RW_FAIL_INSTANTLY)
|
||||
if (!master && cnf->master_failure_mode == RW_FAIL_INSTANTLY)
|
||||
{
|
||||
MXS_ERROR("Couldn't find suitable Master from %lu candidates.", backends.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Check slave selection criteria and set compare function */
|
||||
select_criteria_t select_criteria = config().slave_selection_criteria;
|
||||
select_criteria_t select_criteria = cnf->slave_selection_criteria;
|
||||
auto cmpfun = criteria_cmpfun[select_criteria];
|
||||
ss_dassert(cmpfun);
|
||||
|
||||
|
@ -38,17 +38,17 @@ RWSplitSession::RWSplitSession(RWSplit* instance, MXS_SESSION* session,
|
||||
m_gtid_pos(""),
|
||||
m_wait_gtid(NONE),
|
||||
m_next_seq(0),
|
||||
m_qc(this, session, instance->config().use_sql_variables_in),
|
||||
m_qc(this, session, m_config->use_sql_variables_in),
|
||||
m_retry_duration(0),
|
||||
m_is_replay_active(false),
|
||||
m_can_replay_trx(true)
|
||||
{
|
||||
if (m_config.rw_max_slave_conn_percent)
|
||||
if (m_config->rw_max_slave_conn_percent)
|
||||
{
|
||||
int n_conn = 0;
|
||||
double pct = (double)m_config.rw_max_slave_conn_percent / 100.0;
|
||||
double pct = (double)m_config->rw_max_slave_conn_percent / 100.0;
|
||||
n_conn = MXS_MAX(floor((double)m_nbackends * pct), 1);
|
||||
m_config.max_slave_connections = n_conn;
|
||||
m_config->max_slave_connections = n_conn;
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +350,7 @@ static void log_unexpected_response(SRWBackend& backend, GWBUF* buffer, GWBUF* c
|
||||
|
||||
GWBUF* RWSplitSession::handle_causal_read_reply(GWBUF *writebuf, SRWBackend& backend)
|
||||
{
|
||||
if (m_config.causal_reads)
|
||||
if (m_config->causal_reads)
|
||||
{
|
||||
if (GWBUF_IS_REPLY_OK(writebuf) && backend == m_current_master)
|
||||
{
|
||||
@ -473,7 +473,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
|
||||
poll_fake_hangup_event(backend_dcb);
|
||||
}
|
||||
}
|
||||
else if (m_config.transaction_replay && m_can_replay_trx &&
|
||||
else if (m_config->transaction_replay && m_can_replay_trx &&
|
||||
session_trx_is_active(m_client->session))
|
||||
{
|
||||
if (!backend->has_session_commands())
|
||||
@ -491,7 +491,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
|
||||
|
||||
size_t size{m_trx.size() + m_current_query.length()};
|
||||
// A transaction is open and it is eligible for replaying
|
||||
if (size < m_config.trx_max_size)
|
||||
if (size < m_config->trx_max_size)
|
||||
{
|
||||
/** Transaction size is OK, store the statement for replaying and
|
||||
* update the checksum of the result */
|
||||
@ -524,7 +524,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
|
||||
ss_dassert(backend->get_reply_state() == REPLY_STATE_DONE);
|
||||
MXS_INFO("Reply complete, last reply from %s", backend->name());
|
||||
|
||||
if (m_config.causal_reads)
|
||||
if (m_config->causal_reads)
|
||||
{
|
||||
// The reply should never be complete while we are still waiting for the header.
|
||||
ss_dassert(m_wait_gtid != WAITING_FOR_HEADER);
|
||||
@ -560,7 +560,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
|
||||
}
|
||||
else if (m_is_replay_active)
|
||||
{
|
||||
ss_dassert(m_config.transaction_replay);
|
||||
ss_dassert(m_config->transaction_replay);
|
||||
handle_trx_replay();
|
||||
|
||||
/**
|
||||
@ -582,7 +582,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (m_config.transaction_replay && session_trx_is_ending(m_client->session))
|
||||
else if (m_config->transaction_replay && session_trx_is_ending(m_client->session))
|
||||
{
|
||||
m_trx.close();
|
||||
m_can_replay_trx = true;
|
||||
@ -638,7 +638,7 @@ bool RWSplitSession::start_trx_replay()
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (!m_is_replay_active && m_config.transaction_replay && m_can_replay_trx)
|
||||
if (!m_is_replay_active && m_config->transaction_replay && m_can_replay_trx)
|
||||
{
|
||||
if (m_trx.have_stmts() || m_current_query.get())
|
||||
{
|
||||
@ -736,7 +736,7 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
|
||||
* can't be sure whether it was executed or not. In this
|
||||
* case the safest thing to do is to close the client
|
||||
* connection. */
|
||||
if (m_config.master_failure_mode != RW_FAIL_INSTANTLY)
|
||||
if (m_config->master_failure_mode != RW_FAIL_INSTANTLY)
|
||||
{
|
||||
can_continue = true;
|
||||
}
|
||||
@ -752,7 +752,7 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
|
||||
can_continue = true;
|
||||
retry_query(m_current_query.release());
|
||||
}
|
||||
else if (m_config.master_failure_mode == RW_ERROR_ON_WRITE)
|
||||
else if (m_config->master_failure_mode == RW_ERROR_ON_WRITE)
|
||||
{
|
||||
/** In error_on_write mode, the session can continue even
|
||||
* if the master is lost. Send a read-only error to
|
||||
@ -865,7 +865,7 @@ bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg
|
||||
*/
|
||||
GWBUF *stored = m_current_query.release();
|
||||
|
||||
if (stored && m_config.retry_failed_reads)
|
||||
if (stored && m_config->retry_failed_reads)
|
||||
{
|
||||
MXS_INFO("Re-routing failed read after server '%s' failed", backend->name());
|
||||
retry_query(stored, 0);
|
||||
@ -905,7 +905,7 @@ bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg
|
||||
* Try to get replacement slave or at least the minimum
|
||||
* number of slave connections for router session.
|
||||
*/
|
||||
if (m_recv_sescmd > 0 && m_config.disable_sescmd_history)
|
||||
if (m_recv_sescmd > 0 && m_config->disable_sescmd_history)
|
||||
{
|
||||
succp = m_router->have_enough_servers();
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
mxs::SRWBackend m_current_master; /**< Current master server */
|
||||
mxs::SRWBackend m_target_node; /**< The currently locked target node */
|
||||
mxs::SRWBackend m_prev_target; /**< The previous target where a query was sent */
|
||||
Config m_config; /**< copied config info from router instance */
|
||||
SConfig m_config; /**< Configuration for this session */
|
||||
int m_nbackends; /**< Number of backend servers (obsolete) */
|
||||
DCB* m_client; /**< The client DCB */
|
||||
uint64_t m_sescmd_count; /**< Number of executed session commands */
|
||||
@ -249,14 +249,14 @@ private:
|
||||
*
|
||||
* @see handle_trx_replay
|
||||
*/
|
||||
return m_config.delayed_retry &&
|
||||
m_retry_duration < m_config.delayed_retry_timeout &&
|
||||
return m_config->delayed_retry &&
|
||||
m_retry_duration < m_config->delayed_retry_timeout &&
|
||||
!session_trx_is_active(m_client->session);
|
||||
}
|
||||
|
||||
inline bool can_recover_servers() const
|
||||
{
|
||||
return !m_config.disable_sescmd_history || m_recv_sescmd == 0;
|
||||
return !m_config->disable_sescmd_history || m_recv_sescmd == 0;
|
||||
}
|
||||
|
||||
inline bool is_large_query(GWBUF* buf)
|
||||
|
Reference in New Issue
Block a user