404 lines
11 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: 2022-01-01
*
* 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/service.hh>
#include <maxscale/resultset.hh>
#include <mutex>
#include <string>
#include <vector>
#include "filter.hh"
/**
* @file service.h - MaxScale internal service functions
*/
struct LastUserLoad
{
time_t last = 0; // The last time the users were loaded
bool warned = false; // Has a warning been logged
};
// The internal service representation
class Service : public SERVICE
{
public:
using FilterList = std::vector<SFilterDef>;
using RateLimits = std::vector<LastUserLoad>;
Service(const std::string& name, const std::string& router, MXS_CONFIG_PARAMETER* params);
~Service();
/**
* Check if name matches a basic service parameter
*
* Basic parameters are common to all services. These include, for example, the
* `user` and `password` parameters.
*
* @return True if the parameter is a basic service parameter
*/
bool is_basic_parameter(const std::string& name);
/**
* Update a basic service parameter
*
* Update a parameter that is common to all services.
*
* @param name Name of the parameter to update
* @param value The new value of the parameter
*/
void update_basic_parameter(const std::string& name, const std::string& value);
/**
* Set the list of filters for this service
*
* @param filters Filters to set
*
* @return True if filters were all found and were valid
*/
bool set_filters(const std::vector<std::string>& filters);
/**
* Get the list of filters this service uses
*
* @note This can lock the service if this is the first time this worker
* accesses the filter list
*
* @return A list of filters or an empty list of no filters are in use
*/
const FilterList& get_filters() const;
/**
* Reload users for all listeners
*
* @return True if loading of users was successful
*/
bool refresh_users();
/**
* Dump service configuration into a file
*
* @param filename File where the configuration should be written
*
* @return True on success
*/
bool dump_config(const char* filename) const;
// TODO: Make JSON output internal (could iterate over get_filters() but that takes the service lock)
json_t* json_relationships(const char* host) const;
// TODO: Make these private
mutable std::mutex lock;
private:
FilterList m_filters; /**< Ordered list of filters */
std::string m_name; /**< Name of the service */
std::string m_router_name; /**< Router module */
std::string m_user; /**< Username */
std::string m_password; /**< Password */
std::string m_weightby; /**< Weighting parameter name */
std::string m_version_string; /**< Version string sent to clients */
RateLimits m_rate_limits; /**< The refresh rate limits for users of each thread */
uint64_t m_wkey; /**< Key for worker local data */
// Get the worker local filter list
FilterList* get_local_filters() const;
// Update the local filter list on the current worker
void update_local_filters();
// Callback for updating the local filter list
static void update_filters_cb(void* data)
{
Service* service = static_cast<Service*>(data);
service->update_local_filters();
}
};
/**
* Service life cycle management
*
* These functions should only be called by the MaxScale core.
*/
/**
* @brief Allocate a new service
*
* @param name The service name
* @param router The router module this service uses
* @param params Service parameters
*
* @return The newly created service or NULL if an error occurred
*/
Service* service_alloc(const char* name, const char* router, MXS_CONFIG_PARAMETER* params);
/**
* Free a service
*
* @note Must not be called if the service has any active client connections or
* active listeners
*
* @param service Service to free
*/
void service_free(Service* service);
/**
* Mark a service for destruction
*
* Once the service reference count drops down to zero, the service is destroyed.
*
* @param service Service to destroy
*/
void service_destroy(Service* service);
/**
* Check whether a service can be destroyed
*
* @param service Service to check
*
* @return True if service can be destroyed
*/
bool service_can_be_destroyed(Service* service);
/**
* @brief Shut all services down
*
* Turns on the shutdown flag in each service. This should be done as
* part of the MaxScale shutdown.
*/
void service_shutdown(void);
/**
* @brief Destroy all service router and filter instances
*
* Calls the @c destroyInstance entry point of each service' router and
* filters. This should be done after all worker threads have exited.
*/
void service_destroy_instances(void);
/**
* @brief Launch all services
*
* Initialize and start all services. This should only be called once by the
* main initialization code.
*
* @return False if a fatal error occurred
*/
bool service_launch_all(void);
/**
* @brief Remove a listener from use
*
* @note This does not free the memory
*
* @param service Service that owns the listener
* @param char Name of the listener to remove
*
* @return True if listener was found and removed
*/
bool service_remove_listener(Service* service, const char* target);
void serviceRemoveBackend(Service* service, const SERVER* server);
/**
* @brief Serialize a service to a file
*
* This converts @c service into an INI format file.
*
* NOTE: This does not persist the complete service configuration and requires
* that an existing service configuration is in the main configuration file.
*
* @param service Service to serialize
* @return False if the serialization of the service fails, true if it was successful
*/
bool service_serialize(const Service* service);
/**
* Internal utility functions
*/
bool service_all_services_have_listeners(void);
bool service_isvalid(Service* service);
/**
* Check if a service uses @c servers
* @param server Server that is queried
* @return True if server is used by at least one service
*/
bool service_server_in_use(const SERVER* server);
/**
* Check if filter is used by any service
*
* @param filter Filter to inspect
*
* @return True if at least one service uses the filter
*/
bool service_filter_in_use(const SFilterDef& filter);
/** Update the server weights used by services */
void service_update_weights();
/**
* @brief Add parameters to a service
*
* A copy of @c param is added to @c service.
*
* @param service Service where the parameters are added
* @param param Parameters to add
*/
void service_add_parameters(Service* service, const MXS_CONFIG_PARAMETER* param);
/**
* @brief Add parameters to a service
*
* A copy of @c param is added to @c service.
*
* @param service Service where the parameters are added
* @param key Parameter name
* @param value Parameter value
*/
void service_add_parameter(Service* service, const char* key, const char* value);
/**
* @brief Remove service parameter
*
* @param service Service to modify
* @param key Parameter to remove
*/
void service_remove_parameter(Service* service, const char* key);
/**
* @brief Replace service parameter
*
* @param service Service to modify
* @param key Parameter name
* @param value Parameter value
*/
void service_replace_parameter(Service* service, const char* key, const char* value);
// Internal search function
Service* service_internal_find(const char* name);
/**
* @brief Check if a service uses a server
* @param service Service to check
* @param server Server being used
* @return True if service uses the server
*/
bool serviceHasBackend(Service* service, SERVER* server);
/**
* @brief Find listener with specified properties.
*
* @param service Service to check
* @param socket Listener socket path
* @param address Listener address
* @param port Listener port number
*
* @note Either socket should be NULL and port non-zero or socket
* non-NULL and port zero.
*
* @return True if service has the listener
*/
SListener service_find_listener(Service* service,
const std::string& socket,
const std::string& address,
unsigned short port);
/**
* @brief Check if a MaxScale service listens on a port
*
* @param port The port to check
* @return True if a MaxScale service uses the port
*/
bool service_port_is_used(int port);
/**
* @brief Check if the service has a listener with a matching name
*
* @param service Service to check
* @param name Name to compare to
*
* @return True if the service has a listener with a matching name
*/
bool service_has_named_listener(Service* service, const char* name);
// Required by MaxAdmin
int service_enable_root(Service* service, int action);
/**
* @brief Convert a service to JSON
*
* @param service Service to convert
* @param host Hostname of this server
*
* @return JSON representation of the service
*/
json_t* service_to_json(const Service* service, const char* host);
/**
* @brief Convert all services to JSON
*
* @param host Hostname of this server
*
* @return A JSON array with all services
*/
json_t* service_list_to_json(const char* host);
/**
* @brief Convert service listeners to JSON
*
* @param service Service whose listeners are converted
* @param host Hostname of this server
*
* @return Array of JSON format listeners
*/
json_t* service_listener_list_to_json(const Service* service, const char* host);
/**
* @brief Convert service listener to JSON
*
* @param service Service whose listener is converted
* @param name The name of the listener
* @param host Hostname of this server
*
* @return JSON format listener
*/
json_t* service_listener_to_json(const Service* service, const char* name, const char* host);
/**
* @brief Get links to services that relate to a server
*
* @param server Server to inspect
* @param host Hostname of this server
*
* @return Array of service links or NULL if no relations exist
*/
json_t* service_relations_to_server(const SERVER* server, const char* host);
/**
* @brief Get links to services that relate to a filter
*
* @param filter Filter to inspect
* @param host Hostname of this server
*
* @return Array of service links
*/
json_t* service_relations_to_filter(const SFilterDef& filter, const char* host);
std::unique_ptr<ResultSet> serviceGetList(void);
std::unique_ptr<ResultSet> serviceGetListenerList(void);