From 8ef99c9066878dcd18e3316acd6edb0e79989b40 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Tue, 22 Nov 2016 15:18:04 +0200 Subject: [PATCH] Move configuration changes to a common file The config_runtime.h header contains functions that can be used to manipulate the running configuration. Currently the header contains the function to create, add, remove and destroy servers. --- include/maxscale/config_runtime.h | 81 +++++++++ include/maxscale/monitor.h | 2 +- include/maxscale/server.h | 37 ++-- include/maxscale/service.h | 2 +- server/core/CMakeLists.txt | 2 +- server/core/config_runtime.c | 190 +++++++++++++++++++++ server/core/monitor.c | 2 +- server/core/server.c | 106 +----------- server/core/service.c | 2 +- server/modules/routing/debugcli/debugcmd.c | 50 +----- 10 files changed, 295 insertions(+), 179 deletions(-) create mode 100644 include/maxscale/config_runtime.h create mode 100644 server/core/config_runtime.c diff --git a/include/maxscale/config_runtime.h b/include/maxscale/config_runtime.h new file mode 100644 index 000000000..775902eeb --- /dev/null +++ b/include/maxscale/config_runtime.h @@ -0,0 +1,81 @@ +#pragma once +/* + * Copyright (c) 2016 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/bsl. + * + * Change Date: 2019-07-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. + */ + +/** + * @file config_runtime.h - Functions for runtime configuration modifications + */ + +#include + +#include +#include +#include +#include + +/** + * @brief Create a new server + * + * This function creates a new, persistent server by first allocating a new + * server and then storing the resulting configuration file on disk. This + * function should be used only from administrative interface modules and internal + * modules should use server_alloc() instead. + * + * @param name Server name + * @param address Network address + * @param port Network port + * @param protocol Protocol module name + * @param authenticator Authenticator module name + * @param options Options for the authenticator module + * @return True on success, false if an error occurred + */ +bool runtime_create_server(const char *name, const char *address, + const char *port, const char *protocol, + const char *authenticator, const char *options); + +/** + * @brief Destroy a server + * + * This removes any created server configuration files and marks the server removed + * If the server is not in use. + * + * @param server Server to destroy + * @return True if server was destroyed + */ +bool runtime_destroy_server(SERVER *server); + +/** + * @brief Link a server to an object + * + * This function links the server to another object. The target can be either + * a monitor or a service. + * + * @param server Server to link + * @param target The monitor or service where the server is added + * @return True if the object was found and the server was linked to it, false + * if no object matching @c target was found + */ +bool runtime_link_server(SERVER *server, const char *target); + +/** + * @brief Unlink a server from an object + * + * This function unlinks the server from another object. The target can be either + * a monitor or a service. + * + * @param server Server to unlink + * @param target The monitor or service from which the server is removed + * @return True if the object was found and the server was unlinked from it, false + * if no object matching @c target was found + */ +bool runtime_unlink_server(SERVER *server, const char *target); diff --git a/include/maxscale/monitor.h b/include/maxscale/monitor.h index 46a9df814..5c458ce46 100644 --- a/include/maxscale/monitor.h +++ b/include/maxscale/monitor.h @@ -203,7 +203,7 @@ struct monitor extern MONITOR *monitor_alloc(char *, char *); extern void monitor_free(MONITOR *); -extern MONITOR *monitor_find(char *); +extern MONITOR *monitor_find(const char *); extern void monitorAddServer(MONITOR *mon, SERVER *server); extern void monitorRemoveServer(MONITOR *mon, SERVER *server); extern void monitorAddUser(MONITOR *, char *, char *); diff --git a/include/maxscale/server.h b/include/maxscale/server.h index cfde36a10..dbbd9d7e4 100644 --- a/include/maxscale/server.h +++ b/include/maxscale/server.h @@ -227,25 +227,20 @@ extern SERVER* server_alloc(const char *name, const char *address, unsigned shor const char *auth_options); /** - * @brief Create a new server + * @brief Find a server that can be reused * - * This function creates a new, persistent server by first allocating a new - * server and then storing the resulting configuration file on disk. This - * function should be used only from administrative interface modules and internal - * modules should use server_alloc() instead. + * A server that has been destroyed will not be deleted but only deactivated. * - * @param name Server name - * @param address Network address - * @param port Network port - * @param protocol Protocol module name - * @param authenticator Authenticator module name - * @param options Options for the authenticator module - * @return True on success, false if an error occurred + * @param name Name of the server + * @param protocol Protocol used by the server + * @param authenticator The authenticator module of the server + * @param auth_options Options for the authenticator + * @return Reusable SERVER or NULL if no servers matching the criteria were + * found + * @see runtime_create_server */ -extern bool server_create(const char *name, const char *address, const char *port, - const char *protocol, const char *authenticator, - const char *options); - +SERVER* server_find_destroyed(const char *name, const char *protocol, + const char *authenticator, const char *auth_options); /** * @brief Serialize a server to a file * @@ -258,16 +253,6 @@ extern bool server_create(const char *name, const char *address, const char *por */ bool server_serialize(const SERVER *server); -/** - * @brief Destroy a server - * - * This removes any created server configuration files and marks the server removed - * If the server is not in use. - * @param server Server to destroy - * @return True if server was destroyed - */ -bool server_destroy(SERVER *server); - extern int server_free(SERVER *); extern SERVER *server_find_by_unique_name(const char *name); extern SERVER *server_find(char *, unsigned short); diff --git a/include/maxscale/service.h b/include/maxscale/service.h index 95ac954c6..8e2fa8ab9 100644 --- a/include/maxscale/service.h +++ b/include/maxscale/service.h @@ -190,7 +190,7 @@ typedef enum count_spec_t extern SERVICE *service_alloc(const char *, const char *); extern int service_free(SERVICE *); -extern SERVICE *service_find(char *); +extern SERVICE *service_find(const char *); extern int service_isvalid(SERVICE *); extern int serviceAddProtocol(SERVICE *service, char *name, char *protocol, char *address, unsigned short port, diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index d232fe559..847d2fa42 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(maxscale-common SHARED adminusers.c alloc.c authenticator.c atomic.c buffer.c config.c dcb.c filter.c externcmd.c gwbitmask.c gwdirs.c hashtable.c hint.c housekeeper.c listmanager.c load_utils.c log_manager.cc maxscale_pcre2.c memlog.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c gw_ssl.c mysql_utils.c mysql_binlog.c modulecmd.c) +add_library(maxscale-common SHARED adminusers.c alloc.c authenticator.c atomic.c buffer.c config.c config_runtime.c dcb.c filter.c externcmd.c gwbitmask.c gwdirs.c hashtable.c hint.c housekeeper.c listmanager.c load_utils.c log_manager.cc maxscale_pcre2.c memlog.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.c poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c gw_ssl.c mysql_utils.c mysql_binlog.c modulecmd.c ) target_link_libraries(maxscale-common ${MARIADB_CONNECTOR_LIBRARIES} ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} ${CURL_LIBRARIES} ssl pthread crypt dl crypto inih z rt m stdc++) diff --git a/server/core/config_runtime.c b/server/core/config_runtime.c new file mode 100644 index 000000000..05760e113 --- /dev/null +++ b/server/core/config_runtime.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2016 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/bsl. + * + * Change Date: 2019-07-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. + */ + +#include +#include +#include + +static SPINLOCK crt_lock = SPINLOCK_INIT; + +bool runtime_link_server(SERVER *server, const char *target) +{ + spinlock_acquire(&crt_lock); + + bool rval = false; + SERVICE *service = service_find(target); + MONITOR *monitor = service ? NULL : monitor_find(target); + + if (service || monitor) + { + rval = true; + + if (service) + { + serviceAddBackend(service, server); + service_serialize_servers(service); + } + else if (monitor) + { + monitorAddServer(monitor, server); + monitor_serialize_servers(monitor); + } + + const char *type = service ? "service" : "monitor"; + + MXS_NOTICE("Added server '%s' to %s '%s'", server->unique_name, type, target); + } + + spinlock_release(&crt_lock); + return rval; +} + +bool runtime_unlink_server(SERVER *server, const char *target) +{ + spinlock_acquire(&crt_lock); + + bool rval = false; + SERVICE *service = service_find(target); + MONITOR *monitor = service ? NULL : monitor_find(target); + + if (service || monitor) + { + rval = true; + + if (service) + { + serviceRemoveBackend(service, server); + service_serialize_servers(service); + } + else if (monitor) + { + monitorRemoveServer(monitor, server); + monitor_serialize_servers(monitor); + } + + const char *type = service ? "service" : "monitor"; + MXS_NOTICE("Removed server '%s' from %s '%s'", server->unique_name, type, target); + } + + spinlock_release(&crt_lock); + return rval; +} + + +bool runtime_create_server(const char *name, const char *address, const char *port, + const char *protocol, const char *authenticator, + const char *authenticator_options) +{ + spinlock_acquire(&crt_lock); + bool rval = false; + + if (server_find_by_unique_name(name) == NULL) + { + // TODO: Get default values from the protocol module + if (port == NULL) + { + port = "3306"; + } + if (protocol == NULL) + { + protocol = "MySQLBackend"; + } + if (authenticator == NULL && (authenticator = get_default_authenticator(protocol)) == NULL) + { + MXS_ERROR("No authenticator defined for server '%s' and no default " + "authenticator for protocol '%s'.", name, protocol); + spinlock_release(&crt_lock); + return false; + } + + /** First check if this service has been created before */ + SERVER *server = server_find_destroyed(name, protocol, authenticator, + authenticator_options); + + if (server) + { + /** Found old server, replace network details with new ones and + * reactivate it */ + snprintf(server->name, sizeof(server->name), "%s", address); + server->port = atoi(port); + server->is_active = true; + rval = true; + } + else + { + /** + * server_alloc will add the server to the global list of + * servers so we don't need to manually add it. + */ + server = server_alloc(name, address, atoi(port), protocol, + authenticator, authenticator_options); + } + + if (server && server_serialize(server)) + { + rval = true; + } + } + + spinlock_release(&crt_lock); + return rval; +} + +bool runtime_destroy_server(SERVER *server) +{ + spinlock_acquire(&crt_lock); + bool rval = false; + + if (service_server_in_use(server) || monitor_server_in_use(server)) + { + MXS_ERROR("Cannot destroy server '%s' as it is used by at least one " + "service or monitor", server->unique_name); + } + else + { + char filename[PATH_MAX]; + snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), + server->unique_name); + + if (unlink(filename) == -1) + { + if (errno != ENOENT) + { + char err[MXS_STRERROR_BUFLEN]; + MXS_ERROR("Failed to remove persisted server configuration '%s': %d, %s", + filename, errno, strerror_r(errno, err, sizeof(err))); + } + else + { + rval = true; + MXS_WARNING("Server '%s' was not created at runtime. Remove the " + "server manually from the correct configuration file.", + server->unique_name); + } + } + else + { + rval = true; + } + + if (rval) + { + MXS_NOTICE("Destroyed server '%s' at %s:%u", server->unique_name, + server->name, server->port); + server->is_active = false; + } + } + + spinlock_release(&crt_lock); + return rval; +} diff --git a/server/core/monitor.c b/server/core/monitor.c index 50feaae6b..6a22ee70a 100644 --- a/server/core/monitor.c +++ b/server/core/monitor.c @@ -515,7 +515,7 @@ monitorList(DCB *dcb) * @return Pointer to the monitor or NULL */ MONITOR * -monitor_find(char *name) +monitor_find(const char *name) { MONITOR *ptr; diff --git a/server/core/server.c b/server/core/server.c index 570b47a6e..a06088baf 100644 --- a/server/core/server.c +++ b/server/core/server.c @@ -1228,8 +1228,7 @@ bool server_serialize(const SERVER *server) return rval; } -/** Try to find a server with a matching name that has been destroyed */ -static SERVER* find_destroyed_server(const char *name, const char *protocol, +SERVER* server_find_destroyed(const char *name, const char *protocol, const char *authenticator, const char *auth_options) { spinlock_acquire(&server_spin); @@ -1254,106 +1253,3 @@ static SERVER* find_destroyed_server(const char *name, const char *protocol, return server; } - -bool server_create(const char *name, const char *address, const char *port, - const char *protocol, const char *authenticator, - const char *authenticator_options) -{ - bool rval = false; - - if (server_find_by_unique_name(name) == NULL) - { - // TODO: Get default values from the protocol module - if (port == NULL) - { - port = "3306"; - } - if (protocol == NULL) - { - protocol = "MySQLBackend"; - } - if (authenticator == NULL && (authenticator = get_default_authenticator(protocol)) == NULL) - { - MXS_ERROR("No authenticator defined for server '%s' and no default " - "authenticator for protocol '%s'.", name, protocol); - return false; - } - - /** First check if this service has been created before */ - SERVER *server = find_destroyed_server(name, protocol, authenticator, - authenticator_options); - - if (server) - { - /** Found old server, replace network details with new ones and - * reactivate it */ - snprintf(server->name, sizeof(server->name), "%s", address); - server->port = atoi(port); - server->is_active = true; - rval = true; - } - else - { - /** - * server_alloc will add the server to the global list of - * servers so we don't need to manually add it. - */ - server = server_alloc(name, address, atoi(port), protocol, - authenticator, authenticator_options); - } - - if (server && server_serialize(server)) - { - rval = true; - } - } - - return rval; -} - -bool server_destroy(SERVER *server) -{ - bool rval = false; - - if (service_server_in_use(server) || monitor_server_in_use(server)) - { - MXS_ERROR("Cannot destroy server '%s' as it is used by at least one " - "service or monitor", server->unique_name); - } - else - { - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%s/%s.cnf", get_config_persistdir(), - server->unique_name); - - if (unlink(filename) == -1) - { - if (errno != ENOENT) - { - char err[MXS_STRERROR_BUFLEN]; - MXS_ERROR("Failed to remove persisted server configuration '%s': %d, %s", - filename, errno, strerror_r(errno, err, sizeof(err))); - } - else - { - rval = true; - MXS_WARNING("Server '%s' was not created at runtime. Remove the " - "server manually from the correct configuration file.", - server->unique_name); - } - } - else - { - rval = true; - } - - if (rval) - { - MXS_NOTICE("Destroyed server '%s' at %s:%u", server->unique_name, - server->name, server->port); - server->is_active = false; - } - } - - return rval; -} diff --git a/server/core/service.c b/server/core/service.c index cbc14e781..707360e06 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -1218,7 +1218,7 @@ serviceSetFilters(SERVICE *service, char *filters) * @return The service or NULL if not found */ SERVICE * -service_find(char *servname) +service_find(const char *servname) { SERVICE *service; diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index a7a94e03a..24e272398 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -73,6 +73,7 @@ #include #include #include +#include #include #include @@ -804,28 +805,9 @@ static void cmd_AddServer(DCB *dcb, SERVER *server, char *v1, char *v2, char *v3 for (int i = 0; i < items && values[i]; i++) { - SERVICE *service = service_find(values[i]); - MONITOR *monitor = monitor_find(values[i]); - - if (service || monitor) + if (runtime_link_server(server, values[i])) { - ss_dassert(service == NULL || monitor == NULL); - - if (service) - { - serviceAddBackend(service, server); - service_serialize_servers(service); - } - else if (monitor) - { - monitorAddServer(monitor, server); - monitor_serialize_servers(monitor); - } - - const char *target = service ? "service" : "monitor"; - - MXS_NOTICE("Added server '%s' to %s '%s'", server->unique_name, target, values[i]); - dcb_printf(dcb, "Added server '%s' to %s '%s'\n", server->unique_name, target, values[i]); + dcb_printf(dcb, "Added server '%s' to '%s'\n", server->unique_name, values[i]); } else { @@ -872,27 +854,9 @@ static void cmd_RemoveServer(DCB *dcb, SERVER *server, char *v1, char *v2, char for (int i = 0; i < items && values[i]; i++) { - SERVICE *service = service_find(values[i]); - MONITOR *monitor = monitor_find(values[i]); - - if (service || monitor) + if (runtime_unlink_server(server, values[i])) { - ss_dassert(service == NULL || monitor == NULL); - - if (service) - { - serviceRemoveBackend(service, server); - service_serialize_servers(service); - } - else if (monitor) - { - monitorRemoveServer(monitor, server); - monitor_serialize_servers(monitor); - } - - const char *target = service ? "service" : "monitor"; - MXS_NOTICE("Removed server '%s' from %s '%s'", server->unique_name, target, values[i]); - dcb_printf(dcb, "Removed server '%s' from %s '%s'\n", server->unique_name, target, values[i]); + dcb_printf(dcb, "Removed server '%s' from '%s'\n", server->unique_name, values[i]); } else { @@ -1044,7 +1008,7 @@ static void createServer(DCB *dcb, char *name, char *address, char *port, if (server_find_by_unique_name(name) == NULL) { - if (server_create(name, address, port, protocol, authenticator, authenticator_options)) + if (runtime_create_server(name, address, port, protocol, authenticator, authenticator_options)) { dcb_printf(dcb, "Created server '%s'\n", name); } @@ -1093,7 +1057,7 @@ static void destroyServer(DCB *dcb, SERVER *server) char name[strlen(server->unique_name) + 1]; strcpy(name, server->unique_name); - if (server_destroy(server)) + if (runtime_destroy_server(server)) { dcb_printf(dcb, "Destroyed server '%s'\n", name); }