Merge branch '2.3' into 2.4
This commit is contained in:
@ -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.",
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user