Merge branch '2.3' into 2.4

This commit is contained in:
Markus Mäkelä
2019-07-18 12:49:00 +03:00
5 changed files with 55 additions and 36 deletions

View File

@ -21,6 +21,9 @@
#include <netdb.h> #include <netdb.h>
#include <stdio.h> #include <stdio.h>
#include <algorithm>
#include <vector>
#include <maxbase/alloc.h> #include <maxbase/alloc.h>
#include <maxscale/dcb.hh> #include <maxscale/dcb.hh>
#include <maxscale/maxscale.h> #include <maxscale/maxscale.h>
@ -143,7 +146,7 @@ enum server_category_t
SERVER_CLUSTRIX SERVER_CLUSTRIX
}; };
static int get_users(Listener* listener, bool skip_local); static int get_users(Listener* listener, bool skip_local, SERVER** srv);
static MYSQL* gw_mysql_init(void); static MYSQL* gw_mysql_init(void);
static int gw_mysql_set_timeouts(MYSQL* handle); static int gw_mysql_set_timeouts(MYSQL* handle);
static char* mysql_format_user_entry(void* data); static char* mysql_format_user_entry(void* data);
@ -255,9 +258,9 @@ static char* get_users_query(const SERVER::Version& version, bool include_root,
return rval; return rval;
} }
int replace_mysql_users(Listener* listener, bool skip_local) int replace_mysql_users(Listener* listener, bool skip_local, SERVER** srv)
{ {
int i = get_users(listener, skip_local); int i = get_users(listener, skip_local, srv);
return i; return i;
} }
@ -1139,9 +1142,8 @@ bool query_and_process_users(const char* query, MYSQL* con, SERVICE* service, in
return rval; return rval;
} }
int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service, Listener* listener) int get_users_from_server(MYSQL* con, SERVER* server, SERVICE* service, Listener* listener)
{ {
SERVER* server = server_ref->server;
auto server_version = server->version(); auto server_version = server->version();
if (server_version.total == 0) // No monitor or the monitor hasn't ran yet. if (server_version.total == 0) // No monitor or the monitor hasn't ran yet.
{ {
@ -1234,6 +1236,28 @@ int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service,
return users; return users;
} }
// Sorts candidates servers so that masters are before slaves which are before only running servers
static std::vector<SERVER*> get_candidates(SERVICE* service, bool skip_local)
{
std::vector<SERVER*> candidates;
for (auto server = service->dbref; server; server = server->next)
{
if (server_ref_is_active(server) && server->server->is_running()
&& (!skip_local || !server->server->is_mxs_service()))
{
candidates.push_back(server->server);
}
}
std::sort(candidates.begin(), candidates.end(), [](SERVER* a, SERVER* b) {
return (a->is_master() && !b->is_master())
|| (a->is_slave() && !b->is_slave() && !b->is_master());
});
return candidates;
}
/** /**
* Load the user/passwd form mysql.user table into the service users' hashtable * Load the user/passwd form mysql.user table into the service users' hashtable
* environment. * environment.
@ -1242,7 +1266,7 @@ int get_users_from_server(MYSQL* con, SERVER_REF* server_ref, SERVICE* service,
* @param users The users table into which to load the users * @param users The users table into which to load the users
* @return -1 on any error or the number of users inserted * @return -1 on any error or the number of users inserted
*/ */
static int get_users(Listener* listener, bool skip_local) static int get_users(Listener* listener, bool skip_local, SERVER** srv)
{ {
const char* service_user = NULL; const char* service_user = NULL;
const char* service_passwd = NULL; const char* service_passwd = NULL;
@ -1262,33 +1286,18 @@ static int get_users(Listener* listener, bool skip_local)
sqlite3* handle = get_handle(instance); sqlite3* handle = get_handle(instance);
delete_mysql_users(handle); delete_mysql_users(handle);
SERVER_REF* server = service->dbref;
int total_users = -1; int total_users = -1;
bool no_active_servers = true; auto candidates = get_candidates(service, skip_local);
for (server = service->dbref; !maxscale_is_shutting_down() && server; server = server->next) for (auto server : candidates)
{ {
if (!server_ref_is_active(server) || !server->server->server_is_active() if (MYSQL* con = gw_mysql_init())
|| (skip_local && server->server->is_mxs_service())
|| !server->server->is_running())
{ {
continue; if (mxs_mysql_real_connect(con, server, service_user, dpwd) == NULL)
}
no_active_servers = false;
MYSQL* con = gw_mysql_init();
if (con)
{ {
if (mxs_mysql_real_connect(con, server->server, service_user, dpwd) == NULL) MXS_ERROR("Failure loading users data from backend [%s:%i] for service [%s]. "
{ "MySQL error %i, %s", server->address, server->port, service->name(),
MXS_ERROR("Failure loading users data from backend " mysql_errno(con), mysql_error(con));
"[%s:%i] for service [%s]. MySQL error %i, %s",
server->server->address,
server->server->port,
service->name(),
mysql_errno(con),
mysql_error(con));
mysql_close(con); mysql_close(con);
} }
else else
@ -1298,6 +1307,7 @@ static int get_users(Listener* listener, bool skip_local)
if (users > total_users) if (users > total_users)
{ {
*srv = server;
total_users = users; total_users = users;
} }
@ -1313,12 +1323,12 @@ static int get_users(Listener* listener, bool skip_local)
MXS_FREE(dpwd); MXS_FREE(dpwd);
if (no_active_servers) if (candidates.empty())
{ {
// This service has no servers or all servers are local MaxScale services // This service has no servers or all servers are local MaxScale services
total_users = 0; total_users = 0;
} }
else if (server == NULL && total_users == -1) else if (*srv == nullptr && total_users == -1)
{ {
MXS_ERROR("Unable to get user data from backend database for service [%s]." MXS_ERROR("Unable to get user data from backend database for service [%s]."
" Failed to connect to any of the backend databases.", " Failed to connect to any of the backend databases.",

View File

@ -774,7 +774,8 @@ static int mysql_auth_load_users(Listener* port)
first_load = true; first_load = true;
} }
int loaded = replace_mysql_users(port, first_load); SERVER* srv = nullptr;
int loaded = replace_mysql_users(port, first_load, &srv);
bool injected = false; bool injected = false;
if (loaded <= 0) if (loaded <= 0)
@ -821,7 +822,9 @@ static int mysql_auth_load_users(Listener* port)
} }
else if (loaded > 0 && first_load) else if (loaded > 0 && first_load)
{ {
MXS_NOTICE("[%s] Loaded %d MySQL users for listener %s.", service->name(), loaded, port->name()); mxb_assert(srv);
MXS_NOTICE("[%s] Loaded %d MySQL users for listener %s from server %s.",
service->name(), loaded, port->name(), srv->name());
} }
return rc; return rc;

View File

@ -188,10 +188,11 @@ bool dbusers_save(sqlite3* src, const char* filename);
* *
* @param service The current service * @param service The current service
* @param skip_local Skip loading of users on local MaxScale services * @param skip_local Skip loading of users on local MaxScale services
* @param srv Server where the users were loaded from (output)
* *
* @return -1 on any error or the number of users inserted (0 means no users at all) * @return -1 on any error or the number of users inserted (0 means no users at all)
*/ */
int replace_mysql_users(Listener* listener, bool skip_local); int replace_mysql_users(Listener* listener, bool skip_local, SERVER** srv);
/** /**
* @brief Verify the user has access to the database * @brief Verify the user has access to the database

View File

@ -415,8 +415,6 @@ json_t* RWSplit::diagnostics_json() const
for (const auto& a : all_server_stats()) for (const auto& a : all_server_stats())
{ {
mxb_assert(a.second.total == a.second.read + a.second.write);
ServerStats::CurrentStats stats = a.second.current_stats(); ServerStats::CurrentStats stats = a.second.current_stats();
json_t* obj = json_object(); json_t* obj = json_object();

View File

@ -1027,7 +1027,6 @@ void RWSplitSession::handleError(GWBUF* errmsgbuf,
{ {
// We were expecting a response but we aren't going to get one // We were expecting a response but we aren't going to get one
mxb_assert(m_expected_responses > 0); mxb_assert(m_expected_responses > 0);
m_expected_responses--;
errmsg += " Lost connection to master server while waiting for a result."; errmsg += " Lost connection to master server while waiting for a result.";
if (can_retry_query()) if (can_retry_query())
@ -1042,6 +1041,14 @@ void RWSplitSession::handleError(GWBUF* errmsgbuf,
can_continue = true; can_continue = true;
send_readonly_error(m_client); send_readonly_error(m_client);
} }
// Decrement the expected response count only if we know we can continue the sesssion.
// This keeps the internal logic sound even if another query is routed before the session
// is closed.
if (can_continue)
{
m_expected_responses--;
}
} }
if (session_trx_is_active(session) && m_otrx_state == OTRX_INACTIVE) if (session_trx_is_active(session) && m_otrx_state == OTRX_INACTIVE)