Merge branch '2.3' into develop
This commit is contained in:
commit
643514bbe4
@ -943,6 +943,9 @@ add_test_executable(mxs2313_rank.cpp mxs2313_rank mxs2313_rank LABELS readwrites
|
||||
# MXS-2417: Ignore persisted configs with load_persisted_configs=false
|
||||
add_test_executable(mxs2417_ignore_persisted_cnf.cpp mxs2417_ignore_persisted_cnf mxs2417_ignore_persisted_cnf LABELS REPL_BACKEND)
|
||||
|
||||
# MXS-2450: Crash on COM_CHANGE_USER with disable_sescmd_history=true
|
||||
add_test_executable(mxs2450_change_user_crash.cpp mxs2450_change_user_crash mxs2450_change_user_crash LABELS REPL_BACKEND)
|
||||
|
||||
# MXS-1662: PAM admin authentication
|
||||
add_test_executable(mxs1662_pam_admin.cpp mxs1662_pam_admin mxs1662_pam_admin LABELS REPL_BACKEND)
|
||||
|
||||
|
49
maxscale-system-test/cnf/maxscale.cnf.template.mxs2450_change_user_crash
Executable file
49
maxscale-system-test/cnf/maxscale.cnf.template.mxs2450_change_user_crash
Executable file
@ -0,0 +1,49 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
log_info=1
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=###node_server_IP_1###
|
||||
port=###node_server_port_1###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=###node_server_IP_2###
|
||||
port=###node_server_port_2###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=###node_server_IP_3###
|
||||
port=###node_server_port_3###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server4]
|
||||
type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[MySQL Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
monitor_interval=1000
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
password=skysql
|
||||
disable_sescmd_history=true
|
||||
|
||||
[RW Split Listener]
|
||||
type=listener
|
||||
service=RW Split Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
@ -4,17 +4,16 @@
|
||||
#include <string>
|
||||
#include "envv.h"
|
||||
|
||||
Maxscales::Maxscales(const char *pref, const char *test_cwd, bool verbose, bool use_valgrind,
|
||||
Maxscales::Maxscales(const char *pref, const char *test_cwd, bool verbose,
|
||||
std::string network_config)
|
||||
{
|
||||
strcpy(prefix, pref);
|
||||
this->verbose = verbose;
|
||||
this->use_valgrind = use_valgrind;
|
||||
valgring_log_num = 0;
|
||||
strcpy(test_dir, test_cwd);
|
||||
this->network_config = network_config;
|
||||
read_env();
|
||||
if (use_valgrind)
|
||||
if (this->use_valgrind)
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
@ -61,6 +60,13 @@ int Maxscales::read_env()
|
||||
}
|
||||
}
|
||||
|
||||
use_valgrind = readenv_bool("use_valgrind", false);
|
||||
use_callgrind = readenv_bool("use_callgrind", false);
|
||||
if (use_callgrind)
|
||||
{
|
||||
use_valgrind = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -211,10 +217,23 @@ int Maxscales::start_maxscale(int m)
|
||||
int res;
|
||||
if (use_valgrind)
|
||||
{
|
||||
res = ssh_node_f(m, false,
|
||||
"sudo --user=maxscale valgrind --leak-check=full --show-leak-kinds=all "
|
||||
"--log-file=/%s/valgrind%02d.log --trace-children=yes "
|
||||
"--track-origins=yes /usr/bin/maxscale", maxscale_log_dir[m], valgring_log_num);
|
||||
if (use_callgrind)
|
||||
{
|
||||
res = ssh_node_f(m, false,
|
||||
"sudo --user=maxscale valgrind -d "
|
||||
"--log-file=/%s/valgrind%02d.log --trace-children=yes "
|
||||
" --tool=callgrind --callgrind-out-file=/%s/callgrind%02d.log "
|
||||
" /usr/bin/maxscale",
|
||||
maxscale_log_dir[m], valgring_log_num,
|
||||
maxscale_log_dir[m], valgring_log_num);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ssh_node_f(m, false,
|
||||
"sudo --user=maxscale valgrind --leak-check=full --show-leak-kinds=all "
|
||||
"--log-file=/%s/valgrind%02d.log --trace-children=yes "
|
||||
"--track-origins=yes /usr/bin/maxscale", maxscale_log_dir[m], valgring_log_num);
|
||||
}
|
||||
valgring_log_num++;
|
||||
}
|
||||
else
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
READCONN_SLAVE
|
||||
};
|
||||
|
||||
Maxscales(const char *pref, const char *test_cwd, bool verbose, bool use_valgrind,
|
||||
Maxscales(const char *pref, const char *test_cwd, bool verbose,
|
||||
std::string network_config);
|
||||
|
||||
int read_env();
|
||||
@ -338,6 +338,12 @@ public:
|
||||
*/
|
||||
bool use_valgrind;
|
||||
|
||||
/**
|
||||
* @brief use_callgrind if true Maxscale will be executed under Valgrind with
|
||||
* --callgrind option
|
||||
*/
|
||||
bool use_callgrind;
|
||||
|
||||
/**
|
||||
* @brief valgring_log_num Counter for Maxscale restarts to avoid Valgrind log overwriting
|
||||
*/
|
||||
|
20
maxscale-system-test/mxs2450_change_user_crash.cpp
Normal file
20
maxscale-system-test/mxs2450_change_user_crash.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* MXS-2450: Crash on COM_CHANGE_USER with disable_sescmd_history=true
|
||||
* https://jira.mariadb.org/browse/MXS-2450
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
Connection conn = test.maxscales->rwsplit();
|
||||
test.expect(conn.connect(), "Connection failed: %s", conn.error());
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
test.expect(conn.reset_connection(), "Connection reset failed: %s", conn.error());
|
||||
}
|
||||
|
||||
return test.global_result;
|
||||
}
|
@ -139,7 +139,6 @@ TestConnections::TestConnections(int argc, char* argv[])
|
||||
, no_vm_revert(true)
|
||||
, threads(4)
|
||||
, use_ipv6(false)
|
||||
, use_valgrind(false)
|
||||
{
|
||||
std::ios::sync_with_stdio(true);
|
||||
signal_set(SIGSEGV, sigfatal_handler);
|
||||
@ -387,7 +386,7 @@ TestConnections::TestConnections(int argc, char* argv[])
|
||||
galera = NULL;
|
||||
}
|
||||
|
||||
maxscales = new Maxscales("maxscale", test_dir, verbose, use_valgrind, network_config);
|
||||
maxscales = new Maxscales("maxscale", test_dir, verbose, network_config);
|
||||
|
||||
bool maxscale_ok = maxscales->check_nodes();
|
||||
bool repl_ok = no_repl || repl_future.get();
|
||||
@ -517,7 +516,7 @@ TestConnections::~TestConnections()
|
||||
// galera->disable_ssl();
|
||||
}
|
||||
|
||||
if (use_valgrind)
|
||||
if (maxscales->use_valgrind)
|
||||
{
|
||||
// stop all Maxscales to get proper Valgrind logs
|
||||
for (int i = 0; i < maxscales->N; i++)
|
||||
@ -680,7 +679,6 @@ void TestConnections::read_env()
|
||||
revert_snapshot_command = readenv("revert_snapshot_command",
|
||||
"mdbci snapshot revert --path-to-nodes %s --snapshot-name ", mdbci_config_name);
|
||||
no_vm_revert = readenv_bool("no_vm_revert", true);
|
||||
use_valgrind = readenv_bool("use_valgrind", false);
|
||||
}
|
||||
|
||||
void TestConnections::print_env()
|
||||
@ -1478,7 +1476,7 @@ int TestConnections::find_connected_slave1(int m)
|
||||
|
||||
int TestConnections::check_maxscale_processes(int m, int expected)
|
||||
{
|
||||
const char* ps_cmd = use_valgrind ?
|
||||
const char* ps_cmd = maxscales->use_valgrind ?
|
||||
"ps ax | grep valgrind | grep maxscale | grep -v grep | wc -l" :
|
||||
"ps -C maxscale | grep maxscale | wc -l";
|
||||
|
||||
|
@ -686,11 +686,6 @@ public:
|
||||
*/
|
||||
int call_mdbci(const char *options);
|
||||
|
||||
/**
|
||||
* @brief use_valrind if true Maxscale will be executed under Valgrind
|
||||
*/
|
||||
bool use_valgrind;
|
||||
|
||||
/**
|
||||
* @brief resinstall_maxscales Remove Maxscale form all nodes and installs new ones
|
||||
* (to be used for run_test_snapshot)
|
||||
|
@ -203,7 +203,11 @@ void GaleraMonitor::update_server_status(MonitorServer* monitored_server)
|
||||
" ('wsrep_cluster_state_uuid',"
|
||||
" 'wsrep_cluster_size',"
|
||||
" 'wsrep_local_index',"
|
||||
" 'wsrep_local_state')";
|
||||
" 'wsrep_local_state',"
|
||||
" 'wsrep_desync',"
|
||||
" 'wsrep_ready',"
|
||||
" 'wsrep_sst_donor_rejects_queries',"
|
||||
" 'wsrep_reject_queries')";
|
||||
|
||||
if (mxs_mysql_query(monitored_server->con, cluster_member) == 0
|
||||
&& (result = mysql_store_result(monitored_server->con)) != NULL)
|
||||
@ -270,6 +274,42 @@ void GaleraMonitor::update_server_status(MonitorServer* monitored_server)
|
||||
info.local_state = atoi(row[1]);
|
||||
}
|
||||
|
||||
/* Node is in desync - lets take it offline */
|
||||
if (strcmp(row[0], "wsrep_desync") == 0)
|
||||
{
|
||||
if (strcasecmp(row[1],"YES") || strcasecmp(row[1],"ON") || strcasecmp(row[1],"1") || strcasecmp(row[1],"true"))
|
||||
{
|
||||
info.joined = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Node rejects queries - lets take it offline */
|
||||
if (strcmp(row[0], "wsrep_reject_queries") == 0)
|
||||
{
|
||||
if (strcasecmp(row[1],"ALL") || strcasecmp(row[1],"ALL_KILL"))
|
||||
{
|
||||
info.joined = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Node rejects queries - lets take it offline */
|
||||
if (strcmp(row[0], "wsrep_sst_donor_rejects_queries") == 0)
|
||||
{
|
||||
if (strcasecmp(row[1],"YES") || strcasecmp(row[1],"ON") || strcasecmp(row[1],"1") || strcasecmp(row[1],"true"))
|
||||
{
|
||||
info.joined = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Node is not ready - lets take it offline */
|
||||
if (strcmp(row[0], "wsrep_ready") == 0)
|
||||
{
|
||||
if (strcasecmp(row[1],"NO") || strcasecmp(row[1],"OFF") || strcasecmp(row[1],"0") || strcasecmp(row[1],"false"))
|
||||
{
|
||||
info.joined = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(row[0], "wsrep_cluster_state_uuid") == 0 && row[1] && *row[1])
|
||||
{
|
||||
info.cluster_uuid = row[1];
|
||||
|
@ -608,7 +608,7 @@ bool RWSplitSession::route_session_write(GWBUF* querybuf, uint8_t command, uint3
|
||||
return nsucc;
|
||||
}
|
||||
|
||||
RWBackend* RWSplitSession::get_hinted_backend(char* name)
|
||||
RWBackend* RWSplitSession::get_hinted_backend(const char* name)
|
||||
{
|
||||
RWBackend* rval = nullptr;
|
||||
|
||||
@ -669,15 +669,15 @@ RWBackend* RWSplitSession::get_last_used_backend()
|
||||
*
|
||||
* @param rses Pointer to router client session
|
||||
* @param btype Backend type
|
||||
* @param name Name of the backend which is primarily searched. May be NULL.
|
||||
* @param name Name of the requested backend. May be NULL if any name is accepted.
|
||||
* @param max_rlag Maximum replication lag
|
||||
* @param target The target backend
|
||||
*
|
||||
* @return True if a backend was found
|
||||
*/
|
||||
RWBackend* RWSplitSession::get_target_backend(backend_type_t btype,
|
||||
char* name,
|
||||
int max_rlag)
|
||||
const 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))
|
||||
@ -686,13 +686,11 @@ RWBackend* RWSplitSession::get_target_backend(backend_type_t btype,
|
||||
}
|
||||
|
||||
RWBackend* rval = nullptr;
|
||||
|
||||
if (name) /*< Choose backend by name from a hint */
|
||||
if (name)
|
||||
{
|
||||
btype = BE_SLAVE;
|
||||
// Choose backend by name from a hint
|
||||
rval = get_hinted_backend(name);
|
||||
}
|
||||
|
||||
else if (btype == BE_SLAVE)
|
||||
{
|
||||
rval = get_slave_backend(max_rlag);
|
||||
@ -701,7 +699,6 @@ RWBackend* RWSplitSession::get_target_backend(backend_type_t btype,
|
||||
{
|
||||
rval = get_master_backend();
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
@ -738,80 +735,72 @@ int RWSplitSession::get_max_replication_lag()
|
||||
*/
|
||||
RWBackend* RWSplitSession::handle_hinted_target(GWBUF* querybuf, route_target_t route_target)
|
||||
{
|
||||
char* named_server = NULL;
|
||||
int rlag_max = SERVER::RLAG_UNDEFINED;
|
||||
const char rlag_hint_tag[] = "max_slave_replication_lag";
|
||||
const int comparelen = sizeof(rlag_hint_tag);
|
||||
int config_max_rlag = get_max_replication_lag(); // From router configuration.
|
||||
RWBackend* target = nullptr;
|
||||
|
||||
HINT* hint = querybuf->hint;
|
||||
|
||||
while (hint != NULL)
|
||||
for (HINT* hint = querybuf->hint; !target && hint; hint = hint->next)
|
||||
{
|
||||
if (hint->type == HINT_ROUTE_TO_NAMED_SERVER)
|
||||
{
|
||||
/**
|
||||
* Set the name of searched
|
||||
* backend server.
|
||||
*/
|
||||
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))
|
||||
{
|
||||
int val = (int)strtol((char*)hint->value, (char**)NULL, 10);
|
||||
|
||||
if (val != 0 || errno == 0)
|
||||
// Set the name of searched backend server.
|
||||
const char* named_server = (char*)hint->data;
|
||||
MXS_INFO("Hint: route to server '%s'.", named_server);
|
||||
target = get_target_backend(BE_UNDEFINED, named_server, config_max_rlag);
|
||||
if (!target)
|
||||
{
|
||||
/** Set max. acceptable replication lag value for backend srv */
|
||||
rlag_max = val;
|
||||
MXS_INFO("Hint: max_slave_replication_lag=%d", rlag_max);
|
||||
// Target may differ from the requested name if the routing target is locked, e.g. by a trx.
|
||||
// Target is null only if not locked and named server was not found or was invalid.
|
||||
if (mxb_log_is_priority_enabled(LOG_INFO))
|
||||
{
|
||||
std::string status;
|
||||
for (const auto& a : m_backends)
|
||||
{
|
||||
if (strcmp(a->server()->name(), named_server) == 0)
|
||||
{
|
||||
status = a->server()->status_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
MXS_INFO("Was supposed to route to named server %s but couldn't find the server in a "
|
||||
"suitable state. Server state: %s",
|
||||
named_server, !status.empty() ? status.c_str() : "Could not find server");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hint->type == HINT_PARAMETER
|
||||
&& (strncasecmp((char*)hint->data, rlag_hint_tag, comparelen) == 0))
|
||||
{
|
||||
const char* str_val = (char*)hint->value;
|
||||
int hint_max_rlag = (int)strtol(str_val, (char**)NULL, 10);
|
||||
if (hint_max_rlag != 0 || errno == 0)
|
||||
{
|
||||
MXS_INFO("Hint: %s=%d", rlag_hint_tag, hint_max_rlag);
|
||||
target = get_target_backend(BE_SLAVE, nullptr, hint_max_rlag);
|
||||
if (!target)
|
||||
{
|
||||
MXS_INFO("Was supposed to route to server with replication lag "
|
||||
"at most %d but couldn't find such a slave.", hint_max_rlag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Hint: Could not parse value of %s: '%s' is not a valid number.",
|
||||
rlag_hint_tag, str_val);
|
||||
}
|
||||
}
|
||||
hint = hint->next;
|
||||
} /*< while */
|
||||
|
||||
if (rlag_max == SERVER::RLAG_UNDEFINED) /*< no rlag max hint, use config */
|
||||
{
|
||||
rlag_max = get_max_replication_lag();
|
||||
}
|
||||
|
||||
/** target may be master or slave */
|
||||
backend_type_t btype = route_target & TARGET_SLAVE ? BE_SLAVE : BE_MASTER;
|
||||
|
||||
/**
|
||||
* Search backend server by name or replication lag.
|
||||
* If it fails, then try to find valid slave or master.
|
||||
*/
|
||||
RWBackend* target = get_target_backend(btype, named_server, rlag_max);
|
||||
|
||||
if (!target)
|
||||
{
|
||||
if (TARGET_IS_NAMED_SERVER(route_target))
|
||||
{
|
||||
std::string status = "Could not find server";
|
||||
// If no target so far, pick any available. TODO: should this be error instead?
|
||||
// Erroring here is more appropriate when namedserverfilter allows setting multiple target types
|
||||
// e.g. target=server1,->slave
|
||||
|
||||
for (const auto& a : m_backends)
|
||||
{
|
||||
if (strcmp(a->server()->name(), named_server) == 0)
|
||||
{
|
||||
status = a->server()->status_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MXS_INFO("Was supposed to route to named server %s but couldn't find the server in a "
|
||||
"suitable state. Server state: %s", named_server, status.c_str());
|
||||
}
|
||||
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);
|
||||
}
|
||||
backend_type_t btype = route_target & TARGET_SLAVE ? BE_SLAVE : BE_MASTER;
|
||||
target = get_target_backend(btype, NULL, config_max_rlag);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,10 @@ void RWSplitSession::process_sescmd_response(RWBackend* backend, GWBUF** ppPacke
|
||||
*ppPacket = NULL;
|
||||
}
|
||||
|
||||
if (m_expected_responses == 0
|
||||
if (m_expected_responses == 0 && !m_config.disable_sescmd_history
|
||||
&& (command == MXS_COM_CHANGE_USER || command == MXS_COM_RESET_CONNECTION))
|
||||
{
|
||||
mxb_assert_message(!m_sescmd_list.empty(), "Must have stored session commands");
|
||||
mxb_assert_message(m_slave_responses.empty(), "All responses should've been processed");
|
||||
// This is the last session command to finish that resets the session state, reset the history
|
||||
MXS_INFO("Resetting session command history (length: %lu)", m_sescmd_list.size());
|
||||
|
@ -146,11 +146,11 @@ private:
|
||||
void close_stale_connections();
|
||||
|
||||
int64_t get_current_rank();
|
||||
mxs::RWBackend* get_hinted_backend(char* name);
|
||||
mxs::RWBackend* get_hinted_backend(const char* name);
|
||||
mxs::RWBackend* get_slave_backend(int max_rlag);
|
||||
mxs::RWBackend* get_master_backend();
|
||||
mxs::RWBackend* get_last_used_backend();
|
||||
mxs::RWBackend* get_target_backend(backend_type_t btype, char* name, int max_rlag);
|
||||
mxs::RWBackend* get_target_backend(backend_type_t btype, const char* name, int max_rlag);
|
||||
|
||||
bool handle_target_is_all(route_target_t route_target,
|
||||
GWBUF* querybuf,
|
||||
|
Loading…
x
Reference in New Issue
Block a user