MXS-1516: Validate the connection on each query
A subset of the checks done at connection creation time need to be done at query routing time. This guarantees that the connection is closed if the server no longer qualifies as a valid candidate. Added teset case that checks that a change in the replication topology correctly breaks the connection.
This commit is contained in:
parent
3f0ef7481e
commit
bacc11d28e
@ -514,6 +514,10 @@ add_test_executable(mxs1476.cpp mxs1476 mxs1476 LABELS GALERA_BACKEND)
|
||||
# https://jira.mariadb.org/browse/MXS-1509
|
||||
add_test_executable(mxs1509.cpp mxs1509 mxs1509 LABELS REPL_BACKEND)
|
||||
|
||||
# MXS-1516: existing connection don't change routing, even if master switched
|
||||
# https://jira.mariadb.org/browse/MXS-1516
|
||||
add_test_executable(mxs1516.cpp mxs1516 replication LABELS REPL_BACKEND)
|
||||
|
||||
# MXS-1585: Crash in MaxScale 2.1.12
|
||||
# https://jira.mariadb.org/browse/MXS-1585
|
||||
add_test_executable(mxs1585.cpp mxs1585 mxs1585 LABELS REPL_BACKEND)
|
||||
|
26
maxscale-system-test/mxs1516.cpp
Normal file
26
maxscale-system-test/mxs1516.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* MXS-1516: existing connection don't change routing, even if master switched
|
||||
*
|
||||
* https://jira.mariadb.org/browse/MXS-1516
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
test.connect_maxscale();
|
||||
test.try_query(test.conn_master, "SELECT 1");
|
||||
|
||||
// Change master mid-session
|
||||
test.repl->connect();
|
||||
test.repl->change_master(1, 0);
|
||||
|
||||
test.add_result(execute_query_silent(test.conn_master, "SELECT 1") == 0, "Query should fail");
|
||||
|
||||
// Change the master back to the original one
|
||||
test.repl->change_master(0, 1);
|
||||
|
||||
return test.global_result;
|
||||
}
|
@ -510,7 +510,7 @@ closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session)
|
||||
|
||||
/** Log routing failure due to closed session */
|
||||
static void log_closed_session(mysql_server_cmd_t mysql_command, bool is_closed,
|
||||
SERVER_REF *ref)
|
||||
SERVER_REF *ref, bool valid)
|
||||
{
|
||||
char msg[MAX_SERVER_NAME_LEN + 200] = ""; // Extra space for message
|
||||
|
||||
@ -526,11 +526,44 @@ static void log_closed_session(mysql_server_cmd_t mysql_command, bool is_closed,
|
||||
{
|
||||
sprintf(msg, "Server '%s' is in maintenance.", ref->server->unique_name);
|
||||
}
|
||||
else if (!valid)
|
||||
{
|
||||
sprintf(msg, "Server '%s' no longer qualifies as a target server.",
|
||||
ref->server->unique_name);
|
||||
}
|
||||
|
||||
MXS_ERROR("Failed to route MySQL command %d to backend server. %s",
|
||||
mysql_command, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the server we're connected to is still valid
|
||||
*
|
||||
* @param inst Router instance
|
||||
* @param router_cli_ses Router session
|
||||
*
|
||||
* @return True if the backend connection is still valid
|
||||
*/
|
||||
static inline bool connection_is_valid(ROUTER_INSTANCE* inst, ROUTER_CLIENT_SES* router_cli_ses)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (SERVER_IS_RUNNING(router_cli_ses->backend->server) &&
|
||||
(router_cli_ses->backend->server->status & inst->bitmask & inst->bitvalue))
|
||||
{
|
||||
if (inst->bitvalue & SERVER_MASTER)
|
||||
{
|
||||
rval = router_cli_ses->backend == get_root_master(inst->service->dbref);
|
||||
}
|
||||
else
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* We have data from the client, we must route it to the backend.
|
||||
* This is simply a case of sending it to the connection that was
|
||||
@ -574,10 +607,12 @@ routeQuery(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queu
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
}
|
||||
|
||||
bool valid;
|
||||
|
||||
if (rses_is_closed || backend_dcb == NULL ||
|
||||
!SERVER_IS_RUNNING(router_cli_ses->backend->server))
|
||||
(valid = !connection_is_valid(inst, router_cli_ses)))
|
||||
{
|
||||
log_closed_session(mysql_command, rses_is_closed, router_cli_ses->backend);
|
||||
log_closed_session(mysql_command, rses_is_closed, router_cli_ses->backend, valid);
|
||||
gwbuf_free(queue);
|
||||
goto return_rc;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user