MXS-2220 Store server parameters in stl containers
The custom parameters are now protected from concurrent access.
This commit is contained in:
@ -39,15 +39,6 @@ const int MAINTENANCE_ON = 100;
|
|||||||
const int MAINTENANCE_FLAG_NOCHECK = 0;
|
const int MAINTENANCE_FLAG_NOCHECK = 0;
|
||||||
const int MAINTENANCE_FLAG_CHECK = -1;
|
const int MAINTENANCE_FLAG_CHECK = -1;
|
||||||
|
|
||||||
/* Custom server parameters. These can be used by modules for e.g. weighting routing decisions. */
|
|
||||||
struct SERVER_PARAM
|
|
||||||
{
|
|
||||||
char* name; /**< Parameter name */
|
|
||||||
char* value; /**< Parameter value */
|
|
||||||
bool active; /**< Whether the parameter is valid */
|
|
||||||
struct SERVER_PARAM* next; /**< Next Paramter in the linked list */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Server connection and usage statistics */
|
/* Server connection and usage statistics */
|
||||||
struct SERVER_STATS
|
struct SERVER_STATS
|
||||||
{
|
{
|
||||||
@ -119,8 +110,7 @@ public:
|
|||||||
char monpw[MAX_MONPW_LEN] = {'\0'}; /**< Monitor password, overrides monitor setting */
|
char monpw[MAX_MONPW_LEN] = {'\0'}; /**< Monitor password, overrides monitor setting */
|
||||||
bool proxy_protocol = false; /**< Send proxy-protocol header to backends when connecting
|
bool proxy_protocol = false; /**< Send proxy-protocol header to backends when connecting
|
||||||
* routing sessions. */
|
* routing sessions. */
|
||||||
SERVER_PARAM* parameters = nullptr; /**< Additional custom parameters which may affect routing
|
|
||||||
* decisions. */
|
|
||||||
// Base variables
|
// Base variables
|
||||||
bool is_active = false; /**< Server is active and has not been "destroyed" */
|
bool is_active = false; /**< Server is active and has not been "destroyed" */
|
||||||
void* auth_instance = nullptr; /**< Authenticator instance data */
|
void* auth_instance = nullptr; /**< Authenticator instance data */
|
||||||
@ -182,6 +172,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool persistent_conns_enabled() const = 0;
|
virtual bool persistent_conns_enabled() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch value of custom parameter.
|
||||||
|
*
|
||||||
|
* @param name Parameter name
|
||||||
|
* @return Value of parameter, or empty if not found
|
||||||
|
*/
|
||||||
|
virtual std::string get_custom_parameter(const std::string& name) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SERVER()
|
SERVER()
|
||||||
{
|
{
|
||||||
@ -383,18 +381,6 @@ inline bool server_is_disk_space_exhausted(const SERVER* server)
|
|||||||
return status_is_disk_space_exhausted(server->status);
|
return status_is_disk_space_exhausted(server->status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Serialize a server to a file
|
|
||||||
*
|
|
||||||
* This converts @c server into an INI format file. This allows created servers
|
|
||||||
* to be persisted to disk. This will replace any existing files with the same
|
|
||||||
* name.
|
|
||||||
*
|
|
||||||
* @param server Server to serialize
|
|
||||||
* @return False if the serialization of the server fails, true if it was successful
|
|
||||||
*/
|
|
||||||
bool server_serialize(const SERVER* server);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a server parameter
|
* @brief Add a server parameter
|
||||||
*
|
*
|
||||||
@ -404,24 +390,6 @@ bool server_serialize(const SERVER* server);
|
|||||||
*/
|
*/
|
||||||
void server_add_parameter(SERVER* server, const char* name, const char* value);
|
void server_add_parameter(SERVER* server, const char* name, const char* value);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove a server parameter
|
|
||||||
*
|
|
||||||
* @param server Server to remove the parameter from
|
|
||||||
* @param name The name of the parameter to remove
|
|
||||||
* @return True if a parameter was removed
|
|
||||||
*/
|
|
||||||
bool server_remove_parameter(SERVER* server, const char* name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set server parameter
|
|
||||||
*
|
|
||||||
* @param server Server to update
|
|
||||||
* @param name Parameter to set
|
|
||||||
* @param value Value of parameter
|
|
||||||
*/
|
|
||||||
void server_set_parameter(SERVER* server, const char* name, const char* value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if a server points to a local MaxScale service
|
* @brief Check if a server points to a local MaxScale service
|
||||||
*
|
*
|
||||||
@ -430,16 +398,6 @@ void server_set_parameter(SERVER* server, const char* name, const char* value);
|
|||||||
*/
|
*/
|
||||||
bool server_is_mxs_service(const SERVER* server);
|
bool server_is_mxs_service(const SERVER* server);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert a server to JSON format
|
|
||||||
*
|
|
||||||
* @param server Server to convert
|
|
||||||
* @param host Hostname of this server
|
|
||||||
*
|
|
||||||
* @return JSON representation of server or NULL if an error occurred
|
|
||||||
*/
|
|
||||||
json_t* server_to_json(const SERVER* server, const char* host);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert all servers into JSON format
|
* @brief Convert all servers into JSON format
|
||||||
*
|
*
|
||||||
@ -478,7 +436,6 @@ extern void server_set_status_nolock(SERVER* server, uint64_t bit);
|
|||||||
extern void server_clear_status_nolock(SERVER* server, uint64_t bit);
|
extern void server_clear_status_nolock(SERVER* server, uint64_t bit);
|
||||||
extern void server_transfer_status(SERVER* dest_server, const SERVER* source_server);
|
extern void server_transfer_status(SERVER* dest_server, const SERVER* source_server);
|
||||||
extern void server_add_mon_user(SERVER* server, const char* user, const char* passwd);
|
extern void server_add_mon_user(SERVER* server, const char* user, const char* passwd);
|
||||||
extern size_t server_get_parameter(const SERVER* server, const char* name, char* out, size_t size);
|
|
||||||
extern void server_update_credentials(SERVER* server, const char* user, const char* passwd);
|
extern void server_update_credentials(SERVER* server, const char* user, const char* passwd);
|
||||||
extern void server_update_address(SERVER* server, const char* address);
|
extern void server_update_address(SERVER* server, const char* address);
|
||||||
extern void server_update_port(SERVER* server, unsigned short port);
|
extern void server_update_port(SERVER* server, unsigned short port);
|
||||||
|
@ -244,7 +244,7 @@ bool runtime_create_server(const char* name,
|
|||||||
|
|
||||||
Server* server = Server::server_alloc(name, ctx.parameters);
|
Server* server = Server::server_alloc(name, ctx.parameters);
|
||||||
|
|
||||||
if (server && server_serialize(server))
|
if (server && server->serialize())
|
||||||
{
|
{
|
||||||
rval = true;
|
rval = true;
|
||||||
MXS_NOTICE("Created server '%s' at %s:%u",
|
MXS_NOTICE("Created server '%s' at %s:%u",
|
||||||
@ -383,7 +383,7 @@ bool runtime_enable_server_ssl(Server* server,
|
|||||||
atomic_synchronize();
|
atomic_synchronize();
|
||||||
server->server_ssl = ssl;
|
server->server_ssl = ssl;
|
||||||
|
|
||||||
if (server_serialize(server))
|
if (server->serialize())
|
||||||
{
|
{
|
||||||
MXS_NOTICE("Enabled SSL for server '%s'", server->name);
|
MXS_NOTICE("Enabled SSL for server '%s'", server->name);
|
||||||
rval = true;
|
rval = true;
|
||||||
@ -476,7 +476,7 @@ bool runtime_alter_server(Server* server, const char* key, const char* value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> guard(crt_lock);
|
std::lock_guard<std::mutex> guard(crt_lock);
|
||||||
server_set_parameter(server, key, value);
|
server->set_parameter(key, value);
|
||||||
|
|
||||||
if (strcmp(key, CN_ADDRESS) == 0)
|
if (strcmp(key, CN_ADDRESS) == 0)
|
||||||
{
|
{
|
||||||
@ -524,7 +524,7 @@ bool runtime_alter_server(Server* server, const char* key, const char* value)
|
|||||||
service_update_weights();
|
service_update_weights();
|
||||||
}
|
}
|
||||||
|
|
||||||
server_serialize(server);
|
server->serialize();
|
||||||
MXS_NOTICE("Updated server '%s': %s=%s", server->name, key, value);
|
MXS_NOTICE("Updated server '%s': %s=%s", server->name, key, value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <maxbase/ccdefs.hh>
|
#include <maxbase/ccdefs.hh>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <maxbase/average.hh>
|
#include <maxbase/average.hh>
|
||||||
#include <maxscale/config.hh>
|
#include <maxscale/config.hh>
|
||||||
@ -36,6 +37,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ConfigParameter
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
int response_time_num_samples() const
|
int response_time_num_samples() const
|
||||||
{
|
{
|
||||||
return m_response_time.num_samples();
|
return m_response_time.num_samples();
|
||||||
@ -133,6 +140,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
static Server* find_by_unique_name(const std::string& name);
|
static Server* find_by_unique_name(const std::string& name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if name is a normal server setting name.
|
||||||
|
*
|
||||||
|
* @param name Name to check
|
||||||
|
* @return True if name is a standard parameter
|
||||||
|
*/
|
||||||
|
bool is_custom_parameter(const std::string& name) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print server details to a DCB
|
* Print server details to a DCB
|
||||||
*
|
*
|
||||||
@ -168,6 +183,32 @@ public:
|
|||||||
*/
|
*/
|
||||||
static void dListServers(DCB*);
|
static void dListServers(DCB*);
|
||||||
|
|
||||||
|
static bool create_server_config(const Server* server, const char* filename);
|
||||||
|
|
||||||
|
static json_t* server_json_attributes(const Server* server);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set server parameter
|
||||||
|
*
|
||||||
|
* @param server Server to update
|
||||||
|
* @param name Parameter to set
|
||||||
|
* @param value Value of parameter
|
||||||
|
*/
|
||||||
|
void set_parameter(const std::string& name, const std::string& value);
|
||||||
|
|
||||||
|
std::string get_custom_parameter(const std::string& name) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Serialize a server to a file
|
||||||
|
*
|
||||||
|
* This converts @c server into an INI format file. This allows created servers
|
||||||
|
* to be persisted to disk. This will replace any existing files with the same
|
||||||
|
* name.
|
||||||
|
*
|
||||||
|
* @return False if the serialization of the server fails, true if it was successful
|
||||||
|
*/
|
||||||
|
bool serialize() const;
|
||||||
|
|
||||||
mutable std::mutex m_lock;
|
mutable std::mutex m_lock;
|
||||||
DCB** persistent = nullptr; /**< List of unused persistent connections to the server */
|
DCB** persistent = nullptr; /**< List of unused persistent connections to the server */
|
||||||
|
|
||||||
@ -175,7 +216,16 @@ private:
|
|||||||
struct Settings
|
struct Settings
|
||||||
{
|
{
|
||||||
mutable std::mutex lock; /**< Protects array-like settings from concurrent access */
|
mutable std::mutex lock; /**< Protects array-like settings from concurrent access */
|
||||||
MxsDiskSpaceThreshold disk_space_limits; /**< Disk space thresholds */
|
|
||||||
|
/** Disk space thresholds. Can be queried from modules at any time so access must be protected
|
||||||
|
* by mutex. */
|
||||||
|
MxsDiskSpaceThreshold disk_space_limits;
|
||||||
|
/** All config settings in text form. This is only read and written from the admin thread
|
||||||
|
* so no need for locking. */
|
||||||
|
std::vector<ConfigParameter> all_parameters;
|
||||||
|
/** Additional custom parameters which may affect routing decisions or the monitor module.
|
||||||
|
* Can be queried from modules at any time so access must be protected by mutex. */
|
||||||
|
std::map<std::string, std::string> custom_parameters;
|
||||||
|
|
||||||
long persistpoolmax = 0; /**< Maximum size of persistent connections pool */
|
long persistpoolmax = 0; /**< Maximum size of persistent connections pool */
|
||||||
long persistmaxtime = 0; /**< Maximum number of seconds connection can live */
|
long persistmaxtime = 0; /**< Maximum number of seconds connection can live */
|
||||||
@ -186,3 +236,12 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void server_free(Server* server);
|
void server_free(Server* server);
|
||||||
|
/**
|
||||||
|
* @brief Convert a server to JSON format
|
||||||
|
*
|
||||||
|
* @param server Server to convert
|
||||||
|
* @param host Hostname of this server
|
||||||
|
*
|
||||||
|
* @return JSON representation of server or NULL if an error occurred
|
||||||
|
*/
|
||||||
|
json_t* server_to_json(const Server* server, const char* host);
|
||||||
|
@ -548,7 +548,7 @@ HttpResponse cb_all_servers(const HttpRequest& request)
|
|||||||
|
|
||||||
HttpResponse cb_get_server(const HttpRequest& request)
|
HttpResponse cb_get_server(const HttpRequest& request)
|
||||||
{
|
{
|
||||||
SERVER* server = server_find_by_unique_name(request.uri_part(1).c_str());
|
auto server = Server::find_by_unique_name(request.uri_part(1));
|
||||||
mxb_assert(server);
|
mxb_assert(server);
|
||||||
return HttpResponse(MHD_HTTP_OK, server_to_json(server, request.host()));
|
return HttpResponse(MHD_HTTP_OK, server_to_json(server, request.host()));
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ static const char ERR_CANNOT_MODIFY[] = "The server is monitored, so only the ma
|
|||||||
"set/cleared manually. Status was not modified.";
|
"set/cleared manually. Status was not modified.";
|
||||||
static const char WRN_REQUEST_OVERWRITTEN[] = "Previous maintenance request was not yet read by the monitor "
|
static const char WRN_REQUEST_OVERWRITTEN[] = "Previous maintenance request was not yet read by the monitor "
|
||||||
"and was overwritten.";
|
"and was overwritten.";
|
||||||
static void server_parameter_free(SERVER_PARAM* tofree);
|
|
||||||
|
|
||||||
|
|
||||||
Server* Server::server_alloc(const char* name, MXS_CONFIG_PARAMETER* params)
|
Server* Server::server_alloc(const char* name, MXS_CONFIG_PARAMETER* params)
|
||||||
{
|
{
|
||||||
@ -170,7 +168,11 @@ Server* Server::server_alloc(const char* name, MXS_CONFIG_PARAMETER* params)
|
|||||||
|
|
||||||
for (MXS_CONFIG_PARAMETER* p = params; p; p = p->next)
|
for (MXS_CONFIG_PARAMETER* p = params; p; p = p->next)
|
||||||
{
|
{
|
||||||
server_set_parameter(server, p->name, p->value);
|
server->m_settings.all_parameters.push_back({p->name, p->value});
|
||||||
|
if (server->is_custom_parameter(p->name))
|
||||||
|
{
|
||||||
|
server->set_parameter(p->name, p->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Guard guard(server_lock);
|
Guard guard(server_lock);
|
||||||
@ -202,7 +204,6 @@ void server_free(Server* server)
|
|||||||
MXS_FREE(server->protocol);
|
MXS_FREE(server->protocol);
|
||||||
MXS_FREE(server->name);
|
MXS_FREE(server->name);
|
||||||
MXS_FREE(server->authenticator);
|
MXS_FREE(server->authenticator);
|
||||||
server_parameter_free(server->parameters);
|
|
||||||
|
|
||||||
if (server->persistent)
|
if (server->persistent)
|
||||||
{
|
{
|
||||||
@ -482,20 +483,14 @@ void Server::print_to_dcb(DCB* dcb) const
|
|||||||
"\tLast Repl Heartbeat: %s",
|
"\tLast Repl Heartbeat: %s",
|
||||||
asctime_r(localtime_r((time_t*)(&server->node_ts), &result), buf));
|
asctime_r(localtime_r((time_t*)(&server->node_ts), &result), buf));
|
||||||
}
|
}
|
||||||
SERVER_PARAM* param;
|
|
||||||
if ((param = server->parameters))
|
if (!server->m_settings.all_parameters.empty())
|
||||||
{
|
{
|
||||||
dcb_printf(dcb, "\tServer Parameters:\n");
|
dcb_printf(dcb, "\tServer Parameters:\n");
|
||||||
while (param)
|
for (const auto& elem : server->m_settings.all_parameters)
|
||||||
{
|
{
|
||||||
if (param->active)
|
dcb_printf(dcb, "\t %s\t%s\n",
|
||||||
{
|
elem.name.c_str(), elem.value.c_str());
|
||||||
dcb_printf(dcb,
|
|
||||||
"\t %s\t%s\n",
|
|
||||||
param->name,
|
|
||||||
param->value);
|
|
||||||
}
|
|
||||||
param = param->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dcb_printf(dcb, "\tNumber of connections: %d\n", server->stats.n_connections);
|
dcb_printf(dcb, "\tNumber of connections: %d\n", server->stats.n_connections);
|
||||||
@ -789,130 +784,39 @@ void server_update_credentials(SERVER* server, const char* user, const char* pas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SERVER_PARAM* allocate_parameter(const char* name, const char* value)
|
void Server::set_parameter(const string& name, const string& value)
|
||||||
{
|
{
|
||||||
char* my_name = MXS_STRDUP(name);
|
// Set/add the parameter in both containers
|
||||||
char* my_value = MXS_STRDUP(value);
|
bool found = false;
|
||||||
|
for (auto& elem : m_settings.all_parameters)
|
||||||
SERVER_PARAM* param = (SERVER_PARAM*)MXS_MALLOC(sizeof(SERVER_PARAM));
|
|
||||||
|
|
||||||
if (!my_name || !my_value || !param)
|
|
||||||
{
|
{
|
||||||
MXS_FREE(my_name);
|
if (name == elem.name)
|
||||||
MXS_FREE(my_value);
|
|
||||||
MXS_FREE(param);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
param->active = true;
|
|
||||||
param->name = my_name;
|
|
||||||
param->value = my_value;
|
|
||||||
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool server_remove_parameter(SERVER* srv, const char* name)
|
|
||||||
{
|
{
|
||||||
Server* server = static_cast<Server*>(srv);
|
found = true;
|
||||||
bool rval = false;
|
elem.value = value; // Update
|
||||||
std::lock_guard<std::mutex> guard(server->m_lock);
|
|
||||||
|
|
||||||
for (SERVER_PARAM* p = server->parameters; p; p = p->next)
|
|
||||||
{
|
|
||||||
if (strcmp(p->name, name) == 0 && p->active)
|
|
||||||
{
|
|
||||||
p->active = false;
|
|
||||||
rval = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
m_settings.all_parameters.push_back({name, value});
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> guard(m_settings.lock);
|
||||||
|
m_settings.custom_parameters[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
string Server::get_custom_parameter(const string& name) const
|
||||||
|
{
|
||||||
|
string rval;
|
||||||
|
std::lock_guard<std::mutex> guard(m_settings.lock);
|
||||||
|
auto iter = m_settings.custom_parameters.find(name);
|
||||||
|
if (iter != m_settings.custom_parameters.end())
|
||||||
|
{
|
||||||
|
rval = iter->second;
|
||||||
|
}
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_set_parameter(SERVER* srv, const char* name, const char* value)
|
|
||||||
{
|
|
||||||
Server* server = static_cast<Server*>(srv);
|
|
||||||
SERVER_PARAM* param = allocate_parameter(name, value);
|
|
||||||
|
|
||||||
if (param)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> guard(server->m_lock);
|
|
||||||
|
|
||||||
// Insert new value
|
|
||||||
param->next = server->parameters;
|
|
||||||
server->parameters = param;
|
|
||||||
|
|
||||||
// Mark old value, if found, as inactive
|
|
||||||
for (SERVER_PARAM* p = server->parameters->next; p; p = p->next)
|
|
||||||
{
|
|
||||||
if (strcmp(p->name, name) == 0 && p->active)
|
|
||||||
{
|
|
||||||
p->active = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free a list of server parameters
|
|
||||||
* @param tofree Parameter list to free
|
|
||||||
*/
|
|
||||||
static void server_parameter_free(SERVER_PARAM* tofree)
|
|
||||||
{
|
|
||||||
SERVER_PARAM* param;
|
|
||||||
|
|
||||||
if (tofree)
|
|
||||||
{
|
|
||||||
param = tofree;
|
|
||||||
tofree = tofree->next;
|
|
||||||
MXS_FREE(param->name);
|
|
||||||
MXS_FREE(param->value);
|
|
||||||
MXS_FREE(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as server_get_parameter but doesn't lock the server
|
|
||||||
*
|
|
||||||
* @note Should only be called when the server is already locked
|
|
||||||
*/
|
|
||||||
static size_t server_get_parameter_nolock(const SERVER* server, const char* name, char* out, size_t size)
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
SERVER_PARAM* param = server->parameters;
|
|
||||||
|
|
||||||
while (param)
|
|
||||||
{
|
|
||||||
if (strcmp(param->name, name) == 0 && param->active)
|
|
||||||
{
|
|
||||||
len = snprintf(out, out ? size : 0, "%s", param->value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
param = param->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve a parameter value from a server
|
|
||||||
*
|
|
||||||
* @param server The server we are looking for a parameter of
|
|
||||||
* @param name The name of the parameter we require
|
|
||||||
* @param out Buffer where value is stored, use NULL to check if the parameter exists
|
|
||||||
* @param size Size of @c out, ignored if @c out is NULL
|
|
||||||
*
|
|
||||||
* @return Length of the parameter value or 0 if parameter was not found
|
|
||||||
*/
|
|
||||||
size_t server_get_parameter(const SERVER* srv, const char* name, char* out, size_t size)
|
|
||||||
{
|
|
||||||
const Server* server = static_cast<const Server*>(srv);
|
|
||||||
std::lock_guard<std::mutex> guard(server->m_lock);
|
|
||||||
return server_get_parameter_nolock(server, name, out, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a resultset that has the current set of servers in it
|
* Return a resultset that has the current set of servers in it
|
||||||
*
|
*
|
||||||
@ -1074,53 +978,59 @@ uint64_t server_get_version(const SERVER* server)
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
// Converts SERVER_PARAM to MXS_CONFIG_PARAM and keeps them in the same order
|
// Converts Server::ConfigParam to MXS_CONFIG_PARAM and keeps them in the same order. Required for some
|
||||||
|
// functions taking MXS_CONFIG_PARAMs as arguments.
|
||||||
class ParamAdaptor
|
class ParamAdaptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ParamAdaptor(SERVER_PARAM* params)
|
ParamAdaptor(const std::vector<Server::ConfigParameter>& parameters)
|
||||||
{
|
{
|
||||||
for (auto p = params; p; p = p->next)
|
for (const auto& elem : parameters)
|
||||||
{
|
{
|
||||||
if (p->active)
|
// Allocate and add new head element.
|
||||||
{
|
MXS_CONFIG_PARAMETER* new_elem =
|
||||||
// The current tail of the list
|
static_cast<MXS_CONFIG_PARAMETER*>(MXS_MALLOC(sizeof(MXS_CONFIG_PARAMETER)));
|
||||||
auto it = m_params.begin();
|
new_elem->name = MXS_STRDUP(elem.name.c_str());
|
||||||
|
new_elem->value = MXS_STRDUP(elem.value.c_str());
|
||||||
// Push the new tail
|
new_elem->next = m_params;
|
||||||
m_params.push_front({p->name, p->value, nullptr});
|
m_params = new_elem;
|
||||||
|
|
||||||
if (it != m_params.end())
|
|
||||||
{
|
|
||||||
// Update the old tail to point to the new tail
|
|
||||||
it->next = &m_params.front();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ParamAdaptor()
|
||||||
|
{
|
||||||
|
while (m_params)
|
||||||
|
{
|
||||||
|
auto elem = m_params;
|
||||||
|
m_params = elem->next;
|
||||||
|
MXS_FREE(elem->name);
|
||||||
|
MXS_FREE(elem->value);
|
||||||
|
MXS_FREE(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator MXS_CONFIG_PARAMETER*()
|
operator MXS_CONFIG_PARAMETER*()
|
||||||
{
|
{
|
||||||
// Return the head of the parameter list which is the tail of the internal list
|
return m_params;
|
||||||
return m_params.empty() ? nullptr : &m_params.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Holds the temporary configuration objects. Needs to be a list so that
|
// Holds the temporary configuration objects. Needs to be a list so that
|
||||||
// inserts into the container won't invalidate the next pointers
|
// inserts into the container won't invalidate the next pointers
|
||||||
std::list<MXS_CONFIG_PARAMETER> m_params;
|
MXS_CONFIG_PARAMETER* m_params = nullptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a server configuration at the location pointed by @c filename
|
* Creates a server configuration at the location pointed by @c filename
|
||||||
|
* TODO: Move to member
|
||||||
*
|
*
|
||||||
* @param server Server to serialize into a configuration
|
* @param server Server to serialize into a configuration
|
||||||
* @param filename Filename where configuration is written
|
* @param filename Filename where configuration is written
|
||||||
* @return True on success, false on error
|
* @return True on success, false on error
|
||||||
*/
|
*/
|
||||||
static bool create_server_config(const SERVER* server, const char* filename)
|
bool Server::create_server_config(const Server* server, const char* filename)
|
||||||
{
|
{
|
||||||
int file = open(filename, O_EXCL | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
int file = open(filename, O_EXCL | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
|
||||||
@ -1140,36 +1050,24 @@ static bool create_server_config(const SERVER* server, const char* filename)
|
|||||||
|
|
||||||
const MXS_MODULE* mod = get_module(server->protocol, MODULE_PROTOCOL);
|
const MXS_MODULE* mod = get_module(server->protocol, MODULE_PROTOCOL);
|
||||||
dump_param_list(file,
|
dump_param_list(file,
|
||||||
ParamAdaptor(server->parameters),
|
ParamAdaptor(server->m_settings.all_parameters),
|
||||||
{CN_TYPE},
|
{CN_TYPE},
|
||||||
config_server_params,
|
config_server_params,
|
||||||
mod->parameters);
|
mod->parameters);
|
||||||
|
|
||||||
std::unordered_set<std::string> known;
|
// Print custom parameters
|
||||||
|
for (const auto& elem : server->m_settings.custom_parameters)
|
||||||
for (auto a : {config_server_params, mod->parameters})
|
|
||||||
{
|
{
|
||||||
for (int i = 0; a[i].name; i++)
|
dprintf(file, "%s=%s\n", elem.first.c_str(), elem.second.c_str());
|
||||||
{
|
|
||||||
known.insert(a[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto p = server->parameters; p; p = p->next)
|
|
||||||
{
|
|
||||||
if (known.count(p->name) == 0 && p->active)
|
|
||||||
{
|
|
||||||
dprintf(file, "%s=%s\n", p->name, p->value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(file);
|
close(file);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool server_serialize(const SERVER* server)
|
bool Server::serialize() const
|
||||||
{
|
{
|
||||||
|
const Server* server = this;
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
char filename[PATH_MAX];
|
char filename[PATH_MAX];
|
||||||
snprintf(filename,
|
snprintf(filename,
|
||||||
@ -1329,7 +1227,8 @@ bool server_is_mxs_service(const SERVER* server)
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static json_t* server_json_attributes(const SERVER* server)
|
// TODO: member function
|
||||||
|
json_t* Server::server_json_attributes(const Server* server)
|
||||||
{
|
{
|
||||||
/** Resource attributes */
|
/** Resource attributes */
|
||||||
json_t* attr = json_object();
|
json_t* attr = json_object();
|
||||||
@ -1338,18 +1237,18 @@ static json_t* server_json_attributes(const SERVER* server)
|
|||||||
json_t* params = json_object();
|
json_t* params = json_object();
|
||||||
|
|
||||||
const MXS_MODULE* mod = get_module(server->protocol, MODULE_PROTOCOL);
|
const MXS_MODULE* mod = get_module(server->protocol, MODULE_PROTOCOL);
|
||||||
config_add_module_params_json(ParamAdaptor(server->parameters),
|
config_add_module_params_json(ParamAdaptor(server->m_settings.all_parameters),
|
||||||
{CN_TYPE},
|
{CN_TYPE},
|
||||||
config_server_params,
|
config_server_params,
|
||||||
mod->parameters,
|
mod->parameters,
|
||||||
params);
|
params);
|
||||||
|
|
||||||
// Add weighting parameters that weren't added by config_add_module_params_json
|
// Add weighting parameters that weren't added by config_add_module_params_json
|
||||||
for (SERVER_PARAM* p = server->parameters; p; p = p->next)
|
for (const auto& elem : server->m_settings.custom_parameters)
|
||||||
{
|
{
|
||||||
if (!json_object_get(params, p->name))
|
if (!json_object_get(params, elem.first.c_str()))
|
||||||
{
|
{
|
||||||
json_object_set_new(params, p->name, json_string(p->value));
|
json_object_set_new(params, elem.first.c_str(), json_string(elem.second.c_str()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1402,7 +1301,7 @@ static json_t* server_json_attributes(const SERVER* server)
|
|||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static json_t* server_to_json_data(const SERVER* server, const char* host)
|
static json_t* server_to_json_data(const Server* server, const char* host)
|
||||||
{
|
{
|
||||||
json_t* rval = json_object();
|
json_t* rval = json_object();
|
||||||
|
|
||||||
@ -1427,13 +1326,13 @@ static json_t* server_to_json_data(const SERVER* server, const char* host)
|
|||||||
|
|
||||||
json_object_set_new(rval, CN_RELATIONSHIPS, rel);
|
json_object_set_new(rval, CN_RELATIONSHIPS, rel);
|
||||||
/** Attributes */
|
/** Attributes */
|
||||||
json_object_set_new(rval, CN_ATTRIBUTES, server_json_attributes(server));
|
json_object_set_new(rval, CN_ATTRIBUTES, Server::server_json_attributes(server));
|
||||||
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_SERVERS, server->name));
|
json_object_set_new(rval, CN_LINKS, mxs_json_self_link(host, CN_SERVERS, server->name));
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_t* server_to_json(const SERVER* server, const char* host)
|
json_t* server_to_json(const Server* server, const char* host)
|
||||||
{
|
{
|
||||||
string self = MXS_JSON_API_SERVERS;
|
string self = MXS_JSON_API_SERVERS;
|
||||||
self += server->name;
|
self += server->name;
|
||||||
@ -1544,3 +1443,23 @@ Server* Server::find_by_unique_name(const string& name)
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::is_custom_parameter(const string& name) const
|
||||||
|
{
|
||||||
|
for (int i = 0; config_server_params[i].name; i++)
|
||||||
|
{
|
||||||
|
if (name == config_server_params[i].name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto module_params = get_module(protocol, MODULE_PROTOCOL)->parameters;
|
||||||
|
for (int i = 0; module_params[i].name; i++)
|
||||||
|
{
|
||||||
|
if (name == module_params[i].name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -1319,16 +1319,16 @@ static void service_calculate_weights(SERVICE* service)
|
|||||||
" and will be removed in a later version of MaxScale.",
|
" and will be removed in a later version of MaxScale.",
|
||||||
weightby);
|
weightby);
|
||||||
|
|
||||||
char buf[50]; // Enough to hold most numbers
|
|
||||||
/** Service has a weighting parameter and at least one server */
|
/** Service has a weighting parameter and at least one server */
|
||||||
double total {0};
|
double total {0};
|
||||||
|
|
||||||
/** Calculate total weight */
|
/** Calculate total weight */
|
||||||
for (SERVER_REF* server = service->dbref; server; server = server->next)
|
for (SERVER_REF* server = service->dbref; server; server = server->next)
|
||||||
{
|
{
|
||||||
if (server_get_parameter(server->server, weightby, buf, sizeof(buf)))
|
string buf = server->server->get_custom_parameter(weightby);
|
||||||
|
if (!buf.empty())
|
||||||
{
|
{
|
||||||
long w = atol(buf);
|
long w = atol(buf.c_str());
|
||||||
if (w > 0)
|
if (w > 0)
|
||||||
{
|
{
|
||||||
total += w;
|
total += w;
|
||||||
@ -1348,9 +1348,10 @@ static void service_calculate_weights(SERVICE* service)
|
|||||||
/** Calculate the relative weight of the servers */
|
/** Calculate the relative weight of the servers */
|
||||||
for (SERVER_REF* server = service->dbref; server; server = server->next)
|
for (SERVER_REF* server = service->dbref; server; server = server->next)
|
||||||
{
|
{
|
||||||
if (server_get_parameter(server->server, weightby, buf, sizeof(buf)))
|
string buf = server->server->get_custom_parameter(weightby);
|
||||||
|
if (!buf.empty())
|
||||||
{
|
{
|
||||||
long config_weight = atol(buf);
|
long config_weight = atol(buf.c_str());
|
||||||
if (config_weight <= 0)
|
if (config_weight <= 0)
|
||||||
{
|
{
|
||||||
MXS_WARNING("Weighting parameter '%s' is set to %ld for server '%s'."
|
MXS_WARNING("Weighting parameter '%s' is set to %ld for server '%s'."
|
||||||
|
@ -66,13 +66,12 @@ static int test1()
|
|||||||
Server* server = Server::server_alloc("uniquename", params.params());
|
Server* server = Server::server_alloc("uniquename", params.params());
|
||||||
mxb_assert_message(server, "Allocating the server should not fail");
|
mxb_assert_message(server, "Allocating the server should not fail");
|
||||||
|
|
||||||
char buf[120];
|
|
||||||
fprintf(stderr, "\t..done\nTest Parameter for Server.");
|
fprintf(stderr, "\t..done\nTest Parameter for Server.");
|
||||||
mxb_assert_message(!server_get_parameter(server, "name", buf, sizeof(buf)),
|
mxb_assert_message(server->get_custom_parameter("name").empty(),
|
||||||
"Parameter should be null when not set");
|
"Parameter should be empty when not set");
|
||||||
server_set_parameter(server, "name", "value");
|
server->set_parameter("name", "value");
|
||||||
mxb_assert(server_get_parameter(server, "name", buf, sizeof(buf)));
|
std::string buf = server->get_custom_parameter("name");
|
||||||
mxb_assert_message(strcmp("value", buf) == 0, "Parameter should be returned correctly");
|
mxb_assert_message(buf == "value", "Parameter should be returned correctly");
|
||||||
fprintf(stderr, "\t..done\nTesting Unique Name for Server.");
|
fprintf(stderr, "\t..done\nTesting Unique Name for Server.");
|
||||||
mxb_assert_message(NULL == server_find_by_unique_name("non-existent"),
|
mxb_assert_message(NULL == server_find_by_unique_name("non-existent"),
|
||||||
"Should not find non-existent unique name.");
|
"Should not find non-existent unique name.");
|
||||||
@ -145,18 +144,18 @@ bool test_serialize()
|
|||||||
unlink(old_config_name);
|
unlink(old_config_name);
|
||||||
|
|
||||||
/** Serialize server to disk */
|
/** Serialize server to disk */
|
||||||
TEST(server_serialize(server), "Failed to synchronize original server");
|
TEST(server->serialize(), "Failed to synchronize original server");
|
||||||
|
|
||||||
/** Load it again */
|
/** Load it again */
|
||||||
TEST(test_load_config(config_name, server), "Failed to load the serialized server");
|
TEST(test_load_config(config_name, server), "Failed to load the serialized server");
|
||||||
|
|
||||||
/** We should have two identical servers */
|
/** We should have two identical servers */
|
||||||
SERVER* created = server_find_by_unique_name(name);
|
Server* created = Server::find_by_unique_name(name);
|
||||||
|
|
||||||
rename(config_name, old_config_name);
|
rename(config_name, old_config_name);
|
||||||
|
|
||||||
/** Serialize the loaded server to disk */
|
/** Serialize the loaded server to disk */
|
||||||
TEST(server_serialize(created), "Failed to synchronize the copied server");
|
TEST(created->serialize(), "Failed to synchronize the copied server");
|
||||||
|
|
||||||
/** Check that they serialize to identical files */
|
/** Check that they serialize to identical files */
|
||||||
char cmd[1024];
|
char cmd[1024];
|
||||||
|
@ -375,12 +375,13 @@ MXS_MONITORED_SERVER* GaleraMonitor::get_candidate_master()
|
|||||||
if (!server_is_in_maint(moitor_servers->server)
|
if (!server_is_in_maint(moitor_servers->server)
|
||||||
&& (moitor_servers->pending_status & SERVER_JOINED))
|
&& (moitor_servers->pending_status & SERVER_JOINED))
|
||||||
{
|
{
|
||||||
|
if (m_use_priority)
|
||||||
char buf[50]; // Enough to hold most numbers
|
{
|
||||||
if (m_use_priority && server_get_parameter(moitor_servers->server, "priority", buf, sizeof(buf)))
|
std::string buf = moitor_servers->server->get_custom_parameter("priority");
|
||||||
|
if (!buf.empty())
|
||||||
{
|
{
|
||||||
/** The server has a priority */
|
/** The server has a priority */
|
||||||
if ((currval = atoi(buf)) > 0)
|
if ((currval = atoi(buf.c_str())) > 0)
|
||||||
{
|
{
|
||||||
/** The priority is valid */
|
/** The priority is valid */
|
||||||
if (currval < minval && currval > 0)
|
if (currval < minval && currval > 0)
|
||||||
@ -390,6 +391,7 @@ MXS_MONITORED_SERVER* GaleraMonitor::get_candidate_master()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (moitor_servers->server->node_id >= 0
|
else if (moitor_servers->server->node_id >= 0
|
||||||
&& (!m_use_priority || candidate_master == NULL))
|
&& (!m_use_priority || candidate_master == NULL))
|
||||||
{
|
{
|
||||||
@ -527,7 +529,7 @@ void GaleraMonitor::update_sst_donor_nodes(int is_cluster)
|
|||||||
* the server list will be order by default method.
|
* the server list will be order by default method.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (m_use_priority && server_get_parameter(ptr->server, "priority", NULL, 0))
|
if (m_use_priority && !ptr->server->get_custom_parameter("priority").empty())
|
||||||
{
|
{
|
||||||
ignore_priority = false;
|
ignore_priority = false;
|
||||||
}
|
}
|
||||||
@ -641,10 +643,10 @@ static int compare_node_priority(const void* a, const void* b)
|
|||||||
{
|
{
|
||||||
const MXS_MONITORED_SERVER* s_a = *(MXS_MONITORED_SERVER* const*)a;
|
const MXS_MONITORED_SERVER* s_a = *(MXS_MONITORED_SERVER* const*)a;
|
||||||
const MXS_MONITORED_SERVER* s_b = *(MXS_MONITORED_SERVER* const*)b;
|
const MXS_MONITORED_SERVER* s_b = *(MXS_MONITORED_SERVER* const*)b;
|
||||||
char pri_a[50];
|
std::string pri_a = s_a->server->get_custom_parameter("priority");
|
||||||
char pri_b[50];
|
std::string pri_b = s_b->server->get_custom_parameter("priority");
|
||||||
bool have_a = server_get_parameter(s_a->server, "priority", pri_a, sizeof(pri_a));
|
bool have_a = !pri_a.empty();
|
||||||
bool have_b = server_get_parameter(s_b->server, "priority", pri_b, sizeof(pri_b));
|
bool have_b = !pri_b.empty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check priority parameter:
|
* Check priority parameter:
|
||||||
@ -672,8 +674,8 @@ static int compare_node_priority(const void* a, const void* b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The given priority is valid */
|
/* The given priority is valid */
|
||||||
int pri_val_a = atoi(pri_a);
|
int pri_val_a = atoi(pri_a.c_str());
|
||||||
int pri_val_b = atoi(pri_b);
|
int pri_val_b = atoi(pri_b.c_str());
|
||||||
|
|
||||||
/* Return a - b in case of issues */
|
/* Return a - b in case of issues */
|
||||||
if ((pri_val_a < INT_MAX && pri_val_a > 0) && !(pri_val_b < INT_MAX && pri_val_b > 0))
|
if ((pri_val_a < INT_MAX && pri_val_a > 0) && !(pri_val_b < INT_MAX && pri_val_b > 0))
|
||||||
|
Reference in New Issue
Block a user