Uncrustify maxscale

See script directory for method. The script to run in the top level
MaxScale directory is called maxscale-uncrustify.sh, which uses
another script, list-src, from the same directory (so you need to set
your PATH). The uncrustify version was 0.66.
This commit is contained in:
Niclas Antti
2018-09-09 22:26:19 +03:00
parent fa7ec95069
commit c447e5cf15
849 changed files with 35002 additions and 27238 deletions

View File

@ -52,10 +52,10 @@ using namespace maxscale;
#define MAX_SLAVE_COUNT "255"
// TODO: Don't process parameters in readwritesplit
static bool handle_max_slaves(Config& config, const char *str)
static bool handle_max_slaves(Config& config, const char* str)
{
bool rval = true;
char *endptr;
char* endptr;
int val = strtol(str, &endptr, 10);
if (*endptr == '%' && *(endptr + 1) == '\0')
@ -77,10 +77,10 @@ static bool handle_max_slaves(Config& config, const char *str)
return rval;
}
RWSplit::RWSplit(SERVICE* service, const Config& config):
mxs::Router<RWSplit, RWSplitSession>(service),
m_service(service),
m_config(config)
RWSplit::RWSplit(SERVICE* service, const Config& config)
: mxs::Router<RWSplit, RWSplitSession>(service)
, m_service(service)
, m_config(config)
{
}
@ -110,9 +110,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));
}
@ -132,7 +132,10 @@ bool RWSplit::have_enough_servers() const
{
MXS_ERROR("Unable to start %s service. There are "
"too few backend servers available. Found %d "
"when %d is required.", m_service->name, router_nsrv, min_nsrv);
"when %d is required.",
m_service->name,
router_nsrv,
min_nsrv);
}
else
{
@ -144,7 +147,9 @@ bool RWSplit::have_enough_servers() const
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)
{
@ -152,8 +157,10 @@ bool RWSplit::have_enough_servers() const
MXS_ERROR("Unable to start %s service. There are "
"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);
"would be required.",
m_service->name,
m_config->rw_max_slave_conn_percent,
dbgpct);
}
}
succp = false;
@ -166,14 +173,16 @@ static void log_router_options_not_supported(SERVICE* service, MXS_CONFIG_PARAME
{
std::stringstream ss;
for (const auto& a: mxs::strtok(p->value, ", \t"))
for (const auto& a : mxs::strtok(p->value, ", \t"))
{
ss << a << "\n";
}
MXS_ERROR("`router_options` is no longer supported in readwritesplit. "
"To define the router options as parameters, add the following "
"lines to service '%s':\n\n%s\n", service->name, ss.str().c_str());
"lines to service '%s':\n\n%s\n",
service->name,
ss.str().c_str());
}
/**
@ -181,7 +190,7 @@ static void log_router_options_not_supported(SERVICE* service, MXS_CONFIG_PARAME
*/
RWSplit* RWSplit::create(SERVICE *service, MXS_CONFIG_PARAMETER* params)
RWSplit* RWSplit::create(SERVICE* service, MXS_CONFIG_PARAMETER* params)
{
if (MXS_CONFIG_PARAMETER* p = config_get_param(params, CN_ROUTER_OPTIONS))
{
@ -218,54 +227,70 @@ RWSplit* RWSplit::create(SERVICE *service, MXS_CONFIG_PARAMETER* params)
config.master_reconnection = true;
}
return new (std::nothrow) RWSplit(service, config);
return new( std::nothrow) RWSplit(service, config);
}
RWSplitSession* RWSplit::newSession(MXS_SESSION *session)
RWSplitSession* RWSplit::newSession(MXS_SESSION* session)
{
RWSplitSession* rses = NULL;
MXS_EXCEPTION_GUARD(rses = RWSplitSession::create(this, session));
return rses;
}
void RWSplit::diagnostics(DCB *dcb)
void RWSplit::diagnostics(DCB* dcb)
{
const char *weightby = serviceGetWeightingParameter(service());
const char* weightby = serviceGetWeightingParameter(service());
double master_pct = 0.0, slave_pct = 0.0, all_pct = 0.0;
Config cnf = config();
dcb_printf(dcb, "\n");
dcb_printf(dcb, "\tuse_sql_variables_in: %s\n",
dcb_printf(dcb,
"\tuse_sql_variables_in: %s\n",
mxs_target_to_str(cnf.use_sql_variables_in));
dcb_printf(dcb, "\tslave_selection_criteria: %s\n",
dcb_printf(dcb,
"\tslave_selection_criteria: %s\n",
select_criteria_to_str(cnf.slave_selection_criteria));
dcb_printf(dcb, "\tmaster_failure_mode: %s\n",
dcb_printf(dcb,
"\tmaster_failure_mode: %s\n",
failure_mode_to_str(cnf.master_failure_mode));
dcb_printf(dcb, "\tmax_slave_replication_lag: %d\n",
dcb_printf(dcb,
"\tmax_slave_replication_lag: %d\n",
cnf.max_slave_replication_lag);
dcb_printf(dcb, "\tretry_failed_reads: %s\n",
dcb_printf(dcb,
"\tretry_failed_reads: %s\n",
cnf.retry_failed_reads ? "true" : "false");
dcb_printf(dcb, "\tstrict_multi_stmt: %s\n",
dcb_printf(dcb,
"\tstrict_multi_stmt: %s\n",
cnf.strict_multi_stmt ? "true" : "false");
dcb_printf(dcb, "\tstrict_sp_calls: %s\n",
dcb_printf(dcb,
"\tstrict_sp_calls: %s\n",
cnf.strict_sp_calls ? "true" : "false");
dcb_printf(dcb, "\tdisable_sescmd_history: %s\n",
dcb_printf(dcb,
"\tdisable_sescmd_history: %s\n",
cnf.disable_sescmd_history ? "true" : "false");
dcb_printf(dcb, "\tmax_sescmd_history: %lu\n",
dcb_printf(dcb,
"\tmax_sescmd_history: %lu\n",
cnf.max_sescmd_history);
dcb_printf(dcb, "\tmaster_accept_reads: %s\n",
dcb_printf(dcb,
"\tmaster_accept_reads: %s\n",
cnf.master_accept_reads ? "true" : "false");
dcb_printf(dcb, "\tconnection_keepalive: %d\n",
dcb_printf(dcb,
"\tconnection_keepalive: %d\n",
cnf.connection_keepalive);
dcb_printf(dcb, "\tcausal_reads: %s\n",
dcb_printf(dcb,
"\tcausal_reads: %s\n",
cnf.causal_reads ? "true" : "false");
dcb_printf(dcb, "\tcausal_reads_timeout: %s\n",
dcb_printf(dcb,
"\tcausal_reads_timeout: %s\n",
cnf.causal_reads_timeout.c_str());
dcb_printf(dcb, "\tmaster_reconnection: %s\n",
dcb_printf(dcb,
"\tmaster_reconnection: %s\n",
cnf.master_reconnection ? "true" : "false");
dcb_printf(dcb, "\tdelayed_retry: %s\n",
dcb_printf(dcb,
"\tdelayed_retry: %s\n",
cnf.delayed_retry ? "true" : "false");
dcb_printf(dcb, "\tdelayed_retry_timeout: %lu\n",
dcb_printf(dcb,
"\tdelayed_retry_timeout: %lu\n",
cnf.delayed_retry_timeout);
dcb_printf(dcb, "\n");
@ -277,38 +302,55 @@ void RWSplit::diagnostics(DCB *dcb)
all_pct = ((double)stats().n_all / (double)stats().n_queries) * 100.0;
}
dcb_printf(dcb, "\tNumber of router sessions: %" PRIu64 "\n",
dcb_printf(dcb,
"\tNumber of router sessions: %" PRIu64 "\n",
stats().n_sessions);
dcb_printf(dcb, "\tCurrent no. of router sessions: %d\n",
dcb_printf(dcb,
"\tCurrent no. of router sessions: %d\n",
service()->stats.n_current);
dcb_printf(dcb, "\tNumber of queries forwarded: %" PRIu64 "\n",
dcb_printf(dcb,
"\tNumber of queries forwarded: %" PRIu64 "\n",
stats().n_queries);
dcb_printf(dcb, "\tNumber of queries forwarded to master: %" PRIu64 " (%.2f%%)\n",
stats().n_master, master_pct);
dcb_printf(dcb, "\tNumber of queries forwarded to slave: %" PRIu64 " (%.2f%%)\n",
stats().n_slave, slave_pct);
dcb_printf(dcb, "\tNumber of queries forwarded to all: %" PRIu64 " (%.2f%%)\n",
stats().n_all, all_pct);
dcb_printf(dcb, "\tNumber of read-write transactions: %" PRIu64 "\n",
dcb_printf(dcb,
"\tNumber of queries forwarded to master: %" PRIu64 " (%.2f%%)\n",
stats().n_master,
master_pct);
dcb_printf(dcb,
"\tNumber of queries forwarded to slave: %" PRIu64 " (%.2f%%)\n",
stats().n_slave,
slave_pct);
dcb_printf(dcb,
"\tNumber of queries forwarded to all: %" PRIu64 " (%.2f%%)\n",
stats().n_all,
all_pct);
dcb_printf(dcb,
"\tNumber of read-write transactions: %" PRIu64 "\n",
stats().n_rw_trx);
dcb_printf(dcb, "\tNumber of read-only transactions: %" PRIu64 "\n",
dcb_printf(dcb,
"\tNumber of read-only transactions: %" PRIu64 "\n",
stats().n_ro_trx);
dcb_printf(dcb, "\tNumber of replayed transactions: %" PRIu64 "\n",
dcb_printf(dcb,
"\tNumber of replayed transactions: %" PRIu64 "\n",
stats().n_trx_replay);
if (*weightby)
{
dcb_printf(dcb, "\tConnection distribution based on %s "
dcb_printf(dcb,
"\tConnection distribution based on %s "
"server parameter.\n",
weightby);
dcb_printf(dcb, "\t\tServer Target %% Connections "
dcb_printf(dcb,
"\t\tServer Target %% Connections "
"Operations\n");
dcb_printf(dcb, "\t\t Global Router\n");
for (SERVER_REF *ref = service()->dbref; ref; ref = ref->next)
for (SERVER_REF* ref = service()->dbref; ref; ref = ref->next)
{
dcb_printf(dcb, "\t\t%-20s %3.1f%% %-6d %-6d %d\n",
ref->server->name, (1.0 - ref->inv_weight) * 100,
ref->server->stats.n_current, ref->connections,
dcb_printf(dcb,
"\t\t%-20s %3.1f%% %-6d %-6d %d\n",
ref->server->name,
(1.0 - ref->inv_weight) * 100,
ref->server->stats.n_current,
ref->connections,
ref->server->stats.n_current_ops);
}
}
@ -328,7 +370,7 @@ json_t* RWSplit::diagnostics_json() const
json_object_set_new(rval, "ro_transactions", json_integer(stats().n_ro_trx));
json_object_set_new(rval, "replayed_transactions", json_integer(stats().n_trx_replay));
const char *weightby = serviceGetWeightingParameter(service());
const char* weightby = serviceGetWeightingParameter(service());
if (*weightby)
{
@ -340,9 +382,9 @@ json_t* RWSplit::diagnostics_json() const
uint64_t RWSplit::getCapabilities()
{
return RCAP_TYPE_STMT_INPUT | RCAP_TYPE_TRANSACTION_TRACKING |
RCAP_TYPE_PACKET_OUTPUT | RCAP_TYPE_SESSION_STATE_TRACKING |
RCAP_TYPE_RUNTIME_CONFIG;
return RCAP_TYPE_STMT_INPUT | RCAP_TYPE_TRANSACTION_TRACKING
| RCAP_TYPE_PACKET_OUTPUT | RCAP_TYPE_SESSION_STATE_TRACKING
| RCAP_TYPE_RUNTIME_CONFIG;
}
bool RWSplit::configure(MXS_CONFIG_PARAMETER* params)
@ -364,21 +406,22 @@ bool RWSplit::configure(MXS_CONFIG_PARAMETER* params)
* the structure that is referred to as the "module object". This is a
* structure with the set of external entry points for this module.
*/
extern "C" MXS_MODULE *MXS_CREATE_MODULE()
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
{
static MXS_MODULE info =
{
MXS_MODULE_API_ROUTER, MXS_MODULE_GA, MXS_ROUTER_VERSION,
MXS_MODULE_API_ROUTER, MXS_MODULE_GA,
MXS_ROUTER_VERSION,
"A Read/Write splitting router for enhancement read scalability",
"V1.1.0",
RCAP_TYPE_STMT_INPUT | RCAP_TYPE_TRANSACTION_TRACKING |
RCAP_TYPE_PACKET_OUTPUT | RCAP_TYPE_SESSION_STATE_TRACKING |
RCAP_TYPE_RUNTIME_CONFIG,
RCAP_TYPE_STMT_INPUT | RCAP_TYPE_TRANSACTION_TRACKING
| RCAP_TYPE_PACKET_OUTPUT | RCAP_TYPE_SESSION_STATE_TRACKING
| RCAP_TYPE_RUNTIME_CONFIG,
&RWSplit::s_object,
NULL, /* Process init. */
NULL, /* Process finish. */
NULL, /* Thread init. */
NULL, /* Thread finish. */
NULL, /* Process init. */
NULL, /* Process finish. */
NULL, /* Thread init. */
NULL, /* Thread finish. */
{
{
"use_sql_variables_in",
@ -401,23 +444,40 @@ extern "C" MXS_MODULE *MXS_CREATE_MODULE()
MXS_MODULE_OPT_NONE,
master_failure_mode_values
},
{"max_slave_replication_lag", MXS_MODULE_PARAM_INT, "-1"},
{"max_slave_connections", MXS_MODULE_PARAM_STRING, MAX_SLAVE_COUNT},
{"retry_failed_reads", MXS_MODULE_PARAM_BOOL, "true"},
{"disable_sescmd_history", MXS_MODULE_PARAM_BOOL, "false"},
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT, "50"},
{"strict_multi_stmt", MXS_MODULE_PARAM_BOOL, "false"},
{"strict_sp_calls", MXS_MODULE_PARAM_BOOL, "false"},
{"master_accept_reads", MXS_MODULE_PARAM_BOOL, "false"},
{"connection_keepalive", MXS_MODULE_PARAM_COUNT, "0"},
{"causal_reads", MXS_MODULE_PARAM_BOOL, "false"},
{"causal_reads_timeout", MXS_MODULE_PARAM_STRING, "120"},
{"master_reconnection", MXS_MODULE_PARAM_BOOL, "false"},
{"delayed_retry", MXS_MODULE_PARAM_BOOL, "false"},
{"delayed_retry_timeout", MXS_MODULE_PARAM_COUNT, "10"},
{"transaction_replay", MXS_MODULE_PARAM_BOOL, "false"},
{"transaction_replay_max_size", MXS_MODULE_PARAM_SIZE, "1Mi"},
{"optimistic_trx", MXS_MODULE_PARAM_BOOL, "false"},
{"max_slave_replication_lag", MXS_MODULE_PARAM_INT,
"-1" },
{"max_slave_connections", MXS_MODULE_PARAM_STRING,
MAX_SLAVE_COUNT },
{"retry_failed_reads", MXS_MODULE_PARAM_BOOL,
"true" },
{"disable_sescmd_history", MXS_MODULE_PARAM_BOOL,
"false" },
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT,
"50" },
{"strict_multi_stmt", MXS_MODULE_PARAM_BOOL,
"false" },
{"strict_sp_calls", MXS_MODULE_PARAM_BOOL,
"false" },
{"master_accept_reads", MXS_MODULE_PARAM_BOOL,
"false" },
{"connection_keepalive", MXS_MODULE_PARAM_COUNT,
"0" },
{"causal_reads", MXS_MODULE_PARAM_BOOL,
"false" },
{"causal_reads_timeout", MXS_MODULE_PARAM_STRING,
"120" },
{"master_reconnection", MXS_MODULE_PARAM_BOOL,
"false" },
{"delayed_retry", MXS_MODULE_PARAM_BOOL,
"false" },
{"delayed_retry_timeout", MXS_MODULE_PARAM_COUNT,
"10" },
{"transaction_replay", MXS_MODULE_PARAM_BOOL,
"false" },
{"transaction_replay_max_size", MXS_MODULE_PARAM_SIZE,
"1Mi" },
{"optimistic_trx", MXS_MODULE_PARAM_BOOL,
"false" },
{MXS_END_MODULE_PARAMS}
}
};

View File

@ -10,7 +10,7 @@
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#pragma once
/**
* @file Readwritesplit common header
@ -42,7 +42,7 @@ enum backend_type_t
{
BE_UNDEFINED = -1,
BE_MASTER,
BE_JOINED = BE_MASTER,
BE_JOINED = BE_MASTER,
BE_SLAVE,
BE_COUNT
};
@ -84,7 +84,7 @@ enum failure_mode
*/
static const MXS_ENUM_VALUE use_sql_variables_in_values[] =
{
{"all", TYPE_ALL},
{"all", TYPE_ALL },
{"master", TYPE_MASTER},
{NULL}
};
@ -93,80 +93,81 @@ static const MXS_ENUM_VALUE slave_selection_criteria_values[] =
{
{"LEAST_GLOBAL_CONNECTIONS", LEAST_GLOBAL_CONNECTIONS},
{"LEAST_ROUTER_CONNECTIONS", LEAST_ROUTER_CONNECTIONS},
{"LEAST_BEHIND_MASTER", LEAST_BEHIND_MASTER},
{"LEAST_BEHIND_MASTER", LEAST_BEHIND_MASTER },
{"LEAST_CURRENT_OPERATIONS", LEAST_CURRENT_OPERATIONS},
{"LOWEST_RESPONSE_TIME", LOWEST_RESPONSE_TIME},
{"LOWEST_RESPONSE_TIME", LOWEST_RESPONSE_TIME },
{NULL}
};
static const MXS_ENUM_VALUE master_failure_mode_values[] =
{
{"fail_instantly", RW_FAIL_INSTANTLY},
{"fail_on_write", RW_FAIL_ON_WRITE},
{"fail_on_write", RW_FAIL_ON_WRITE },
{"error_on_write", RW_ERROR_ON_WRITE},
{NULL}
};
#define BREF_IS_NOT_USED(s) ((s)->bref_state & ~BREF_IN_USE)
#define BREF_IS_IN_USE(s) ((s)->bref_state & BREF_IN_USE)
#define BREF_IS_WAITING_RESULT(s) ((s)->bref_num_result_wait > 0)
#define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE)
#define BREF_IS_CLOSED(s) ((s)->bref_state & BREF_CLOSED)
#define BREF_HAS_FAILED(s) ((s)->bref_state & BREF_FATAL_FAILURE)
#define BREF_IS_NOT_USED(s) ((s)->bref_state & ~BREF_IN_USE)
#define BREF_IS_IN_USE(s) ((s)->bref_state & BREF_IN_USE)
#define BREF_IS_WAITING_RESULT(s) ((s)->bref_num_result_wait > 0)
#define BREF_IS_QUERY_ACTIVE(s) ((s)->bref_state & BREF_QUERY_ACTIVE)
#define BREF_IS_CLOSED(s) ((s)->bref_state & BREF_CLOSED)
#define BREF_HAS_FAILED(s) ((s)->bref_state & BREF_FATAL_FAILURE)
/** default values for rwsplit configuration parameters */
#define CONFIG_MAX_SLAVE_CONN 1
#define CONFIG_MAX_SLAVE_RLAG -1 /**< not used */
#define CONFIG_MAX_SLAVE_CONN 1
#define CONFIG_MAX_SLAVE_RLAG -1 /**< not used */
#define CONFIG_SQL_VARIABLES_IN TYPE_ALL
#define BACKEND_TYPE(b) (server_is_master((b)->backend_server) ? BE_MASTER : \
(server_is_slave((b)->backend_server) ? BE_SLAVE : BE_UNDEFINED));
#define BACKEND_TYPE(b) \
(server_is_master((b)->backend_server) ? BE_MASTER \
: (server_is_slave((b)->backend_server) ? BE_SLAVE : BE_UNDEFINED));
#define MARIADB_WAIT_GTID_FUNC "MASTER_GTID_WAIT"
#define MYSQL_WAIT_GTID_FUNC "WAIT_FOR_EXECUTED_GTID_SET"
static const char gtid_wait_stmt[] =
"SET @maxscale_secret_variable=(SELECT CASE WHEN %s('%s', %s) = 0 "
"THEN 1 ELSE (SELECT 1 FROM INFORMATION_SCHEMA.ENGINES) END);";
static const char gtid_wait_stmt[]
= "SET @maxscale_secret_variable=(SELECT CASE WHEN %s('%s', %s) = 0 "
"THEN 1 ELSE (SELECT 1 FROM INFORMATION_SCHEMA.ENGINES) END);";
/** Function that returns a "score" for a server to enable comparison.
* Smaller numbers are better.
*/
using SRWBackendVector = std::vector<mxs::SRWBackend*>;
using BackendSelectFunction = std::function
<SRWBackendVector::const_iterator (const SRWBackendVector& sBackends)>;
<SRWBackendVector::const_iterator (const SRWBackendVector& sBackends)>;
BackendSelectFunction get_backend_select_function(select_criteria_t);
struct Config
{
Config(MXS_CONFIG_PARAMETER* params):
slave_selection_criteria(
Config(MXS_CONFIG_PARAMETER* params)
: slave_selection_criteria(
(select_criteria_t)config_get_enum(
params, "slave_selection_criteria", slave_selection_criteria_values)),
backend_select_fct(get_backend_select_function(slave_selection_criteria)),
use_sql_variables_in(
params, "slave_selection_criteria", slave_selection_criteria_values))
, backend_select_fct(get_backend_select_function(slave_selection_criteria))
, use_sql_variables_in(
(mxs_target_t)config_get_enum(
params, "use_sql_variables_in", use_sql_variables_in_values)),
master_failure_mode(
params, "use_sql_variables_in", use_sql_variables_in_values))
, master_failure_mode(
(enum failure_mode)config_get_enum(
params, "master_failure_mode", master_failure_mode_values)),
max_sescmd_history(config_get_integer(params, "max_sescmd_history")),
disable_sescmd_history(config_get_bool(params, "disable_sescmd_history")),
master_accept_reads(config_get_bool(params, "master_accept_reads")),
strict_multi_stmt(config_get_bool(params, "strict_multi_stmt")),
strict_sp_calls(config_get_bool(params, "strict_sp_calls")),
retry_failed_reads(config_get_bool(params, "retry_failed_reads")),
connection_keepalive(config_get_integer(params, "connection_keepalive")),
max_slave_replication_lag(config_get_integer(params, "max_slave_replication_lag")),
rw_max_slave_conn_percent(0),
max_slave_connections(0),
causal_reads(config_get_bool(params, "causal_reads")),
causal_reads_timeout(config_get_string(params, "causal_reads_timeout")),
master_reconnection(config_get_bool(params, "master_reconnection")),
delayed_retry(config_get_bool(params, "delayed_retry")),
delayed_retry_timeout(config_get_integer(params, "delayed_retry_timeout")),
transaction_replay(config_get_bool(params, "transaction_replay")),
trx_max_size(config_get_size(params, "transaction_replay_max_size")),
optimistic_trx(config_get_bool(params, "optimistic_trx"))
params, "master_failure_mode", master_failure_mode_values))
, max_sescmd_history(config_get_integer(params, "max_sescmd_history"))
, disable_sescmd_history(config_get_bool(params, "disable_sescmd_history"))
, master_accept_reads(config_get_bool(params, "master_accept_reads"))
, strict_multi_stmt(config_get_bool(params, "strict_multi_stmt"))
, strict_sp_calls(config_get_bool(params, "strict_sp_calls"))
, retry_failed_reads(config_get_bool(params, "retry_failed_reads"))
, connection_keepalive(config_get_integer(params, "connection_keepalive"))
, max_slave_replication_lag(config_get_integer(params, "max_slave_replication_lag"))
, rw_max_slave_conn_percent(0)
, max_slave_connections(0)
, causal_reads(config_get_bool(params, "causal_reads"))
, causal_reads_timeout(config_get_string(params, "causal_reads_timeout"))
, master_reconnection(config_get_bool(params, "master_reconnection"))
, delayed_retry(config_get_bool(params, "delayed_retry"))
, delayed_retry_timeout(config_get_integer(params, "delayed_retry_timeout"))
, transaction_replay(config_get_bool(params, "transaction_replay"))
, trx_max_size(config_get_size(params, "transaction_replay_max_size"))
, optimistic_trx(config_get_bool(params, "optimistic_trx"))
{
if (causal_reads)
{
@ -174,33 +175,33 @@ struct Config
}
}
select_criteria_t slave_selection_criteria; /**< The slave selection criteria */
BackendSelectFunction backend_select_fct;
select_criteria_t slave_selection_criteria; /**< The slave selection criteria */
BackendSelectFunction backend_select_fct;
mxs_target_t use_sql_variables_in; /**< Whether to send user variables to
* master or all nodes */
failure_mode master_failure_mode; /**< Master server failure handling mode */
uint64_t max_sescmd_history; /**< Maximum amount of session commands to store */
bool disable_sescmd_history; /**< Disable session command history */
bool master_accept_reads; /**< Use master for reads */
bool strict_multi_stmt; /**< Force non-multistatement queries to be routed to
* the master after a multistatement query. */
bool strict_sp_calls; /**< Lock session to master after an SP call */
bool retry_failed_reads; /**< Retry failed reads on other servers */
int connection_keepalive; /**< Send pings to servers that have been idle
* for too long */
int max_slave_replication_lag; /**< Maximum replication lag */
int rw_max_slave_conn_percent; /**< Maximum percentage of slaves to use for
* each connection*/
int max_slave_connections; /**< Maximum number of slaves for each connection*/
bool causal_reads; /**< Enable causual read */
std::string causal_reads_timeout; /**< Timeout, second parameter of function master_wait_gtid */
bool master_reconnection; /**< Allow changes in master server */
bool delayed_retry; /**< Delay routing if no target found */
uint64_t delayed_retry_timeout; /**< How long to delay until an error is returned */
bool transaction_replay; /**< Replay failed transactions */
size_t trx_max_size; /**< Max transaction size for replaying */
bool optimistic_trx; /**< Enable optimistic transactions */
mxs_target_t use_sql_variables_in; /**< Whether to send user variables to
* master or all nodes */
failure_mode master_failure_mode; /**< Master server failure handling mode */
uint64_t max_sescmd_history; /**< Maximum amount of session commands to store */
bool disable_sescmd_history;/**< Disable session command history */
bool master_accept_reads; /**< Use master for reads */
bool strict_multi_stmt; /**< Force non-multistatement queries to be routed to
* the master after a multistatement query. */
bool strict_sp_calls; /**< Lock session to master after an SP call */
bool retry_failed_reads; /**< Retry failed reads on other servers */
int connection_keepalive; /**< Send pings to servers that have been idle
* for too long */
int max_slave_replication_lag; /**< Maximum replication lag */
int rw_max_slave_conn_percent; /**< Maximum percentage of slaves to use for
* each connection*/
int max_slave_connections; /**< Maximum number of slaves for each connection*/
bool causal_reads; /**< Enable causual read */
std::string causal_reads_timeout; /**< Timeout, second parameter of function master_wait_gtid */
bool master_reconnection; /**< Allow changes in master server */
bool delayed_retry; /**< Delay routing if no target found */
uint64_t delayed_retry_timeout; /**< How long to delay until an error is returned */
bool transaction_replay; /**< Replay failed transactions */
size_t trx_max_size; /**< Max transaction size for replaying */
bool optimistic_trx; /**< Enable optimistic transactions */
};
/**
@ -223,7 +224,7 @@ class RWSplitSession;
/**
* The per instance data for the router.
*/
class RWSplit: public mxs::Router<RWSplit, RWSplitSession>
class RWSplit : public mxs::Router<RWSplit, RWSplitSession>
{
RWSplit(const RWSplit&);
RWSplit& operator=(const RWSplit&);
@ -232,18 +233,18 @@ public:
RWSplit(SERVICE* service, const Config& config);
~RWSplit();
SERVICE* service() const;
SERVICE* service() const;
const Config& config() const;
Stats& stats();
const Stats& stats() const;
int max_slave_count() const;
bool have_enough_servers() const;
bool select_connect_backend_servers(MXS_SESSION *session,
mxs::SRWBackendList& backends,
mxs::SRWBackend& current_master,
mxs::SessionCommandList* sescmd_list,
int* expected_responses,
connection_type type);
Stats& stats();
const Stats& stats() const;
int max_slave_count() const;
bool have_enough_servers() const;
bool select_connect_backend_servers(MXS_SESSION* session,
mxs::SRWBackendList& backends,
mxs::SRWBackend& current_master,
mxs::SessionCommandList* sescmd_list,
int* expected_responses,
connection_type type);
// API functions
/**
@ -303,14 +304,14 @@ public:
private:
// Update configuration
void store_config(const Config& config);
void update_local_config() const;
void store_config(const Config& config);
void update_local_config() const;
Config* get_local_config() const;
// Called when worker local data needs to be updated
static void update_config(void* data);
SERVICE* m_service; /**< Service where the router belongs*/
SERVICE* m_service; /**< Service where the router belongs*/
mxs::rworker_local<Config> m_config;
Stats m_stats;
};
@ -358,8 +359,8 @@ static inline const char* failure_mode_to_str(enum failure_mode type)
}
}
void closed_session_reply(GWBUF *querybuf);
bool send_readonly_error(DCB *dcb);
void closed_session_reply(GWBUF* querybuf);
bool send_readonly_error(DCB* dcb);
mxs::SRWBackend get_root_master(const mxs::SRWBackendList& backends);
@ -385,8 +386,8 @@ std::pair<int, int> get_slave_counts(mxs::SRWBackendList& backends, mxs::SRWBack
* @return Valid iterator into argument backends, or end(backends) if empty
*/
SRWBackendVector::const_iterator find_best_backend(const SRWBackendVector& backends,
BackendSelectFunction select,
bool masters_accepts_reads);
BackendSelectFunction select,
bool masters_accepts_reads);
/*
* The following are implemented in rwsplit_tmp_table_multi.c

View File

@ -19,14 +19,15 @@ namespace maxscale
ResponseStat::ResponseStat(int num_filter_samples,
int num_synch_medians,
maxbase::Duration sync_duration)
: m_num_filter_samples {num_filter_samples},
m_num_synch_medians{num_synch_medians},
m_sync_duration{sync_duration},
m_sample_count{0},
m_samples(num_filter_samples),
m_last_start{maxbase::TimePoint()},
m_next_sync{maxbase::Clock::now() + sync_duration}
{}
: m_num_filter_samples {num_filter_samples}
, m_num_synch_medians{num_synch_medians}
, m_sync_duration{sync_duration}
, m_sample_count{0}
, m_samples(num_filter_samples)
, m_last_start{maxbase::TimePoint()}
, m_next_sync{maxbase::Clock::now() + sync_duration}
{
}
void ResponseStat::query_started()
@ -83,8 +84,8 @@ maxbase::Duration ResponseStat::average() const
bool ResponseStat::sync_time_reached()
{
auto now = maxbase::Clock::now();
bool reached = m_next_sync < now
|| m_average.num_samples() >= m_num_synch_medians;
bool reached = m_next_sync < now
|| m_average.num_samples() >= m_num_synch_medians;
if (reached)
{
@ -99,6 +100,4 @@ void ResponseStat::reset()
m_average.reset();
m_next_sync = maxbase::Clock::now() + m_sync_duration;
}
}

View File

@ -7,14 +7,14 @@
namespace maxscale
{
RWBackend::RWBackend(SERVER_REF* ref):
mxs::Backend(ref),
m_reply_state(REPLY_STATE_DONE),
m_modutil_state{0},
m_command(0),
m_opening_cursor(false),
m_expected_rows(0),
m_local_infile_requested(false)
RWBackend::RWBackend(SERVER_REF* ref)
: mxs::Backend(ref)
, m_reply_state(REPLY_STATE_DONE)
, m_modutil_state{0}
, m_command(0)
, m_opening_cursor(false)
, m_expected_rows(0)
, m_local_infile_requested(false)
{
}
@ -125,7 +125,7 @@ static inline bool have_next_packet(GWBUF* buffer)
*
* @return True if the complete response has been received
*/
bool RWBackend::reply_is_complete(GWBUF *buffer)
bool RWBackend::reply_is_complete(GWBUF* buffer)
{
if (current_command() == MXS_COM_STMT_FETCH)
{
@ -144,15 +144,15 @@ bool RWBackend::reply_is_complete(GWBUF *buffer)
// COM_STATISTICS returns a single string and thus requires special handling
set_reply_state(REPLY_STATE_DONE);
}
else if (get_reply_state() == REPLY_STATE_START &&
(!mxs_mysql_is_result_set(buffer) || GWBUF_IS_COLLECTED_RESULT(buffer)))
else if (get_reply_state() == REPLY_STATE_START
&& (!mxs_mysql_is_result_set(buffer) || GWBUF_IS_COLLECTED_RESULT(buffer)))
{
m_local_infile_requested = false;
if (GWBUF_IS_COLLECTED_RESULT(buffer) ||
current_command() == MXS_COM_STMT_PREPARE ||
!mxs_mysql_is_ok_packet(buffer) ||
!mxs_mysql_more_results_after_ok(buffer))
if (GWBUF_IS_COLLECTED_RESULT(buffer)
|| current_command() == MXS_COM_STMT_PREPARE
|| !mxs_mysql_is_ok_packet(buffer)
|| !mxs_mysql_more_results_after_ok(buffer))
{
/** Not a result set, we have the complete response */
set_reply_state(REPLY_STATE_DONE);
@ -165,8 +165,8 @@ bool RWBackend::reply_is_complete(GWBUF *buffer)
else
{
// This is an OK packet and more results will follow
mxb_assert(mxs_mysql_is_ok_packet(buffer) &&
mxs_mysql_more_results_after_ok(buffer));
mxb_assert(mxs_mysql_is_ok_packet(buffer)
&& mxs_mysql_more_results_after_ok(buffer));
if (have_next_packet(buffer))
{
@ -230,7 +230,7 @@ bool RWBackend::reply_is_complete(GWBUF *buffer)
return get_reply_state() == REPLY_STATE_DONE;
}
ResponseStat &RWBackend::response_stat()
ResponseStat& RWBackend::response_stat()
{
return m_response_stat;
}
@ -239,7 +239,7 @@ SRWBackendList RWBackend::from_servers(SERVER_REF* servers)
{
SRWBackendList backends;
for (SERVER_REF *ref = servers; ref; ref = ref->next)
for (SERVER_REF* ref = servers; ref; ref = ref->next)
{
if (ref->active)
{
@ -249,5 +249,4 @@ SRWBackendList RWBackend::from_servers(SERVER_REF* servers)
return backends;
}
}

View File

@ -10,7 +10,7 @@
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#pragma once
#include "response_stat.hh"
@ -32,13 +32,13 @@ enum reply_state_t
REPLY_STATE_RSET_ROWS /**< Resultset response, waiting for rows */
};
typedef std::map<uint32_t, uint32_t> BackendHandleMap; /** Internal ID to external ID */
typedef std::map<uint32_t, uint32_t> BackendHandleMap; /** Internal ID to external ID */
class RWBackend;
typedef std::shared_ptr<RWBackend> SRWBackend;
typedef std::list<SRWBackend> SRWBackendList;
typedef std::list<SRWBackend> SRWBackendList;
class RWBackend: public mxs::Backend
class RWBackend : public mxs::Backend
{
RWBackend(const RWBackend&);
RWBackend& operator=(const RWBackend&);
@ -60,7 +60,7 @@ public:
m_reply_state = state;
}
void add_ps_handle(uint32_t id, uint32_t handle);
void add_ps_handle(uint32_t id, uint32_t handle);
uint32_t get_ps_handle(uint32_t id) const;
bool execute_session_command();
@ -110,18 +110,18 @@ public:
return m_local_infile_requested;
}
bool reply_is_complete(GWBUF *buffer);
bool reply_is_complete(GWBUF* buffer);
// Controlled by the session
ResponseStat& response_stat();
private:
reply_state_t m_reply_state;
BackendHandleMap m_ps_handles; /**< Internal ID to backend PS handle mapping */
modutil_state m_modutil_state; /**< @see modutil_count_signal_packets */
BackendHandleMap m_ps_handles; /**< Internal ID to backend PS handle mapping */
modutil_state m_modutil_state; /**< @see modutil_count_signal_packets */
uint8_t m_command;
bool m_opening_cursor; /**< Whether we are opening a cursor */
uint32_t m_expected_rows; /**< Number of rows a COM_STMT_FETCH is retrieving */
bool m_local_infile_requested; /**< Whether a LOCAL INFILE was requested */
bool m_opening_cursor; /**< Whether we are opening a cursor */
uint32_t m_expected_rows; /**< Number of rows a COM_STMT_FETCH is retrieving */
bool m_local_infile_requested; /**< Whether a LOCAL INFILE was requested */
ResponseStat m_response_stat;
inline bool is_opening_cursor() const
@ -134,5 +134,4 @@ private:
m_opening_cursor = false;
}
};
}

View File

@ -79,8 +79,10 @@
* @param qtype Query type
* @return bool indicating whether the session can continue
*/
bool RWSplitSession::handle_target_is_all(route_target_t route_target, GWBUF *querybuf,
int packet_type, uint32_t qtype)
bool RWSplitSession::handle_target_is_all(route_target_t route_target,
GWBUF* querybuf,
int packet_type,
uint32_t qtype)
{
bool result = false;
bool is_large = is_large_query(querybuf);
@ -91,15 +93,20 @@ bool RWSplitSession::handle_target_is_all(route_target_t route_target, GWBUF *qu
* Conflicting routing targets. Return an error to the client.
*/
char *query_str = modutil_get_query(querybuf);
char *qtype_str = qc_typemask_to_string(qtype);
char* query_str = modutil_get_query(querybuf);
char* qtype_str = qc_typemask_to_string(qtype);
MXS_ERROR("Can't route %s:%s:\"%s\". SELECT with session data "
"modification is not supported if configuration parameter "
"use_sql_variables_in=all .", STRPACKETTYPE(packet_type),
qtype_str, (query_str == NULL ? "(empty)" : query_str));
"use_sql_variables_in=all .",
STRPACKETTYPE(packet_type),
qtype_str,
(query_str == NULL ? "(empty)" : query_str));
GWBUF *errbuf = modutil_create_mysql_err_msg(1, 0, 1064, "42000",
GWBUF* errbuf = modutil_create_mysql_err_msg(1,
0,
1064,
"42000",
"Routing query to backend failed. "
"See the error log for further details.");
@ -139,13 +146,16 @@ bool RWSplitSession::handle_target_is_all(route_target_t route_target, GWBUF *qu
*
* @return True if sending the message was successful, false if an error occurred
*/
bool send_readonly_error(DCB *dcb)
bool send_readonly_error(DCB* dcb)
{
bool succp = false;
const char* errmsg = "The MariaDB server is running with the --read-only"
" option so it cannot execute this statement";
GWBUF* err = modutil_create_mysql_err_msg(1, 0, ER_OPTION_PREVENTS_STATEMENT,
"HY000", errmsg);
GWBUF* err = modutil_create_mysql_err_msg(1,
0,
ER_OPTION_PREVENTS_STATEMENT,
"HY000",
errmsg);
if (err)
{

View File

@ -55,7 +55,8 @@ void RWSplitSession::handle_connection_keepalive(SRWBackend& target)
if (diff > keepalive)
{
MXS_INFO("Pinging %s, idle for %ld seconds",
backend->name(), MXS_CLOCK_TO_SEC(diff));
backend->name(),
MXS_CLOCK_TO_SEC(diff));
modutil_ignorable_ping(backend->dcb());
}
}
@ -79,8 +80,8 @@ bool RWSplitSession::prepare_target(SRWBackend& target, route_target_t route_tar
if (rval && target->is_waiting_result())
{
mxb_assert_message(!m_sescmd_list.empty() && target->has_session_commands(),
"Session command list must not be empty and target "
"should have unfinished session commands.");
"Session command list must not be empty and target "
"should have unfinished session commands.");
m_expected_responses++;
}
}
@ -105,12 +106,11 @@ void replace_binary_ps_id(GWBUF* buffer, uint32_t id)
uint8_t* ptr = GWBUF_DATA(buffer) + MYSQL_PS_ID_OFFSET;
gw_mysql_set_byte4(ptr, id);
}
}
bool RWSplitSession::have_connected_slaves() const
{
for (const auto& b: m_backends)
for (const auto& b : m_backends)
{
if (b->is_slave() && b->in_use())
{
@ -123,12 +123,12 @@ 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
!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
TARGET_IS_MASTER(route_target) && // The target type is master
have_connected_slaves(); // At least one connected slave
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
&& TARGET_IS_MASTER(route_target)// The target type is master
&& have_connected_slaves(); // At least one connected slave
}
bool RWSplitSession::track_optimistic_trx(GWBUF** buffer)
@ -168,10 +168,10 @@ bool RWSplitSession::track_optimistic_trx(GWBUF** buffer)
* @return true if routing succeed or if it failed due to unsupported query.
* false if backend failure was encountered.
*/
bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
bool RWSplitSession::route_single_stmt(GWBUF* querybuf)
{
mxb_assert_message(m_otrx_state != OTRX_ROLLBACK,
"OTRX_ROLLBACK should never happen when routing queries");
"OTRX_ROLLBACK should never happen when routing queries");
bool succp = false;
const QueryClassifier::RouteInfo& info = m_qc.current_route_info();
uint32_t stmt_id = info.stmt_id();
@ -197,9 +197,9 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
{
update_trx_statistics();
if (m_qc.is_trx_starting() && // A transaction is starting
!session_trx_is_read_only(m_client->session) && // Not explicitly read-only
should_try_trx_on_slave(route_target)) // Qualifies for speculative routing
if (m_qc.is_trx_starting() // A transaction is starting
&& !session_trx_is_read_only(m_client->session) // Not explicitly read-only
&& should_try_trx_on_slave(route_target)) // Qualifies for speculative routing
{
// Speculatively start routing the transaction to a slave
m_otrx_state = OTRX_STARTING;
@ -270,7 +270,8 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
if (!succp && should_migrate_trx(target))
{
MXS_INFO("Starting transaction migration from '%s' to '%s'",
m_current_master->name(), target->name());
m_current_master->name(),
target->name());
/**
* Stash the current query so that the transaction replay treats
@ -328,7 +329,8 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
else
{
MXS_ERROR("Could not find valid server for target type %s, closing "
"connection.", STRTARGET(route_target));
"connection.",
STRTARGET(route_target));
}
}
@ -351,10 +353,9 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
*/
void RWSplitSession::compress_history(mxs::SSessionCommand& sescmd)
{
auto eq = [&](mxs::SSessionCommand& scmd)
{
return scmd->eq(*sescmd);
};
auto eq = [&](mxs::SSessionCommand& scmd) {
return scmd->eq(*sescmd);
};
auto first = std::find_if(m_sescmd_list.begin(), m_sescmd_list.end(), eq);
@ -365,7 +366,7 @@ void RWSplitSession::compress_history(mxs::SSessionCommand& sescmd)
}
}
void RWSplitSession::continue_large_session_write(GWBUF *querybuf, uint32_t type)
void RWSplitSession::continue_large_session_write(GWBUF* querybuf, uint32_t type)
{
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
{
@ -397,7 +398,7 @@ void RWSplitSession::continue_large_session_write(GWBUF *querybuf, uint32_t type
* backends being used, otherwise false.
*
*/
bool RWSplitSession::route_session_write(GWBUF *querybuf, uint8_t command, uint32_t type)
bool RWSplitSession::route_session_write(GWBUF* querybuf, uint8_t command, uint32_t type)
{
/** The SessionCommand takes ownership of the buffer */
uint64_t id = m_sescmd_count++;
@ -407,8 +408,8 @@ bool RWSplitSession::route_session_write(GWBUF *querybuf, uint8_t command, uint3
uint64_t lowest_pos = id;
gwbuf_set_type(querybuf, GWBUF_TYPE_COLLECT_RESULT);
if (qc_query_is_type(type, QUERY_TYPE_PREPARE_NAMED_STMT) ||
qc_query_is_type(type, QUERY_TYPE_PREPARE_STMT))
if (qc_query_is_type(type, QUERY_TYPE_PREPARE_NAMED_STMT)
|| qc_query_is_type(type, QUERY_TYPE_PREPARE_STMT))
{
m_qc.ps_store(querybuf, id);
}
@ -446,12 +447,14 @@ bool RWSplitSession::route_session_write(GWBUF *querybuf, uint8_t command, uint3
MXS_INFO("Route query to %s: %s \t%s",
backend->is_master() ? "master" : "slave",
backend->name(), backend->uri());
backend->name(),
backend->uri());
}
else
{
MXS_ERROR("Failed to execute session command in %s (%s)",
backend->name(), backend->uri());
backend->name(),
backend->uri());
}
}
}
@ -468,7 +471,8 @@ 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;
}
@ -516,7 +520,7 @@ static inline bool rpl_lag_is_ok(SRWBackend& backend, int max_rlag)
return max_rlag == MXS_RLAG_UNDEFINED || backend->server()->rlag <= max_rlag;
}
SRWBackend RWSplitSession::get_hinted_backend(char *name)
SRWBackend RWSplitSession::get_hinted_backend(char* name)
{
SRWBackend rval;
@ -525,9 +529,9 @@ SRWBackend RWSplitSession::get_hinted_backend(char *name)
auto& backend = *it;
/** The server must be a valid slave, relay server, or master */
if ((backend->in_use() || (can_recover_servers() && backend->can_connect())) &&
strcasecmp(name, backend->name()) == 0 &&
(backend->is_slave() || backend->is_relay() || backend->is_master()))
if ((backend->in_use() || (can_recover_servers() && backend->can_connect()))
&& strcasecmp(name, backend->name()) == 0
&& (backend->is_slave() || backend->is_relay() || backend->is_master()))
{
rval = backend;
break;
@ -547,14 +551,14 @@ SRWBackend RWSplitSession::get_slave_backend(int max_rlag)
for (auto& backend : m_backends)
{
bool can_take_slave_into_use = backend->is_slave()
&& !backend->in_use()
&& can_recover_servers()
&& backend->can_connect()
&& counts.second < m_router->max_slave_count();
&& !backend->in_use()
&& can_recover_servers()
&& backend->can_connect()
&& counts.second < m_router->max_slave_count();
bool master_or_slave = backend->is_master() || backend->is_slave();
bool is_useable = backend->in_use() || can_take_slave_into_use;
bool not_a_slacker = rpl_lag_is_ok(backend, max_rlag);
bool is_useable = backend->in_use() || can_take_slave_into_use;
bool not_a_slacker = rpl_lag_is_ok(backend, max_rlag);
bool server_is_candidate = master_or_slave && is_useable && not_a_slacker;
@ -565,8 +569,8 @@ SRWBackend RWSplitSession::get_slave_backend(int max_rlag)
}
SRWBackendVector::const_iterator rval = find_best_backend(candidates,
m_config.backend_select_fct,
m_config.master_accept_reads);
m_config.backend_select_fct,
m_config.master_accept_reads);
return (rval == candidates.end()) ? SRWBackend() : **rval;
}
@ -588,7 +592,8 @@ SRWBackend RWSplitSession::get_master_backend()
else
{
MXS_ERROR("Server '%s' does not have the master state and "
"can't be chosen as the master.", master->name());
"can't be chosen as the master.",
master->name());
}
}
else
@ -618,7 +623,8 @@ SRWBackend RWSplitSession::get_last_used_backend()
* @return True if a backend was found
*/
SRWBackend RWSplitSession::get_target_backend(backend_type_t btype,
char *name, int max_rlag)
char* name,
int max_rlag)
{
/** Check whether using target_node as target SLAVE */
if (m_target_node && session_trx_is_read_only(m_client->session))
@ -628,7 +634,7 @@ SRWBackend RWSplitSession::get_target_backend(backend_type_t btype,
SRWBackend rval;
if (name) /*< Choose backend by name from a hint */
if (name) /*< Choose backend by name from a hint */
{
mxb_assert(btype != BE_MASTER);
btype = BE_SLAVE;
@ -682,9 +688,9 @@ int RWSplitSession::get_max_replication_lag()
*
* @return bool - true if succeeded, false otherwise
*/
SRWBackend RWSplitSession::handle_hinted_target(GWBUF *querybuf, route_target_t route_target)
SRWBackend RWSplitSession::handle_hinted_target(GWBUF* querybuf, route_target_t route_target)
{
char *named_server = NULL;
char* named_server = NULL;
int rlag_max = MXS_RLAG_UNDEFINED;
HINT* hint = querybuf->hint;
@ -700,11 +706,12 @@ SRWBackend RWSplitSession::handle_hinted_target(GWBUF *querybuf, route_target_t
named_server = (char*)hint->data;
MXS_INFO("Hint: route to server '%s'", named_server);
}
else if (hint->type == HINT_PARAMETER &&
(strncasecmp((char *)hint->data, "max_slave_replication_lag",
strlen("max_slave_replication_lag")) == 0))
else if (hint->type == HINT_PARAMETER
&& (strncasecmp((char*)hint->data,
"max_slave_replication_lag",
strlen("max_slave_replication_lag")) == 0))
{
int val = (int)strtol((char *)hint->value, (char **)NULL, 10);
int val = (int)strtol((char*)hint->value, (char**)NULL, 10);
if (val != 0 || errno == 0)
{
@ -714,9 +721,9 @@ SRWBackend RWSplitSession::handle_hinted_target(GWBUF *querybuf, route_target_t
}
}
hint = hint->next;
} /*< while */
} /*< while */
if (rlag_max == MXS_RLAG_UNDEFINED) /*< no rlag max hint, use config */
if (rlag_max == MXS_RLAG_UNDEFINED) /*< no rlag max hint, use config */
{
rlag_max = get_max_replication_lag();
}
@ -736,13 +743,15 @@ SRWBackend RWSplitSession::handle_hinted_target(GWBUF *querybuf, route_target_t
{
MXS_INFO("Was supposed to route to named server "
"%s but couldn't find the server in a "
"suitable state.", named_server);
"suitable state.",
named_server);
}
else if (TARGET_IS_RLAG_MAX(route_target))
{
MXS_INFO("Was supposed to route to server with "
"replication lag at most %d but couldn't "
"find such a slave.", rlag_max);
"find such a slave.",
rlag_max);
}
}
@ -778,7 +787,8 @@ SRWBackend RWSplitSession::handle_slave_is_target(uint8_t cmd, uint32_t stmt_id)
else
{
MXS_ERROR("Old COM_STMT_EXECUTE target %s not in use, cannot "
"proceed with COM_STMT_FETCH", it->second->name());
"proceed with COM_STMT_FETCH",
it->second->name());
}
}
else
@ -813,10 +823,11 @@ void RWSplitSession::log_master_routing_failure(bool found,
{
/** Both backends should either be empty, not connected or the DCB should
* be a backend (the last check is slightly redundant). */
mxb_assert(!old_master || !old_master->in_use() || old_master->dcb()->dcb_role == DCB_ROLE_BACKEND_HANDLER);
mxb_assert(!curr_master || !curr_master->in_use() ||
curr_master->dcb()->dcb_role == DCB_ROLE_BACKEND_HANDLER);
char errmsg[MAX_SERVER_ADDRESS_LEN * 2 + 100]; // Extra space for error message
mxb_assert(!old_master || !old_master->in_use()
|| old_master->dcb()->dcb_role == DCB_ROLE_BACKEND_HANDLER);
mxb_assert(!curr_master || !curr_master->in_use()
|| curr_master->dcb()->dcb_role == DCB_ROLE_BACKEND_HANDLER);
char errmsg[MAX_SERVER_ADDRESS_LEN * 2 + 100]; // Extra space for error message
if (!found)
{
@ -826,15 +837,18 @@ void RWSplitSession::log_master_routing_failure(bool found,
{
/** We found a master but it's not the same connection */
mxb_assert(old_master != curr_master);
sprintf(errmsg, "Master server changed from '%s' to '%s'",
old_master->name(), curr_master->name());
sprintf(errmsg,
"Master server changed from '%s' to '%s'",
old_master->name(),
curr_master->name());
}
else if (old_master && old_master->in_use())
{
// TODO: Figure out if this is an impossible situation
mxb_assert(!curr_master);
/** We have an original master connection but we couldn't find it */
sprintf(errmsg, "The connection to master server '%s' is not available",
sprintf(errmsg,
"The connection to master server '%s' is not available",
old_master->name());
}
else
@ -842,31 +856,35 @@ void RWSplitSession::log_master_routing_failure(bool found,
/** We never had a master connection, the session must be in read-only mode */
if (m_config.master_failure_mode != RW_FAIL_INSTANTLY)
{
sprintf(errmsg, "Session is in read-only mode because it was created "
sprintf(errmsg,
"Session is in read-only mode because it was created "
"when no master was available");
}
else
{
mxb_assert(old_master && !old_master->in_use());
sprintf(errmsg, "Was supposed to route to master but the master connection is %s",
sprintf(errmsg,
"Was supposed to route to master but the master connection is %s",
old_master->is_closed() ? "closed" : "not in a suitable state");
mxb_assert(old_master->is_closed());
}
}
MXS_WARNING("[%s] Write query received from %s@%s. %s. Closing client connection.",
m_router->service()->name, m_client->user,
m_client->remote, errmsg);
m_router->service()->name,
m_client->user,
m_client->remote,
errmsg);
}
bool RWSplitSession::should_replace_master(SRWBackend& target)
{
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)
(!session_trx_is_active(m_client->session) || m_is_replay_active) &&
// We are not locked to the old master
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)
(!session_trx_is_active(m_client->session) || m_is_replay_active)
&& // We are not locked to the old master
!is_locked_to_master();
}
@ -879,14 +897,14 @@ void RWSplitSession::replace_master(SRWBackend& target)
bool RWSplitSession::should_migrate_trx(SRWBackend& target)
{
return m_config.transaction_replay &&
// We have a target server and it's not the current master
target && target != m_current_master &&
// Transaction replay is not active (replay is only attempted once)
!m_is_replay_active &&
// We have an open transaction
session_trx_is_active(m_client->session) &&
// The transaction can be replayed
return m_config.transaction_replay
&& // We have a target server and it's not the current master
target && target != m_current_master
&& // Transaction replay is not active (replay is only attempted once)
!m_is_replay_active
&& // We have an open transaction
session_trx_is_active(m_client->session)
&& // The transaction can be replayed
m_can_replay_trx;
}
@ -908,8 +926,10 @@ bool RWSplitSession::handle_master_is_target(SRWBackend* dest)
if (should_replace_master(target))
{
MXS_INFO("Replacing old master '%s' with new master '%s'", m_current_master ?
m_current_master->name() : "<no previous master>", target->name());
MXS_INFO("Replacing old master '%s' with new master '%s'",
m_current_master
? m_current_master->name() : "<no previous master>",
target->name());
replace_master(target);
}
@ -930,16 +950,16 @@ 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);
}
}
if (!m_config.strict_multi_stmt && !m_config.strict_sp_calls &&
m_target_node == m_current_master)
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 */
m_target_node.reset();
@ -958,7 +978,7 @@ bool RWSplitSession::handle_master_is_target(SRWBackend* dest)
* @param origin origin send buffer
* @return A new buffer contains wait statement and origin query
*/
GWBUF* RWSplitSession::add_prefix_wait_gtid(SERVER *server, GWBUF *origin)
GWBUF* RWSplitSession::add_prefix_wait_gtid(SERVER* server, GWBUF* origin)
{
/**
@ -973,21 +993,21 @@ 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_config.causal_reads_timeout.c_str();
const char *gtid_position = m_gtid_pos.c_str();
const char* wait_func = (server->server_type == SERVER_TYPE_MARIADB)
? MARIADB_WAIT_GTID_FUNC : MYSQL_WAIT_GTID_FUNC;
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 */
size_t prefix_len = strlen(gtid_wait_stmt) + strlen(gtid_position) +
strlen(gtid_wait_timeout) + strlen(wait_func);
size_t prefix_len = strlen(gtid_wait_stmt) + strlen(gtid_position)
+ strlen(gtid_wait_timeout) + strlen(wait_func);
// Only do the replacement if it fits into one packet
if (gwbuf_length(origin) + prefix_len < GW_MYSQL_MAX_PACKET_LEN + MYSQL_HEADER_LEN)
{
char prefix_sql[prefix_len];
snprintf(prefix_sql, prefix_len, gtid_wait_stmt, wait_func, gtid_position, gtid_wait_timeout);
GWBUF *prefix_buff = modutil_create_query(prefix_sql);
GWBUF* prefix_buff = modutil_create_query(prefix_sql);
/* Trim origin to sql, Append origin buffer to the prefix buffer */
uint8_t header[MYSQL_HEADER_LEN];
@ -1023,26 +1043,28 @@ bool RWSplitSession::handle_got_target(GWBUF* querybuf, SRWBackend& target, bool
m_target_node = target;
}
MXS_INFO("Route query to %s: %s \t%s <", target->is_master() ? "master" : "slave",
target->name(), target->uri());
MXS_INFO("Route query to %s: %s \t%s <",
target->is_master() ? "master" : "slave",
target->name(),
target->uri());
/** The session command cursor must not be active */
mxb_assert(!target->has_session_commands());
mxs::Backend::response_type response = mxs::Backend::NO_RESPONSE;
uint8_t cmd = mxs_mysql_get_command(querybuf);
GWBUF *send_buf = gwbuf_clone(querybuf);
GWBUF* send_buf = gwbuf_clone(querybuf);
if (m_config.causal_reads && cmd == COM_QUERY && !m_gtid_pos.empty() &&
target->is_slave())
if (m_config.causal_reads && cmd == COM_QUERY && !m_gtid_pos.empty()
&& target->is_slave())
{
// Perform the causal read only when the query is routed to a slave
send_buf = add_prefix_wait_gtid(target->server(), send_buf);
m_wait_gtid = WAITING_FOR_HEADER;
}
if (m_qc.load_data_state() != QueryClassifier::LOAD_DATA_ACTIVE &&
!m_qc.large_query() && mxs_mysql_command_will_respond(cmd))
if (m_qc.load_data_state() != QueryClassifier::LOAD_DATA_ACTIVE
&& !m_qc.large_query() && mxs_mysql_command_will_respond(cmd))
{
response = mxs::Backend::EXPECT_RESPONSE;
}
@ -1055,9 +1077,9 @@ bool RWSplitSession::handle_got_target(GWBUF* querybuf, SRWBackend& target, bool
* will do the replacement of PS IDs which must not be done if we are
* continuing an ongoing query.
*/
bool success = !m_qc.large_query() ?
target->write(send_buf, response) :
target->continue_write(send_buf);
bool success = !m_qc.large_query()
? target->write(send_buf, response)
: target->continue_write(send_buf);
if (success)
{
@ -1098,9 +1120,9 @@ bool RWSplitSession::handle_got_target(GWBUF* querybuf, SRWBackend& target, bool
/**
* If a READ ONLY transaction is ending set forced_node to NULL
*/
if (m_target_node &&
session_trx_is_read_only(m_client->session) &&
session_trx_is_ending(m_client->session))
if (m_target_node
&& session_trx_is_read_only(m_client->session)
&& session_trx_is_ending(m_client->session))
{
m_target_node.reset();
}

View File

@ -53,12 +53,12 @@ double toss()
*/
static bool valid_for_slave(const SRWBackend& backend, const SRWBackend& master)
{
return (backend->is_slave() || backend->is_relay()) &&
(!master || backend != master);
return (backend->is_slave() || backend->is_relay())
&& (!master || backend != master);
}
SRWBackendVector::const_iterator best_score(const SRWBackendVector& sBackends,
std::function <double(SERVER_REF* server)> server_score)
std::function<double(SERVER_REF* server)> server_score)
{
double min {std::numeric_limits<double>::max()};
auto best = sBackends.end();
@ -78,10 +78,9 @@ SRWBackendVector::const_iterator best_score(const SRWBackendVector& sBackends,
/** Compare number of connections from this router in backend servers */
SRWBackendVector::const_iterator backend_cmp_router_conn(const SRWBackendVector& sBackends)
{
static auto server_score = [](SERVER_REF * server)
{
return server->inv_weight * server->connections;
};
static auto server_score = [](SERVER_REF* server) {
return server->inv_weight * server->connections;
};
return best_score(sBackends, server_score);
}
@ -89,10 +88,9 @@ SRWBackendVector::const_iterator backend_cmp_router_conn(const SRWBackendVector&
/** Compare number of global connections in backend servers */
SRWBackendVector::const_iterator backend_cmp_global_conn(const SRWBackendVector& sBackends)
{
static auto server_score = [](SERVER_REF * server)
{
return server->inv_weight * server->server->stats.n_current;
};
static auto server_score = [](SERVER_REF* server) {
return server->inv_weight * server->server->stats.n_current;
};
return best_score(sBackends, server_score);
}
@ -100,10 +98,9 @@ SRWBackendVector::const_iterator backend_cmp_global_conn(const SRWBackendVector&
/** Compare replication lag between backend servers */
SRWBackendVector::const_iterator backend_cmp_behind_master(const SRWBackendVector& sBackends)
{
static auto server_score = [](SERVER_REF * server)
{
return server->inv_weight * server->server->rlag;
};
static auto server_score = [](SERVER_REF* server) {
return server->inv_weight * server->server->rlag;
};
return best_score(sBackends, server_score);
}
@ -111,10 +108,9 @@ SRWBackendVector::const_iterator backend_cmp_behind_master(const SRWBackendVecto
/** Compare number of current operations in backend servers */
SRWBackendVector::const_iterator backend_cmp_current_load(const SRWBackendVector& sBackends)
{
static auto server_score = [](SERVER_REF * server)
{
return server->inv_weight * server->server->stats.n_current_ops;
};
static auto server_score = [](SERVER_REF* server) {
return server->inv_weight * server->server->stats.n_current_ops;
};
return best_score(sBackends, server_score);
}
@ -130,16 +126,17 @@ SRWBackendVector::const_iterator backend_cmp_response_time(const SRWBackendVecto
{
SERVER_REF* server = (**sBackends[i]).backend();
auto ave = server->server->response_time->average();
if (ave==0)
if (ave == 0)
{
constexpr double very_quick = 1.0/10000000; // arbitrary very short duration (0.1 microseconds)
slot[i] = 1 / very_quick; // will be used and updated (almost) immediately.
constexpr double very_quick = 1.0 / 10000000; // arbitrary very short duration (0.1
// microseconds)
slot[i] = 1 / very_quick; // will be used and updated (almost) immediately.
}
else
{
slot[i] = 1 / ave;
}
slot[i] = slot[i]*slot[i]; // favor faster servers even more
slot[i] = slot[i] * slot[i]; // favor faster servers even more
total += slot[i];
}
@ -172,13 +169,17 @@ BackendSelectFunction get_backend_select_function(select_criteria_t sc)
{
case LEAST_GLOBAL_CONNECTIONS:
return backend_cmp_global_conn;
case LEAST_ROUTER_CONNECTIONS:
return backend_cmp_router_conn;
case LEAST_BEHIND_MASTER:
return backend_cmp_behind_master;
case LEAST_CURRENT_OPERATIONS:
return backend_cmp_current_load;
case LOWEST_RESPONSE_TIME:
case LOWEST_RESPONSE_TIME:
return backend_cmp_response_time;
}
@ -197,17 +198,17 @@ BackendSelectFunction get_backend_select_function(select_criteria_t sc)
* @return iterator to the best slave or backends.end() if none found
*/
SRWBackendVector::const_iterator find_best_backend(const SRWBackendVector& backends,
BackendSelectFunction select,
bool masters_accepts_reads)
BackendSelectFunction select,
bool masters_accepts_reads)
{
// Group backends by priority. The set of highest priority backends will then compete.
std::map<int, SRWBackendVector> priority_map;
int best_priority {INT_MAX}; // low numbers are high priority
int best_priority {INT_MAX}; // low numbers are high priority
for (auto& psBackend : backends)
{
auto& backend = **psBackend;
bool is_busy = backend.in_use() && backend.has_session_commands();
auto& backend = **psBackend;
bool is_busy = backend.in_use() && backend.has_session_commands();
bool acts_slave = backend.is_slave() || (backend.is_master() && masters_accepts_reads);
int priority;
@ -215,16 +216,16 @@ SRWBackendVector::const_iterator find_best_backend(const SRWBackendVector& backe
{
if (!is_busy)
{
priority = 1; // highest priority, idle servers
priority = 1; // highest priority, idle servers
}
else
{
priority = 13; // lowest priority, busy servers
priority = 13; // lowest priority, busy servers
}
}
else
{
priority = 2; // idle masters with masters_accept_reads==false
priority = 2; // idle masters with masters_accept_reads==false
}
priority_map[priority].push_back(psBackend);
@ -255,27 +256,34 @@ static void log_server_connections(select_criteria_t criteria, const SRWBackendL
{
case LEAST_GLOBAL_CONNECTIONS:
MXS_INFO("MaxScale connections : %d in \t[%s]:%d %s",
b->server->stats.n_current, b->server->address,
b->server->port, STRSRVSTATUS(b->server));
b->server->stats.n_current,
b->server->address,
b->server->port,
STRSRVSTATUS(b->server));
break;
case LEAST_ROUTER_CONNECTIONS:
MXS_INFO("RWSplit connections : %d in \t[%s]:%d %s",
b->connections, b->server->address,
b->server->port, STRSRVSTATUS(b->server));
b->connections,
b->server->address,
b->server->port,
STRSRVSTATUS(b->server));
break;
case LEAST_CURRENT_OPERATIONS:
MXS_INFO("current operations : %d in \t[%s]:%d %s",
b->server->stats.n_current_ops,
b->server->address, b->server->port,
b->server->address,
b->server->port,
STRSRVSTATUS(b->server));
break;
case LEAST_BEHIND_MASTER:
MXS_INFO("replication lag : %d in \t[%s]:%d %s",
b->server->rlag, b->server->address,
b->server->port, STRSRVSTATUS(b->server));
b->server->rlag,
b->server->address,
b->server->port,
STRSRVSTATUS(b->server));
break;
case LOWEST_RESPONSE_TIME:
@ -284,8 +292,10 @@ static void log_server_connections(select_criteria_t criteria, const SRWBackendL
std::ostringstream os;
os << response_ave;
MXS_INFO("Average response time : %s from \t[%s]:%d %s",
os.str().c_str(), b->server->address,
b->server->port, STRSRVSTATUS(b->server));
os.str().c_str(),
b->server->address,
b->server->port,
STRSRVSTATUS(b->server));
}
break;
@ -348,7 +358,7 @@ std::pair<int, int> get_slave_counts(SRWBackendList& backends, SRWBackend& maste
*
* @return True if session can continue
*/
bool RWSplit::select_connect_backend_servers(MXS_SESSION *session,
bool RWSplit::select_connect_backend_servers(MXS_SESSION* session,
SRWBackendList& backends,
SRWBackend& current_master,
SessionCommandList* sescmd_list,
@ -410,7 +420,10 @@ bool RWSplit::select_connect_backend_servers(MXS_SESSION *session,
while (slaves_connected < max_nslaves && candidates.size())
{
auto ite = m_config->backend_select_fct(candidates);
if (ite == candidates.end()) break;
if (ite == candidates.end())
{
break;
}
auto& backend = **ite;

View File

@ -33,7 +33,7 @@ static std::string extract_error(GWBUF* buffer)
{
std::string rval;
if (MYSQL_IS_ERROR_PACKET(((uint8_t *)GWBUF_DATA(buffer))))
if (MYSQL_IS_ERROR_PACKET(((uint8_t*)GWBUF_DATA(buffer))))
{
size_t replylen = MYSQL_GET_PAYLOAD_LEN(GWBUF_DATA(buffer));
char replybuf[replylen];
@ -55,8 +55,10 @@ static std::string extract_error(GWBUF* buffer)
* @param master_cmd Master's reply
* @param slave_cmd Slave's reply
*/
static void discard_if_response_differs(SRWBackend backend, uint8_t master_response,
uint8_t slave_response, SSessionCommand sescmd)
static void discard_if_response_differs(SRWBackend backend,
uint8_t master_response,
uint8_t slave_response,
SSessionCommand sescmd)
{
if (master_response != slave_response)
{
@ -65,7 +67,10 @@ static void discard_if_response_differs(SRWBackend backend, uint8_t master_respo
MXS_WARNING("Slave server '%s': response (0x%02hhx) differs "
"from master's response (0x%02hhx) to %s: `%s`. "
"Closing slave connection due to inconsistent session state.",
backend->name(), slave_response, master_response, STRPACKETTYPE(cmd),
backend->name(),
slave_response,
master_response,
STRPACKETTYPE(cmd),
query.empty() ? "<no query>" : query.c_str());
backend->close(mxs::Backend::CLOSE_FATAL);
}
@ -87,15 +92,15 @@ void RWSplitSession::process_sescmd_response(SRWBackend& backend, GWBUF** ppPack
if (command == MXS_COM_STMT_PREPARE && cmd != MYSQL_REPLY_ERR)
{
// This should never fail or the backend protocol is broken
MXB_AT_DEBUG(bool b = )mxs_mysql_extract_ps_response(*ppPacket, &resp);
MXB_AT_DEBUG(bool b = ) mxs_mysql_extract_ps_response(*ppPacket, &resp);
mxb_assert(b);
backend->add_ps_handle(id, resp.id);
}
if (m_recv_sescmd < m_sent_sescmd && id == m_recv_sescmd + 1)
{
if (!m_current_master || !m_current_master->in_use() || // Session doesn't have a master
m_current_master == backend) // This is the master's response
if (!m_current_master || !m_current_master->in_use()// Session doesn't have a master
|| m_current_master == backend) // This is the master's response
{
/** First reply to this session command, route it to the client */
++m_recv_sescmd;
@ -108,7 +113,8 @@ void RWSplitSession::process_sescmd_response(SRWBackend& backend, GWBUF** ppPack
if (cmd == MYSQL_REPLY_ERR)
{
MXS_INFO("Session command no. %lu failed: %s",
id, extract_error(*ppPacket).c_str());
id,
extract_error(*ppPacket).c_str());
}
else if (command == MXS_COM_STMT_PREPARE)
{

View File

@ -20,28 +20,30 @@
using namespace maxscale;
RWSplitSession::RWSplitSession(RWSplit* instance, MXS_SESSION* session,
RWSplitSession::RWSplitSession(RWSplit* instance,
MXS_SESSION* session,
const SRWBackendList& backends,
const SRWBackend& master):
mxs::RouterSession(session),
m_backends(backends),
m_current_master(master),
m_config(instance->config()),
m_nbackends(instance->service()->n_dbref),
m_client(session->client_dcb),
m_sescmd_count(1), // Needs to be a positive number to work
m_expected_responses(0),
m_query_queue(NULL),
m_router(instance),
m_sent_sescmd(0),
m_recv_sescmd(0),
m_gtid_pos(""),
m_wait_gtid(NONE),
m_next_seq(0),
m_qc(this, session, m_config.use_sql_variables_in),
m_retry_duration(0),
m_is_replay_active(false),
m_can_replay_trx(true)
const SRWBackend& master)
: mxs::RouterSession(session)
, m_backends(backends)
, m_current_master(master)
, m_config(instance->config())
, m_nbackends(instance->service()->n_dbref)
, m_client(session->client_dcb)
, m_sescmd_count(1)
, // Needs to be a positive number to work
m_expected_responses(0)
, m_query_queue(NULL)
, m_router(instance)
, m_sent_sescmd(0)
, m_recv_sescmd(0)
, m_gtid_pos("")
, m_wait_gtid(NONE)
, m_next_seq(0)
, 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)
{
@ -67,8 +69,12 @@ RWSplitSession* RWSplitSession::create(RWSplit* router, MXS_SESSION* session)
SRWBackend master;
if (router->select_connect_backend_servers(session, backends, master, NULL,
NULL, connection_type::ALL))
if (router->select_connect_backend_servers(session,
backends,
master,
NULL,
NULL,
connection_type::ALL))
{
if ((rses = new RWSplitSession(router, session, backends, master)))
{
@ -105,21 +111,21 @@ void RWSplitSession::close()
if (stat.make_valid())
{
server_add_response_average(backend->server(),
stat.average().secs(), stat.num_samples());
stat.average().secs(),
stat.num_samples());
}
backend->response_stat().reset();
}
}
int32_t RWSplitSession::routeQuery(GWBUF* querybuf)
{
int rval = 0;
if (m_query_queue == NULL &&
(m_expected_responses == 0 ||
m_qc.load_data_state() == QueryClassifier::LOAD_DATA_ACTIVE ||
m_qc.large_query()))
if (m_query_queue == NULL
&& (m_expected_responses == 0
|| m_qc.load_data_state() == QueryClassifier::LOAD_DATA_ACTIVE
|| m_qc.large_query()))
{
/** Gather the information required to make routing decisions */
@ -157,7 +163,9 @@ int32_t RWSplitSession::routeQuery(GWBUF* querybuf)
*/
mxb_assert(m_expected_responses > 0 || m_query_queue);
MXS_INFO("Storing query (len: %d cmd: %0x), expecting %d replies to current command",
gwbuf_length(querybuf), GWBUF_DATA(querybuf)[4], m_expected_responses);
gwbuf_length(querybuf),
GWBUF_DATA(querybuf)[4],
m_expected_responses);
m_query_queue = gwbuf_append(m_query_queue, querybuf);
querybuf = NULL;
rval = 1;
@ -210,7 +218,7 @@ bool RWSplitSession::route_stored_query()
/** Store the query queue locally for the duration of the routeQuery call.
* This prevents recursive calls into this function. */
GWBUF *temp_storage = m_query_queue;
GWBUF* temp_storage = m_query_queue;
m_query_queue = NULL;
// TODO: Move the handling of queued queries to the client protocol
@ -249,7 +257,7 @@ bool RWSplitSession::route_stored_query()
*
* @return Any data after the ERR/OK packet, NULL for no data
*/
GWBUF* RWSplitSession::discard_master_wait_gtid_result(GWBUF *buffer)
GWBUF* RWSplitSession::discard_master_wait_gtid_result(GWBUF* buffer)
{
uint8_t header_and_command[MYSQL_HEADER_LEN + 1];
gwbuf_copy_data(buffer, 0, MYSQL_HEADER_LEN + 1, header_and_command);
@ -280,7 +288,7 @@ GWBUF* RWSplitSession::discard_master_wait_gtid_result(GWBUF *buffer)
*
* @return The correct reference
*/
SRWBackend& RWSplitSession::get_backend_from_dcb(DCB *dcb)
SRWBackend& RWSplitSession::get_backend_from_dcb(DCB* dcb)
{
mxb_assert(dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER);
@ -311,7 +319,7 @@ SRWBackend& RWSplitSession::get_backend_from_dcb(DCB *dcb)
* @param proto MySQLProtocol
*
*/
void RWSplitSession::correct_packet_sequence(GWBUF *buffer)
void RWSplitSession::correct_packet_sequence(GWBUF* buffer)
{
uint8_t header[3];
uint32_t offset = 0;
@ -319,7 +327,7 @@ void RWSplitSession::correct_packet_sequence(GWBUF *buffer)
while (gwbuf_copy_data(buffer, offset, 3, header) == 3)
{
uint32_t packet_len = MYSQL_GET_PAYLOAD_LEN(header) + MYSQL_HEADER_LEN;
uint8_t *seq = gwbuf_byte_pointer(buffer, offset + MYSQL_SEQ_OFFSET);
uint8_t* seq = gwbuf_byte_pointer(buffer, offset + MYSQL_SEQ_OFFSET);
*seq = m_next_seq++;
offset += packet_len;
}
@ -355,27 +363,32 @@ static void log_unexpected_response(SRWBackend& backend, GWBUF* buffer, GWBUF* c
mxb_assert(errcode != ER_CONNECTION_KILLED);
MXS_WARNING("Server '%s' sent an unexpected error: %hu, %s",
backend->name(), errcode, errstr.c_str());
backend->name(),
errcode,
errstr.c_str());
}
else
{
std::string sql = current_query ? mxs::extract_sql(current_query, 1024) : "<not available>";
MXS_ERROR("Unexpected internal state: received response 0x%02hhx from "
"server '%s' when no response was expected. Command: 0x%02hhx "
"Query: %s", mxs_mysql_get_command(buffer), backend->name(),
backend->current_command(), sql.c_str());
"Query: %s",
mxs_mysql_get_command(buffer),
backend->name(),
backend->current_command(),
sql.c_str());
session_dump_statements(backend->dcb()->session);
mxb_assert(false);
}
}
GWBUF* RWSplitSession::handle_causal_read_reply(GWBUF *writebuf, SRWBackend& backend)
GWBUF* RWSplitSession::handle_causal_read_reply(GWBUF* writebuf, SRWBackend& backend)
{
if (m_config.causal_reads)
{
if (GWBUF_IS_REPLY_OK(writebuf) && backend == m_current_master)
{
if (char *tmp = gwbuf_get_property(writebuf, MXS_LAST_GTID))
if (char* tmp = gwbuf_get_property(writebuf, MXS_LAST_GTID))
{
m_gtid_pos = std::string(tmp);
}
@ -429,7 +442,11 @@ void RWSplitSession::trx_replay_next_stmt()
else
{
MXS_INFO("Checksum mismatch, transaction replay failed. Closing connection.");
modutil_send_mysql_err_packet(m_client, 0, 0, 1927, "08S01",
modutil_send_mysql_err_packet(m_client,
0,
0,
1927,
"08S01",
"Transaction checksum mismatch encountered "
"when replaying transaction.");
poll_fake_hangup_event(m_client);
@ -450,9 +467,9 @@ void RWSplitSession::trx_replay_next_stmt()
}
}
void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb)
{
DCB *client_dcb = backend_dcb->session->client_dcb;
DCB* client_dcb = backend_dcb->session->client_dcb;
SRWBackend& backend = get_backend_from_dcb(backend_dcb);
@ -477,7 +494,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
if ((writebuf = handle_causal_read_reply(writebuf, backend)) == NULL)
{
return; // Nothing to route, return
return; // Nothing to route, return
}
if (m_otrx_state == OTRX_ROLLBACK)
@ -492,8 +509,8 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
poll_fake_hangup_event(backend_dcb);
}
}
else if (m_config.transaction_replay && m_can_replay_trx &&
session_trx_is_active(m_client->session))
else if (m_config.transaction_replay && m_can_replay_trx
&& session_trx_is_active(m_client->session))
{
if (!backend->has_session_commands())
{
@ -508,7 +525,7 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
* is intentional.
*/
size_t size{m_trx.size() + m_current_query.length()};
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)
{
@ -578,7 +595,8 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
else
{
MXS_INFO("Reply not yet complete. Waiting for %d replies, got one from %s",
m_expected_responses, backend->name());
m_expected_responses,
backend->name());
}
// Later on we need to know whether we processed a session command
@ -629,11 +647,12 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
ResponseStat& stat = backend->response_stat();
stat.query_ended();
if (stat.is_valid() && (stat.sync_time_reached() ||
backend->server()->response_time->num_samples()==0))
if (stat.is_valid() && (stat.sync_time_reached()
|| backend->server()->response_time->num_samples() == 0))
{
server_add_response_average(backend->server(),
stat.average().secs(), stat.num_samples());
stat.average().secs(),
stat.num_samples());
stat.reset();
}
@ -645,8 +664,8 @@ void RWSplitSession::clientReply(GWBUF *writebuf, DCB *backend_dcb)
m_expected_responses++;
}
}
else if (m_expected_responses == 0 && m_query_queue &&
(!m_is_replay_active || processed_sescmd))
else if (m_expected_responses == 0 && m_query_queue
&& (!m_is_replay_active || processed_sescmd))
{
/**
* All replies received, route any stored queries. This should be done
@ -679,12 +698,13 @@ void check_and_log_backend_state(const SRWBackend& backend, DCB* problem_dcb)
}
else
{
const char *remote = problem_dcb->state == DCB_STATE_POLLING &&
problem_dcb->server ? problem_dcb->server->name : "CLOSED";
const char* remote = problem_dcb->state == DCB_STATE_POLLING
&& problem_dcb->server ? problem_dcb->server->name : "CLOSED";
MXS_ERROR("DCB connected to '%s' is not in use by the router "
"session, not closing it. DCB is in state '%s'",
remote, STRDCBSTATE(problem_dcb->state));
remote,
STRDCBSTATE(problem_dcb->state));
}
}
@ -724,15 +744,15 @@ bool RWSplitSession::start_trx_replay()
* a transaction.
*/
mxb_assert_message(qc_get_trx_type_mask(m_interrupted_query.get()) & QUERY_TYPE_BEGIN_TRX,
"The current query should start a transaction");
"The current query should start a transaction");
retry_query(m_interrupted_query.release(), 0);
}
}
else
{
mxb_assert_message(!session_is_autocommit(m_client->session),
"Session should have autocommit disabled if the transaction "
"had no statements and no query was interrupted");
"Session should have autocommit disabled if the transaction "
"had no statements and no query was interrupted");
}
rval = true;
@ -756,11 +776,13 @@ bool RWSplitSession::start_trx_replay()
* ERRACT_REPLY_CLIENT
* @param succp Result of action: true if router can continue
*/
void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
mxs_error_action_t action, bool *succp)
void RWSplitSession::handleError(GWBUF* errmsgbuf,
DCB* problem_dcb,
mxs_error_action_t action,
bool* succp)
{
mxb_assert(problem_dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER);
MXS_SESSION *session = problem_dcb->session;
MXS_SESSION* session = problem_dcb->session;
mxb_assert(session);
SRWBackend& backend = get_backend_from_dcb(problem_dcb);
@ -814,12 +836,13 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
send_readonly_error(m_client);
}
if (!can_continue && !backend->is_master() &&
!backend->server()->master_err_is_logged)
if (!can_continue && !backend->is_master()
&& !backend->server()->master_err_is_logged)
{
MXS_ERROR("Server %s (%s) lost the master status while waiting"
" for a result. Client sessions will be closed.",
backend->name(), backend->uri());
backend->name(),
backend->uri());
backend->server()->master_err_is_logged = true;
}
}
@ -834,8 +857,8 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
else
{
MXS_INFO("Slave '%s' failed", backend->name());
if (m_target_node && m_target_node == backend &&
session_trx_is_read_only(problem_dcb->session))
if (m_target_node && m_target_node == backend
&& session_trx_is_read_only(problem_dcb->session))
{
// We're no longer locked to this server as it failed
m_target_node.reset();
@ -873,7 +896,7 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
case ERRACT_REPLY_CLIENT:
{
handle_error_reply_client(problem_dcb, errmsgbuf);
*succp = false; /*< no new backend servers were made available */
*succp = false; /*< no new backend servers were made available */
break;
}
@ -899,7 +922,7 @@ void RWSplitSession::handleError(GWBUF *errmsgbuf, DCB *problem_dcb,
* @return true if there are enough backend connections to continue, false if
* not
*/
bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg)
bool RWSplitSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg)
{
SRWBackend& backend = get_backend_from_dcb(backend_dcb);
MXS_SESSION* ses = backend_dcb->session;
@ -915,7 +938,7 @@ bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg
* Try to reroute the statement to a working server or send an error
* to the client.
*/
GWBUF *stored = m_current_query.release();
GWBUF* stored = m_current_query.release();
if (stored && m_config.retry_failed_reads)
{
@ -963,7 +986,8 @@ bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg
}
else
{
succp = m_router->select_connect_backend_servers(ses, m_backends,
succp = m_router->select_connect_backend_servers(ses,
m_backends,
m_current_master,
&m_sescmd_list,
&m_expected_responses,
@ -981,7 +1005,7 @@ bool RWSplitSession::handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg
* @param backend_dcb DCB for the backend server that has failed
* @param errmsg GWBUF containing the error message
*/
void RWSplitSession::handle_error_reply_client(DCB *backend_dcb, GWBUF *errmsg)
void RWSplitSession::handle_error_reply_client(DCB* backend_dcb, GWBUF* errmsg)
{
mxs_session_state_t sesstate = m_client->session->state;
SRWBackend& backend = get_backend_from_dcb(backend_dcb);

View File

@ -10,7 +10,7 @@
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#pragma once
#include "readwritesplit.hh"
#include "rwbackend.hh"
@ -22,20 +22,20 @@
#include <maxscale/modutil.h>
#include <maxscale/queryclassifier.hh>
#define TARGET_IS_MASTER(t) maxscale::QueryClassifier::target_is_master(t)
#define TARGET_IS_SLAVE(t) maxscale::QueryClassifier::target_is_slave(t)
#define TARGET_IS_NAMED_SERVER(t) maxscale::QueryClassifier::target_is_named_server(t)
#define TARGET_IS_ALL(t) maxscale::QueryClassifier::target_is_all(t)
#define TARGET_IS_RLAG_MAX(t) maxscale::QueryClassifier::target_is_rlag_max(t)
#define TARGET_IS_LAST_USED(t) maxscale::QueryClassifier::target_is_last_used(t)
#define TARGET_IS_MASTER(t) maxscale::QueryClassifier::target_is_master(t)
#define TARGET_IS_SLAVE(t) maxscale::QueryClassifier::target_is_slave(t)
#define TARGET_IS_NAMED_SERVER(t) maxscale::QueryClassifier::target_is_named_server(t)
#define TARGET_IS_ALL(t) maxscale::QueryClassifier::target_is_all(t)
#define TARGET_IS_RLAG_MAX(t) maxscale::QueryClassifier::target_is_rlag_max(t)
#define TARGET_IS_LAST_USED(t) maxscale::QueryClassifier::target_is_last_used(t)
typedef std::map<uint32_t, uint32_t> ClientHandleMap; /** External ID to internal ID */
typedef std::map<uint32_t, uint32_t> ClientHandleMap; /** External ID to internal ID */
typedef std::unordered_set<std::string> TableSet;
typedef std::map<uint64_t, uint8_t> ResponseMap;
typedef std::map<uint64_t, uint8_t> ResponseMap;
/** List of slave responses that arrived before the master */
typedef std::list< std::pair<mxs::SRWBackend, uint8_t> > SlaveResponseList;
typedef std::list<std::pair<mxs::SRWBackend, uint8_t>> SlaveResponseList;
/** Map of COM_STMT_EXECUTE targets by internal ID */
typedef std::unordered_map<uint32_t, mxs::SRWBackend> ExecMap;
@ -43,8 +43,8 @@ typedef std::unordered_map<uint32_t, mxs::SRWBackend> ExecMap;
/**
* The client session of a RWSplit instance
*/
class RWSplitSession: public mxs::RouterSession,
private mxs::QueryClassifier::Handler
class RWSplitSession : public mxs::RouterSession
, private mxs::QueryClassifier::Handler
{
RWSplitSession(const RWSplitSession&) = delete;
RWSplitSession& operator=(const RWSplitSession&) = delete;
@ -63,10 +63,10 @@ public:
enum otrx_state
{
OTRX_INACTIVE, // No open transactions
OTRX_STARTING, // Transaction starting on slave
OTRX_ACTIVE, // Transaction open on a slave server
OTRX_ROLLBACK // Transaction being rolled back on the slave server
OTRX_INACTIVE, // No open transactions
OTRX_STARTING, // Transaction starting on slave
OTRX_ACTIVE, // Transaction open on a slave server
OTRX_ROLLBACK // Transaction being rolled back on the slave server
};
enum wait_gtid_state
@ -119,10 +119,10 @@ public:
* @param action The context.
* @param pSuccess On output, if false, the session will be terminated.
*/
void handleError(GWBUF* pMessage,
DCB* pProblem,
void handleError(GWBUF* pMessage,
DCB* pProblem,
mxs_error_action_t action,
bool* pSuccess);
bool* pSuccess);
mxs::QueryClassifier& qc()
{
@ -130,81 +130,91 @@ public:
}
// TODO: Make member variables private
mxs::SRWBackendList m_backends; /**< List of backend servers */
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; /**< 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 */
int m_expected_responses; /**< Number of expected responses to the current query */
GWBUF* m_query_queue; /**< Queued commands waiting to be executed */
RWSplit* m_router; /**< The router instance */
mxs::SessionCommandList m_sescmd_list; /**< List of executed session commands */
ResponseMap m_sescmd_responses; /**< Response to each session command */
SlaveResponseList m_slave_responses; /**< Slaves that replied before the master */
uint64_t m_sent_sescmd; /**< ID of the last sent session command*/
uint64_t m_recv_sescmd; /**< ID of the most recently completed session command */
ClientHandleMap m_ps_handles; /**< Client PS handle to internal ID mapping */
ExecMap m_exec_map; /**< Map of COM_STMT_EXECUTE statement IDs to Backends */
std::string m_gtid_pos; /**< Gtid position for causal read */
wait_gtid_state m_wait_gtid; /**< State of MASTER_GTID_WAIT reply */
uint32_t m_next_seq; /**< Next packet's sequence number */
mxs::QueryClassifier m_qc; /**< The query classifier. */
uint64_t m_retry_duration; /**< Total time spent retrying queries */
mxs::Buffer m_current_query; /**< Current query being executed */
Trx m_trx; /**< Current transaction */
bool m_is_replay_active; /**< Whether we are actively replaying a transaction */
bool m_can_replay_trx; /**< Whether the transaction can be replayed */
Trx m_replayed_trx; /**< The transaction we are replaying */
mxs::Buffer m_interrupted_query; /**< Query that was interrupted mid-transaction. */
otrx_state m_otrx_state = OTRX_INACTIVE; /**< Optimistic trx state*/
mxs::SRWBackendList m_backends; /**< List of backend servers */
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; /**< 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 */
int m_expected_responses; /**< Number of expected responses to the current
* query */
GWBUF* m_query_queue; /**< Queued commands waiting to be executed */
RWSplit* m_router; /**< The router instance */
mxs::SessionCommandList m_sescmd_list; /**< List of executed session commands */
ResponseMap m_sescmd_responses; /**< Response to each session command */
SlaveResponseList m_slave_responses; /**< Slaves that replied before the master */
uint64_t m_sent_sescmd; /**< ID of the last sent session command*/
uint64_t m_recv_sescmd; /**< ID of the most recently completed session
* command */
ClientHandleMap m_ps_handles; /**< Client PS handle to internal ID mapping */
ExecMap m_exec_map; /**< Map of COM_STMT_EXECUTE statement IDs to
* Backends */
std::string m_gtid_pos; /**< Gtid position for causal read */
wait_gtid_state m_wait_gtid; /**< State of MASTER_GTID_WAIT reply */
uint32_t m_next_seq; /**< Next packet's sequence number */
mxs::QueryClassifier m_qc; /**< The query classifier. */
uint64_t m_retry_duration; /**< Total time spent retrying queries */
mxs::Buffer m_current_query; /**< Current query being executed */
Trx m_trx; /**< Current transaction */
bool m_is_replay_active; /**< Whether we are actively replaying a
* transaction */
bool m_can_replay_trx; /**< Whether the transaction can be replayed */
Trx m_replayed_trx; /**< The transaction we are replaying */
mxs::Buffer m_interrupted_query; /**< Query that was interrupted mid-transaction.
* */
otrx_state m_otrx_state = OTRX_INACTIVE; /**< Optimistic trx state*/
private:
RWSplitSession(RWSplit* instance, MXS_SESSION* session,
const mxs::SRWBackendList& backends, const mxs::SRWBackend& master);
RWSplitSession(RWSplit* instance,
MXS_SESSION* session,
const mxs::SRWBackendList& backends,
const mxs::SRWBackend& master);
void process_sescmd_response(mxs::SRWBackend& backend, GWBUF** ppPacket);
void compress_history(mxs::SSessionCommand& sescmd);
bool route_session_write(GWBUF *querybuf, uint8_t command, uint32_t type);
void continue_large_session_write(GWBUF *querybuf, uint32_t type);
bool route_single_stmt(GWBUF *querybuf);
bool route_session_write(GWBUF* querybuf, uint8_t command, uint32_t type);
void continue_large_session_write(GWBUF* querybuf, uint32_t type);
bool route_single_stmt(GWBUF* querybuf);
bool route_stored_query();
mxs::SRWBackend get_hinted_backend(char *name);
mxs::SRWBackend get_hinted_backend(char* name);
mxs::SRWBackend get_slave_backend(int max_rlag);
mxs::SRWBackend get_master_backend();
mxs::SRWBackend get_last_used_backend();
mxs::SRWBackend get_target_backend(backend_type_t btype, char *name, int max_rlag);
mxs::SRWBackend get_target_backend(backend_type_t btype, char* name, int max_rlag);
bool handle_target_is_all(route_target_t route_target, GWBUF *querybuf,
int packet_type, uint32_t qtype);
mxs::SRWBackend handle_hinted_target(GWBUF *querybuf, route_target_t route_target);
bool handle_target_is_all(route_target_t route_target,
GWBUF* querybuf,
int packet_type,
uint32_t qtype);
mxs::SRWBackend handle_hinted_target(GWBUF* querybuf, route_target_t route_target);
mxs::SRWBackend handle_slave_is_target(uint8_t cmd, uint32_t stmt_id);
bool handle_master_is_target(mxs::SRWBackend* dest);
bool handle_got_target(GWBUF* querybuf, mxs::SRWBackend& target, bool store);
void handle_connection_keepalive(mxs::SRWBackend& target);
bool prepare_target(mxs::SRWBackend& target, route_target_t route_target);
void retry_query(GWBUF* querybuf, int delay = 1);
bool handle_master_is_target(mxs::SRWBackend* dest);
bool handle_got_target(GWBUF* querybuf, mxs::SRWBackend& target, bool store);
void handle_connection_keepalive(mxs::SRWBackend& target);
bool prepare_target(mxs::SRWBackend& target, route_target_t route_target);
void retry_query(GWBUF* querybuf, int delay = 1);
bool should_replace_master(mxs::SRWBackend& target);
void replace_master(mxs::SRWBackend& target);
bool should_migrate_trx(mxs::SRWBackend& target);
void log_master_routing_failure(bool found, mxs::SRWBackend& old_master,
void log_master_routing_failure(bool found,
mxs::SRWBackend& old_master,
mxs::SRWBackend& curr_master);
GWBUF* handle_causal_read_reply(GWBUF *writebuf, mxs::SRWBackend& backend);
GWBUF* add_prefix_wait_gtid(SERVER *server, GWBUF *origin);
void correct_packet_sequence(GWBUF *buffer);
GWBUF* discard_master_wait_gtid_result(GWBUF *buffer);
GWBUF* handle_causal_read_reply(GWBUF* writebuf, mxs::SRWBackend& backend);
GWBUF* add_prefix_wait_gtid(SERVER* server, GWBUF* origin);
void correct_packet_sequence(GWBUF* buffer);
GWBUF* discard_master_wait_gtid_result(GWBUF* buffer);
int get_max_replication_lag();
mxs::SRWBackend& get_backend_from_dcb(DCB *dcb);
int get_max_replication_lag();
mxs::SRWBackend& get_backend_from_dcb(DCB* dcb);
void handle_error_reply_client(DCB *backend_dcb, GWBUF *errmsg);
bool handle_error_new_connection(DCB *backend_dcb, GWBUF *errmsg);
void handle_error_reply_client(DCB* backend_dcb, GWBUF* errmsg);
bool handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg);
void trx_replay_next_stmt();
@ -253,9 +263,9 @@ private:
*
* @see handle_trx_replay
*/
return m_config.delayed_retry &&
m_retry_duration < m_config.delayed_retry_timeout &&
!session_trx_is_active(m_client->session);
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
@ -279,9 +289,10 @@ private:
{
if (session_trx_is_ending(m_client->session))
{
atomic_add_uint64(m_qc.is_trx_still_read_only() ?
&m_router->stats().n_ro_trx :
&m_router->stats().n_rw_trx, 1);
atomic_add_uint64(m_qc.is_trx_still_read_only()
? &m_router->stats().n_ro_trx
: &m_router->stats().n_rw_trx,
1);
}
}
};
@ -296,10 +307,22 @@ private:
*/
uint32_t get_internal_ps_id(RWSplitSession* rses, GWBUF* buffer);
#define STRTARGET(t) (t == TARGET_ALL ? "TARGET_ALL" : \
(t == TARGET_MASTER ? "TARGET_MASTER" : \
(t == TARGET_SLAVE ? "TARGET_SLAVE" : \
(t == TARGET_NAMED_SERVER ? "TARGET_NAMED_SERVER" : \
(t == TARGET_RLAG_MAX ? "TARGET_RLAG_MAX" : \
(t == TARGET_UNDEFINED ? "TARGET_UNDEFINED" : \
"Unknown target value"))))))
#define STRTARGET(t) \
(t == TARGET_ALL ? "TARGET_ALL" \
: (t == TARGET_MASTER ? "TARGET_MASTER" \
: (t == TARGET_SLAVE ? "TARGET_SLAVE" \
: (t \
== TARGET_NAMED_SERVER ? \
"TARGET_NAMED_SERVER" \
: (t \
== \
TARGET_RLAG_MAX ? \
"TARGET_RLAG_MAX" \
: ( \
t \
== \
TARGET_UNDEFINED \
? \
"TARGET_UNDEFINED" \
: \
"Unknown target value"))))))

View File

@ -10,7 +10,7 @@
* of this software will be governed by version 2 or later of the General
* Public License.
*/
#pragma once
#pragma once
#include <maxscale/ccdefs.hh>
@ -27,8 +27,8 @@ public:
// A log of executed queries, for transaction replay
typedef std::list<mxs::Buffer> TrxLog;
Trx():
m_size(0)
Trx()
: m_size(0)
{
}
@ -149,7 +149,7 @@ public:
}
private:
mxs::SHA1Checksum m_checksum; /**< Checksum of the transaction */
TrxLog m_log; /**< The transaction contents */
size_t m_size; /**< Transaction size in bytes */
mxs::SHA1Checksum m_checksum; /**< Checksum of the transaction */
TrxLog m_log; /**< The transaction contents */
size_t m_size; /**< Transaction size in bytes */
};