544 lines
16 KiB
C++
544 lines
16 KiB
C++
/*
|
|
* Copyright (c) 2018 MariaDB Corporation Ab
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
|
*
|
|
* Change Date: 2026-01-04
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2 or later of the General
|
|
* Public License.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <maxscale/ccdefs.hh>
|
|
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <maxbase/average.hh>
|
|
#include <maxscale/ssl.hh>
|
|
#include <maxscale/modinfo.h>
|
|
|
|
/**
|
|
* Server configuration parameters names
|
|
*/
|
|
extern const char CN_MONITORPW[];
|
|
extern const char CN_MONITORUSER[];
|
|
extern const char CN_PERSISTMAXTIME[];
|
|
extern const char CN_PERSISTPOOLMAX[];
|
|
extern const char CN_PROXY_PROTOCOL[];
|
|
extern const char CN_RANK[];
|
|
|
|
// The enum values for `rank`
|
|
extern const MXS_ENUM_VALUE rank_values[];
|
|
|
|
// Default value for `rank`
|
|
extern const char* DEFAULT_RANK;
|
|
|
|
/**
|
|
* Status bits in the SERVER->status member, which describes the general state of a server. Although the
|
|
* individual bits are independent, not all combinations make sense or are used. The bitfield is 64bits wide.
|
|
*/
|
|
// Bits used by most monitors
|
|
#define SERVER_RUNNING (1 << 0) /**<< The server is up and running */
|
|
#define SERVER_MAINT (1 << 1) /**<< Server is in maintenance mode */
|
|
#define SERVER_AUTH_ERROR (1 << 2) /**<< Authentication error from monitor */
|
|
#define SERVER_MASTER (1 << 3) /**<< The server is a master, i.e. can handle writes */
|
|
#define SERVER_SLAVE (1 << 4) /**<< The server is a slave, i.e. can handle reads */
|
|
#define SERVER_DRAINING (1 << 5) /**<< The server is being drained, i.e. no new connection
|
|
* should be created. */
|
|
#define SERVER_DISK_SPACE_EXHAUSTED (1 << 6) /**<< The disk space of the server is exhausted */
|
|
// Bits used by MariaDB Monitor (mostly)
|
|
#define SERVER_SLAVE_OF_EXT_MASTER (1 << 16) /**<< Server is slave of a non-monitored master */
|
|
#define SERVER_RELAY (1 << 17) /**<< Server is a relay */
|
|
#define SERVER_WAS_MASTER (1 << 18) /**<< Server was a master but lost all slaves. */
|
|
// Bits used by other monitors
|
|
#define SERVER_JOINED (1 << 19) /**<< The server is joined in a Galera cluster */
|
|
#define SERVER_MASTER_STICKINESS (1 << 20) /**<< Server Master stickiness */
|
|
|
|
inline bool status_is_connectable(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_MAINT | SERVER_DRAINING)) == SERVER_RUNNING;
|
|
}
|
|
|
|
inline bool status_is_usable(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_MAINT)) == SERVER_RUNNING;
|
|
}
|
|
|
|
inline bool status_is_running(uint64_t status)
|
|
{
|
|
return status & SERVER_RUNNING;
|
|
}
|
|
|
|
inline bool status_is_down(uint64_t status)
|
|
{
|
|
return (status & SERVER_RUNNING) == 0;
|
|
}
|
|
|
|
inline bool status_is_in_maint(uint64_t status)
|
|
{
|
|
return status & SERVER_MAINT;
|
|
}
|
|
|
|
inline bool status_is_draining(uint64_t status)
|
|
{
|
|
return status & SERVER_DRAINING;
|
|
}
|
|
|
|
inline bool status_is_master(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_MASTER | SERVER_MAINT)) == (SERVER_RUNNING | SERVER_MASTER);
|
|
}
|
|
|
|
inline bool status_is_slave(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_SLAVE | SERVER_MAINT)) == (SERVER_RUNNING | SERVER_SLAVE);
|
|
}
|
|
|
|
inline bool status_is_relay(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_RELAY | SERVER_MAINT)) == (SERVER_RUNNING | SERVER_RELAY);
|
|
}
|
|
|
|
inline bool status_is_joined(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_JOINED | SERVER_MAINT)) == (SERVER_RUNNING | SERVER_JOINED);
|
|
}
|
|
|
|
inline bool status_is_slave_of_ext_master(uint64_t status)
|
|
{
|
|
return (status & (SERVER_RUNNING | SERVER_SLAVE_OF_EXT_MASTER))
|
|
== (SERVER_RUNNING | SERVER_SLAVE_OF_EXT_MASTER);
|
|
}
|
|
|
|
inline bool status_is_disk_space_exhausted(uint64_t status)
|
|
{
|
|
return status & SERVER_DISK_SPACE_EXHAUSTED;
|
|
}
|
|
|
|
/**
|
|
* The SERVER structure defines a backend server. Each server has a name
|
|
* or IP address for the server, a port that the server listens on and
|
|
* the name of a protocol module that is loaded to implement the protocol
|
|
* between the gateway and the server.
|
|
*/
|
|
class SERVER
|
|
{
|
|
public:
|
|
static const int MAX_ADDRESS_LEN = 1024;
|
|
static const int MAX_MONUSER_LEN = 512;
|
|
static const int MAX_MONPW_LEN = 512;
|
|
static const int MAX_VERSION_LEN = 256;
|
|
static const int RLAG_UNDEFINED = -1; // Default replication lag value
|
|
|
|
// A mapping from a path to a percentage, e.g.: "/disk" -> 80.
|
|
typedef std::unordered_map<std::string, int32_t> DiskSpaceLimits;
|
|
|
|
enum class Type
|
|
{
|
|
MARIADB,
|
|
MYSQL,
|
|
XPAND
|
|
};
|
|
|
|
enum class RLagState
|
|
{
|
|
NONE,
|
|
BELOW_LIMIT,
|
|
ABOVE_LIMIT
|
|
};
|
|
|
|
struct Version
|
|
{
|
|
uint64_t total = 0; /**< The version number received from server */
|
|
uint32_t major = 0; /**< Major version */
|
|
uint32_t minor = 0; /**< Minor version */
|
|
uint32_t patch = 0; /**< Patch version */
|
|
};
|
|
|
|
/* Server connection and usage statistics */
|
|
struct ConnStats
|
|
{
|
|
uint64_t n_connections = 0; /**< Number of connections */
|
|
int n_current = 0; /**< Current connections */
|
|
int n_current_ops = 0; /**< Current active operations */
|
|
int n_persistent = 0; /**< Current persistent pool */
|
|
uint64_t n_new_conn = 0; /**< Times the current pool was empty */
|
|
uint64_t n_from_pool = 0; /**< Times when a connection was available from the pool */
|
|
uint64_t packets = 0; /**< Number of packets routed to this server */
|
|
};
|
|
|
|
// Base settings
|
|
char address[MAX_ADDRESS_LEN + 1] = {'\0'}; /**< Server hostname/IP-address */
|
|
int port = -1; /**< Server port */
|
|
int extra_port = -1; /**< Alternative monitor port if normal port fails */
|
|
|
|
// Other settings
|
|
bool proxy_protocol = false; /**< Send proxy-protocol header to backends when connecting
|
|
* routing sessions. */
|
|
|
|
// Base variables
|
|
bool is_active = false; /**< Server is active and has not been "destroyed" */
|
|
uint8_t charset = 0; /**< Character set. Read from backend and sent to client. As no character set
|
|
* has the numeric value of 0, it can be used to detect servers we haven't
|
|
* connected to. */
|
|
|
|
// Statistics and events
|
|
ConnStats stats; /**< The server statistics, e.g. number of connections */
|
|
int persistmax = 0; /**< Maximum pool size actually achieved since startup */
|
|
int last_event = 0; /**< The last event that occurred on this server */
|
|
int64_t triggered_at = 0; /**< Time when the last event was triggered */
|
|
|
|
// Status descriptors. Updated automatically by a monitor or manually by the admin
|
|
uint64_t status = 0; /**< Current status flag bitmap */
|
|
|
|
long node_id = -1; /**< Node id, server_id for M/S or local_index for Galera */
|
|
long master_id = -1; /**< Master server id of this node */
|
|
int rlag = RLAG_UNDEFINED;/**< Replication Lag for Master/Slave replication */
|
|
unsigned long node_ts = 0; /**< Last timestamp set from M/S monitor module */
|
|
|
|
// Misc fields
|
|
bool master_err_is_logged = false; /**< If node failed, this indicates whether it is logged. Only
|
|
* used by rwsplit. TODO: Move to rwsplit */
|
|
bool warn_ssl_not_enabled = true; /**< SSL not used for an SSL enabled server */
|
|
RLagState rlag_state = RLagState::NONE; /**< Is replication lag above or under limit? Used by rwsplit. */
|
|
|
|
virtual ~SERVER() = default;
|
|
|
|
/**
|
|
* Check if server has disk space threshold settings.
|
|
*
|
|
* @return True if limits exist
|
|
*/
|
|
virtual bool have_disk_space_limits() const = 0;
|
|
|
|
/**
|
|
* Get a copy of disk space limit settings.
|
|
*
|
|
* @return A copy of settings
|
|
*/
|
|
virtual DiskSpaceLimits get_disk_space_limits() const = 0;
|
|
|
|
/**
|
|
* Is persistent connection pool enabled.
|
|
*
|
|
* @return True if enabled
|
|
*/
|
|
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;
|
|
|
|
/**
|
|
* Update server version.
|
|
*
|
|
* @param version_num New numeric version
|
|
* @param version_str New version string
|
|
*/
|
|
virtual void set_version(uint64_t version_num, const std::string& version_str) = 0;
|
|
|
|
/**
|
|
* Get numeric version information.
|
|
*
|
|
* @return Major, minor and patch numbers
|
|
*/
|
|
virtual Version version() const = 0;
|
|
|
|
/**
|
|
* Get the type of the server.
|
|
*
|
|
* @return Server type
|
|
*/
|
|
virtual Type type() const = 0;
|
|
|
|
/**
|
|
* Get version string.
|
|
*
|
|
* @return Version string
|
|
*/
|
|
virtual std::string version_string() const = 0;
|
|
|
|
/**
|
|
* Returns the server configuration name. The value is returned as a c-string for printing convenience.
|
|
*
|
|
* @return Server name
|
|
*/
|
|
virtual const char* name() const = 0;
|
|
|
|
/**
|
|
* Get backend protocol module name.
|
|
*
|
|
* @return Backend protocol module name of the server
|
|
*/
|
|
virtual std::string protocol() const = 0;
|
|
|
|
/**
|
|
* Get server rank
|
|
*
|
|
* @return The server rank
|
|
*/
|
|
virtual int64_t rank() const = 0;
|
|
|
|
/*
|
|
* Update server address. TODO: Move this to internal class once blr is gone.
|
|
*
|
|
* @param address The new address
|
|
*/
|
|
bool server_update_address(const std::string& address);
|
|
|
|
/**
|
|
* Update the server port. TODO: Move this to internal class once blr is gone.
|
|
*
|
|
* @param new_port New port. The value is not checked but should generally be 1 -- 65535.
|
|
*/
|
|
void update_port(int new_port);
|
|
|
|
/**
|
|
* Update the server extra port. TODO: Move this to internal class once blr is gone.
|
|
*
|
|
* @param new_port New port. The value is not checked but should generally be 1 -- 65535.
|
|
*/
|
|
void update_extra_port(int new_port);
|
|
|
|
/**
|
|
* @brief Check if a server points to a local MaxScale service
|
|
*
|
|
* @return True if the server points to a local MaxScale service
|
|
*/
|
|
bool is_mxs_service();
|
|
|
|
/**
|
|
* Is the server valid and active? TODO: Rename once "is_active" is moved to internal class.
|
|
*
|
|
* @return True if server has not been removed from the runtime configuration.
|
|
*/
|
|
bool server_is_active() const
|
|
{
|
|
return is_active;
|
|
}
|
|
|
|
/**
|
|
* Is the server running and can be connected to?
|
|
*
|
|
* @return True if the server can be connected to.
|
|
*/
|
|
bool is_connectable() const
|
|
{
|
|
return status_is_connectable(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server running and not in maintenance?
|
|
*
|
|
* @return True if server can be used.
|
|
*/
|
|
bool is_usable() const
|
|
{
|
|
return status_is_usable(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server running?
|
|
*
|
|
* @return True if monitor can connect to the server.
|
|
*/
|
|
bool is_running() const
|
|
{
|
|
return status_is_running(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server down?
|
|
*
|
|
* @return True if monitor cannot connect to the server.
|
|
*/
|
|
bool is_down() const
|
|
{
|
|
return status_is_down(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server in maintenance mode?
|
|
*
|
|
* @return True if server is in maintenance.
|
|
*/
|
|
bool is_in_maint() const
|
|
{
|
|
return status_is_in_maint(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server being drained?
|
|
*
|
|
* @return True if server is being drained.
|
|
*/
|
|
bool is_draining() const
|
|
{
|
|
return status_is_draining(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server a master?
|
|
*
|
|
* @return True if server is running and marked as master.
|
|
*/
|
|
bool is_master() const
|
|
{
|
|
return status_is_master(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server a slave.
|
|
*
|
|
* @return True if server is running and marked as slave.
|
|
*/
|
|
bool is_slave() const
|
|
{
|
|
return status_is_slave(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server a relay slave?
|
|
*
|
|
* @return True, if server is a running relay.
|
|
*/
|
|
bool is_relay() const
|
|
{
|
|
return status_is_relay(status);
|
|
}
|
|
|
|
/**
|
|
* Is the server joined Galera node?
|
|
*
|
|
* @return True, if server is running and joined.
|
|
*/
|
|
bool is_joined() const
|
|
{
|
|
return status_is_joined(status);
|
|
}
|
|
|
|
bool is_in_cluster() const
|
|
{
|
|
return (status & (SERVER_MASTER | SERVER_SLAVE | SERVER_RELAY | SERVER_JOINED)) != 0;
|
|
}
|
|
|
|
bool is_slave_of_ext_master() const
|
|
{
|
|
return status_is_slave_of_ext_master(status);
|
|
}
|
|
|
|
bool is_low_on_disk_space() const
|
|
{
|
|
return status_is_disk_space_exhausted(status);
|
|
}
|
|
|
|
/**
|
|
* Find a server with the specified name.
|
|
*
|
|
* @param name Name of the server
|
|
* @return The server or NULL if not found
|
|
*/
|
|
static SERVER* find_by_unique_name(const std::string& name);
|
|
|
|
/**
|
|
* Find several servers with the names specified in an array. The returned array is equal in size
|
|
* to the server_names-array. If any server name was not found, then the corresponding element
|
|
* will be NULL.
|
|
*
|
|
* @param server_names An array of server names
|
|
* @return Array of servers
|
|
*/
|
|
static std::vector<SERVER*> server_find_by_unique_names(const std::vector<std::string>& server_names);
|
|
|
|
/**
|
|
* Convert the current server status flags to a string.
|
|
*
|
|
* @param server The server to return the status for
|
|
* @return A string representation of the status
|
|
*/
|
|
std::string status_string() const;
|
|
|
|
/**
|
|
* Convert a set of server status flags to a string.
|
|
*
|
|
* @param flags Status flags
|
|
* @param nConnections Number of current connections. Only affects the output
|
|
* if the @c SERVER_DRAINING bit is on. In that case, if
|
|
* the number of connections is 0 the state will be reported
|
|
* as 'Drained', otherwise as 'Draining'.
|
|
*
|
|
* @return A string representation of the status flags
|
|
*/
|
|
static std::string status_to_string(uint64_t flags, int nConnections = -1);
|
|
|
|
/**
|
|
* Convert a status string to a status bit. Only converts one status element.
|
|
*
|
|
* @param str String representation
|
|
* @return bit value or 0 on error
|
|
*/
|
|
static uint64_t status_from_string(const char* str);
|
|
|
|
/**
|
|
* Set a status bit in the server without locking
|
|
*
|
|
* @param bit The bit to set for the server
|
|
*/
|
|
void set_status(uint64_t bit);
|
|
|
|
/**
|
|
* Clear a status bit in the server without locking
|
|
*
|
|
* @param bit The bit to clear for the server
|
|
*/
|
|
void clear_status(uint64_t bit);
|
|
|
|
int response_time_num_samples() const
|
|
{
|
|
return m_response_time.num_samples();
|
|
}
|
|
|
|
double response_time_average() const
|
|
{
|
|
return m_response_time.average();
|
|
}
|
|
|
|
/**
|
|
* Add a response time measurement to the global server value.
|
|
*
|
|
* @param ave The value to add
|
|
* @param num_samples The weight of the new value, that is, the number of measurement points it represents
|
|
*/
|
|
void response_time_add(double ave, int num_samples);
|
|
|
|
const mxs::SSLProvider& ssl() const
|
|
{
|
|
return m_ssl_provider;
|
|
}
|
|
|
|
mxs::SSLProvider& ssl()
|
|
{
|
|
return m_ssl_provider;
|
|
}
|
|
|
|
protected:
|
|
SERVER(std::unique_ptr<mxs::SSLContext> ssl_context)
|
|
: m_response_time{0.04, 0.35, 500}
|
|
, m_ssl_provider{std::move(ssl_context)}
|
|
{
|
|
}
|
|
|
|
private:
|
|
maxbase::EMAverage m_response_time; /**< Response time calculations for this server */
|
|
std::mutex m_average_write_mutex; /**< Protects response time from concurrent writing */
|
|
mxs::SSLProvider m_ssl_provider;
|
|
};
|