Make server creation simpler

Server creation and allocation are now the same apart from the fact that
allocation only adds the server to the running configuration where as the
creation of a server also persist it to disk.

The server serialization should not be seen through the server.h API. This
allows the serialization method to change without actually having to
change the interfaces.
This commit is contained in:
Markus Makela 2016-11-11 10:13:14 +02:00
parent 16e8aa7178
commit 08ebb88aec
7 changed files with 174 additions and 119 deletions

View File

@ -201,9 +201,57 @@ typedef struct server
(((server)->status & (SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE|SERVER_MAINT)) == \
(SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE))
extern SERVER *server_alloc(char *, char *, unsigned short, char*, char*);
/**
* @brief Allocate a new server
*
* This will create a new server that represents a backend server that services
* can use. This function will add the server to the running configuration but
* will not persist the changes.
*
* @param name Unique server name
* @param address The server address
* @param port The port to connect to
* @param protocol The protocol to use to connect to the server
* @param authenticator The server authenticator module
* @param auth_options Options for the authenticator module
* @return The newly created server or NULL if an error occurred
*/
extern SERVER* server_alloc(const char *name, const char *address, unsigned short port,
const char *protocol, const char *authenticator,
const char *auth_options);
/**
* @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
*/
extern bool server_create(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 server_destroy(SERVER *server);
extern int server_free(SERVER *);
extern SERVER *server_find_by_unique_name(char *);
extern SERVER *server_find_by_unique_name(const char *name);
extern SERVER *server_find(char *, unsigned short);
extern void printServer(SERVER *);
extern void printAllServers();
@ -221,7 +269,6 @@ extern void serverAddMonUser(SERVER *, char *, char *);
extern void serverAddParameter(SERVER *, char *, char *);
extern char *serverGetParameter(SERVER *, char *);
extern void server_update_credentials(SERVER *, char *, char *);
extern void server_set_unique_name(SERVER *, char *);
extern DCB *server_get_persistent(SERVER *, char *, const char *);
extern void server_update_address(SERVER *, char *);
extern void server_update_port(SERVER *, unsigned short);
@ -231,26 +278,4 @@ extern bool server_set_version_string(SERVER* server, const char* string);
extern bool server_is_ssl_parameter(const char *key);
extern void server_update_ssl(SERVER *server, const char *key, const char *value);
/**
* @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(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);
MXS_END_DECLS

View File

@ -2730,11 +2730,7 @@ int create_new_server(CONFIG_CONTEXT *obj)
if (address && port && protocol)
{
if ((obj->element = server_alloc(address, protocol, atoi(port), auth, auth_opts)))
{
server_set_unique_name(obj->element, obj->object);
}
else
if ((obj->element = server_alloc(obj->object, address, atoi(port), protocol, auth, auth_opts)) == NULL)
{
MXS_ERROR("Failed to create a new server, memory allocation failed.");
error_count++;

View File

@ -57,57 +57,44 @@ static SERVER *allServers = NULL;
static void spin_reporter(void *, char *, int);
static void server_parameter_free(SERVER_PARAM *tofree);
/**
* Allocate a new server withn the gateway
*
*
* @param servname The server name
* @param protocol The protocol to use to connect to the server
* @param port The port to connect to
*
* @return The newly created server or NULL if an error occured
*/
SERVER *
server_alloc(char *servname, char *protocol, unsigned short port, char *authenticator,
char *auth_options)
SERVER* server_alloc(const char *name, const char *address, unsigned short port,
const char *protocol, const char *authenticator, const char *auth_options)
{
if (authenticator)
if (authenticator == NULL && (authenticator = get_default_authenticator(protocol)) == NULL)
{
authenticator = MXS_STRDUP(authenticator);
}
else if ((authenticator = (char*)get_default_authenticator(protocol)) == NULL ||
(authenticator = MXS_STRDUP(authenticator)) == NULL)
{
MXS_ERROR("No authenticator defined for server at %s:%u and no default "
"authenticator for protocol '%s'.", servname, port, protocol);
MXS_ERROR("No authenticator defined for server '%s' and no default "
"authenticator for protocol '%s'.", name, protocol);
return NULL;
}
void *auth_instance = NULL;
if (!authenticator_init(&auth_instance, authenticator, auth_options))
{
MXS_ERROR("Failed to initialize authenticator module '%s' for server"
" at %s:%u.", authenticator, servname, port);
MXS_FREE(authenticator);
MXS_ERROR("Failed to initialize authenticator module '%s' for server '%s' ",
authenticator, name);
return NULL;
}
if (auth_options && (auth_options = MXS_STRDUP(auth_options)) == NULL)
char *my_auth_options = NULL;
if (auth_options && (my_auth_options = MXS_STRDUP(auth_options)) == NULL)
{
MXS_FREE(authenticator);
return NULL;
}
protocol = MXS_STRDUP(protocol);
SERVER *server = (SERVER *)MXS_CALLOC(1, sizeof(SERVER));
char *my_name = MXS_STRDUP(name);
char *my_protocol = MXS_STRDUP(protocol);
char *my_authenticator = MXS_STRDUP(authenticator);
if (!protocol || !server || !authenticator)
if (!server || !my_name || !my_protocol || !my_authenticator)
{
MXS_FREE(servname);
MXS_FREE(protocol);
MXS_FREE(server);
MXS_FREE(authenticator);
MXS_FREE(my_name);
MXS_FREE(my_protocol);
MXS_FREE(my_authenticator);
return NULL;
}
@ -115,11 +102,12 @@ server_alloc(char *servname, char *protocol, unsigned short port, char *authenti
server->server_chk_top = CHK_NUM_SERVER;
server->server_chk_tail = CHK_NUM_SERVER;
#endif
snprintf(server->name, sizeof(server->name), "%s", servname);
server->protocol = protocol;
server->authenticator = authenticator;
server->unique_name = my_name;
snprintf(server->name, sizeof(server->name), "%s", address);
server->protocol = my_protocol;
server->authenticator = my_authenticator;
server->auth_instance = auth_instance;
server->auth_options = auth_options;
server->auth_options = my_auth_options;
server->port = port;
server->status = SERVER_RUNNING;
server->node_id = -1;
@ -258,32 +246,16 @@ server_get_persistent(SERVER *server, char *user, const char *protocol)
}
/**
* Set a unique name for the server
* @brief Find a server with the specified name
*
* @param server The server to set the name on
* @param name The unique name for the server
* @param name Name of the server
* @return The server or NULL if not found
*/
void
server_set_unique_name(SERVER *server, char *name)
SERVER * server_find_by_unique_name(const char *name)
{
server->unique_name = MXS_STRDUP_A(name);
}
/**
* Find an existing server using the unique section name in
* configuration file
*
* @param servname The Server name or address
* @param port The server port
* @return The server or NULL if not found
*/
SERVER *
server_find_by_unique_name(char *name)
{
SERVER *server;
spinlock_acquire(&server_spin);
server = allServers;
SERVER *server = allServers;
while (server)
{
if (server->is_active && server->unique_name && strcmp(server->unique_name, name) == 0)
@ -293,6 +265,7 @@ server_find_by_unique_name(char *name)
server = server->next;
}
spinlock_release(&server_spin);
return server;
}
@ -1205,7 +1178,17 @@ static bool create_server_config(SERVER *server, const char *filename)
return true;
}
bool server_serialize(SERVER *server)
/**
* @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
*/
static bool server_serialize(SERVER *server)
{
bool rval = false;
char filename[PATH_MAX];
@ -1242,6 +1225,78 @@ bool server_serialize(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,
const char *authenticator, const char *auth_options)
{
spinlock_acquire(&server_spin);
SERVER *server = allServers;
while (server)
{
CHK_SERVER(server);
if (strcmp(server->unique_name, name) == 0 &&
strcmp(server->protocol, protocol) == 0 &&
strcmp(server->authenticator, authenticator) == 0)
{
if ((auth_options == NULL && server->auth_options == NULL) ||
(auth_options && server->auth_options &&
strcmp(server->auth_options, auth_options) == 0))
{
break;
}
}
server = server->next;
}
spinlock_release(&server_spin);
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)
{
if (port == NULL)
{
port = "3306";
}
if (protocol == NULL)
{
protocol = "MySQLBackend";
}
/** 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 if ((server = server_alloc(name, address, atoi(port), protocol, authenticator,
authenticator_options)))
{
if (server_serialize(server))
{
/** server_alloc will add the server to the global list of
* servers so we don't need to manually add it. */
rval = true;
}
}
}
return rval;
}
bool server_destroy(SERVER *server)
{
bool rval = false;

View File

@ -40,6 +40,7 @@
// This is pretty ugly but it's required to test internal functions
#include "../config.c"
#include "../server.c"
/**
* test1 Allocate a server and do lots of other things
@ -55,7 +56,7 @@ test1()
/* Server tests */
ss_dfprintf(stderr, "testserver : creating server called MyServer");
set_libdir(MXS_STRDUP_A("../../modules/authenticator/"));
server = server_alloc("MyServer", "HTTPD", 9876, "NullAuthAllow", NULL);
server = server_alloc("uniquename", "127.0.0.1", 9876, "HTTPD", "NullAuthAllow", NULL);
ss_info_dassert(server, "Allocating the server should not fail");
mxs_log_flush_sync();
@ -71,7 +72,6 @@ test1()
ss_dfprintf(stderr, "\t..done\nTesting Unique Name for Server.");
ss_info_dassert(NULL == server_find_by_unique_name("uniquename"),
"Should not find non-existent unique name.");
server_set_unique_name(server, "uniquename");
mxs_log_flush_sync();
ss_info_dassert(server == server_find_by_unique_name("uniquename"), "Should find by unique name.");
ss_dfprintf(stderr, "\t..done\nTesting Status Setting for Server.");
@ -144,9 +144,8 @@ bool test_serialize()
char old_config_name[] = "serialized-server.cnf.old";
char *persist_dir = MXS_STRDUP_A("./");
set_config_persistdir(persist_dir);
SERVER *server = server_alloc("127.0.0.1", "HTTPD", 9876, "NullAuthAllow", "fake=option");
SERVER *server = server_alloc(name, "127.0.0.1", 9876, "HTTPD", "NullAuthAllow", "fake=option");
TEST(server, "Server allocation failed");
server_set_unique_name(server, name);
/** Make sure the files don't exist */
unlink(config_name);

View File

@ -585,7 +585,8 @@ createInstance(SERVICE *service, char **options)
{
SERVER *server;
SSL_LISTENER *ssl_cfg;
server = server_alloc("_none_", "MySQLBackend", 3306, "MySQLBackendAuth", NULL);
server = server_alloc("binlog_router_master_host", "_none_", 3306,
"MySQLBackend", "MySQLBackendAuth", NULL);
if (server == NULL)
{
MXS_ERROR("%s: Error for server_alloc in createInstance",
@ -617,7 +618,6 @@ createInstance(SERVICE *service, char **options)
server->server_ssl = ssl_cfg;
/* Set server unique name */
server_set_unique_name(server, "binlog_router_master_host");
/* Add server to service backend list */
serviceAddBackend(inst->service, server);
}

View File

@ -103,12 +103,12 @@ int main(int argc, char **argv) {
s = strtok_r(NULL, ",", &lasts);
}
set_libdir(MXS_STRDUP_A("../../../authenticator/"));
server = server_alloc("_none_", "MySQLBackend", 3306, "MySQLBackendAuth", NULL);
server = server_alloc("binlog_router_master_host", "_none_", 3306,
"MySQLBackend", "MySQLBackendAuth", NULL);
if (server == NULL) {
return 1;
}
server_set_unique_name(server, "binlog_router_master_host");
serviceAddBackend(service, server);
}

View File

@ -1005,29 +1005,9 @@ static void createServer(DCB *dcb, char *name, char *address, char *port,
if (server_find_by_unique_name(name) == NULL)
{
if (protocol == NULL)
if (server_create(name, address, port, protocol, authenticator, authenticator_options))
{
protocol = "MySQLBackend";
}
SERVER *server = server_alloc(address, protocol, atoi(port), authenticator,
authenticator_options);
if (server)
{
server_set_unique_name(server, name);
if (server_serialize(server))
{
dcb_printf(dcb, "Created server '%s'\n", name);
}
else
{
dcb_printf(dcb, "WARNING: The server was added to the runtime \n"
"configuration but persisting the new server to disk \n"
"failed. This server will NOT be loaded when MaxScale \n"
"is restarted. See log file for more details on why it failed.\n");
}
dcb_printf(dcb, "Created server '%s'\n", name);
}
else
{