Name change to MaxScale rather than gateway

Addition of code for dynamic reconfiguration by editign the cnf file and sendign a SIGHUP

Improvements to the make install rule
This commit is contained in:
Mark Riddoch
2013-07-17 13:32:04 +02:00
parent b6cbe3a34c
commit 02e60e215b
23 changed files with 499 additions and 90 deletions

View File

@ -1,2 +1,3 @@
core/tags core/tags
gateway gateway
core/maxscale

View File

@ -22,6 +22,7 @@
# 18/06/13 Mark Riddoch Addition of install target # 18/06/13 Mark Riddoch Addition of install target
# 21/06/13 Mark Riddoch Addition of inih # 21/06/13 Mark Riddoch Addition of inih
# 08/07/13 Mark Riddoch Addition of monitor modules # 08/07/13 Mark Riddoch Addition of monitor modules
# 16/07/13 Mark Riddoch Renamed things to match the new naming
DEST=/home/mriddoch/usr/local/skysql DEST=/home/mriddoch/usr/local/skysql
@ -50,11 +51,12 @@ documentation:
doxygen doxygate doxygen doxygate
install: install:
@mkdir -p $(DEST)/gateway/modules @mkdir -p $(DEST)/MaxScale/modules
@mkdir -p $(DEST)/gateway/log @mkdir -p $(DEST)/MaxScale/log
@mkdir -p $(DEST)/gateway/etc @mkdir -p $(DEST)/MaxScale/etc
install gateway.cnf $(DEST)/gateway/etc @mkdir -p $(DEST)/lib
install MaxScale.cnf $(DEST)/MaxScale/etc
(cd core; make DEST=$(DEST) install) (cd core; make DEST=$(DEST) install)
(cd modules/routing; make DEST=$(DEST) install) (cd modules/routing; make DEST=$(DEST) install)
(cd modules/protocol; make DEST=$(DEST) install) (cd modules/protocol; make DEST=$(DEST) install)
(cd modules/moinitor; make DEST=$(DEST) install) (cd modules/monitor; make DEST=$(DEST) install)

View File

@ -70,14 +70,14 @@ LIBS=-L../inih/extra -linih -lssl -lstdc++ \
-lz -lm -lcrypto -ldl -pthread -llog_manager \ -lz -lm -lcrypto -ldl -pthread -llog_manager \
-lmysqld -lmysqld
gateway: $(OBJ) maxscale: $(OBJ)
$(CC) $(LDFLAGS) $(OBJ) $(UTILSPATH)/skygw_utils.o $(LIBS) -o $@ $(CC) $(LDFLAGS) $(OBJ) $(UTILSPATH)/skygw_utils.o $(LIBS) -o $@
.c.o: .c.o:
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@
clean: clean:
rm -f $(OBJ) gateway rm -f $(OBJ) maxscale
- rm *.so - rm *.so
tags: tags:
@ -87,7 +87,7 @@ depend:
@rm -f depend.mk @rm -f depend.mk
cc -M $(CFLAGS) $(SRCS) > depend.mk cc -M $(CFLAGS) $(SRCS) > depend.mk
install: gateway install: maxscale
@mkdir -p $(DEST)/bin @mkdir -p $(DEST)/bin
install -D $< $(DEST)/bin install -D $< $(DEST)/bin

View File

@ -39,11 +39,13 @@
#include <monitor.h> #include <monitor.h>
static int process_config_context(CONFIG_CONTEXT *); static int process_config_context(CONFIG_CONTEXT *);
static int process_config_update(CONFIG_CONTEXT *);
static void free_config_context(CONFIG_CONTEXT *); static void free_config_context(CONFIG_CONTEXT *);
static char *config_get_value(CONFIG_PARAMETER *, const char *); static char *config_get_value(CONFIG_PARAMETER *, const char *);
static int handle_global_item(const char *, const char *); static int handle_global_item(const char *, const char *);
static void global_defaults(); static void global_defaults();
static char *config_file = NULL;
static GATEWAY_CONF gateway; static GATEWAY_CONF gateway;
/** /**
@ -93,6 +95,7 @@ CONFIG_PARAMETER *param;
} }
/** /**
* Load the configuration file for the gateway
* *
* @param file The filename of the configuration file * @param file The filename of the configuration file
*/ */
@ -110,12 +113,40 @@ int rval;
if (ini_parse(file, handler, &config) < 0) if (ini_parse(file, handler, &config) < 0)
return 0; return 0;
config_file = file;
rval = process_config_context(config.next); rval = process_config_context(config.next);
free_config_context(config.next); free_config_context(config.next);
return rval; return rval;
} }
/**
* Relooad the configuration file for the gateway
*
*/
int
config_reload()
{
CONFIG_CONTEXT config;
int rval;
if (!config_file)
return 0;
global_defaults();
config.object = "";
config.next = NULL;
if (ini_parse(config_file, handler, &config) < 0)
return 0;
rval = process_config_update(config.next);
free_config_context(config.next);
return rval;
}
/** /**
* Process a configuration context and turn it into the set of object * Process a configuration context and turn it into the set of object
* we need. * we need.
@ -336,3 +367,142 @@ global_defaults()
{ {
gateway.n_threads = 1; gateway.n_threads = 1;
} }
/**
* Process a configuration context update and turn it into the set of object
* we need.
*
* @param context The configuration data
*/
static int
process_config_update(CONFIG_CONTEXT *context)
{
CONFIG_CONTEXT *obj;
SERVICE *service;
SERVER *server;
/**
* Process the data and create the services and servers defined
* in the data.
*/
obj = context;
while (obj)
{
char *type = config_get_value(obj->parameters, "type");
if (type == NULL)
fprintf(stderr, "Object %s has no type\n", obj->object);
else if (!strcmp(type, "service"))
{
char *router = config_get_value(obj->parameters, "router");
if (router)
{
if ((service = service_find(obj->object)) != NULL)
{
char *user = config_get_value(obj->parameters, "user");
char *auth = config_get_value(obj->parameters, "auth");
service_update(service, router, user, auth);
obj->element = service;
}
else
{
obj->element = service_alloc(obj->object, router);
char *user = config_get_value(obj->parameters, "user");
char *auth = config_get_value(obj->parameters, "auth");
if (obj->element && user && auth)
serviceSetUser(obj->element, user, auth);
}
}
else
fprintf(stderr, "No router defined for service '%s'\n",
obj->object);
}
else if (!strcmp(type, "server"))
{
char *address = config_get_value(obj->parameters, "address");
char *port = config_get_value(obj->parameters, "port");
char *protocol = config_get_value(obj->parameters, "protocol");
char *monuser = config_get_value(obj->parameters, "monitoruser");
char *monpw = config_get_value(obj->parameters, "monitorpw");
if (address && port && protocol)
{
if ((server = server_find(address, atoi(port))) != NULL)
{
server_update(server, protocol, monuser, monpw);
obj->element = server;
}
else
{
obj->element = server_alloc(address, protocol, atoi(port));
if (obj->element && monuser && monpw)
serverAddMonUser(obj->element, monuser, monpw);
}
}
}
obj = obj->next;
}
/*
* Now we have the services we can add the servers to the services
* add the protocols to the services
*/
obj = context;
while (obj)
{
char *type = config_get_value(obj->parameters, "type");
if (type == NULL)
;
else if (!strcmp(type, "service"))
{
char *servers = config_get_value(obj->parameters, "servers");
char *roptions = config_get_value(obj->parameters, "router_options");
if (servers && obj->element)
{
char *s = strtok(servers, ",");
while (s)
{
CONFIG_CONTEXT *obj1 = context;
while (obj1)
{
if (strcmp(s, obj1->object) == 0 && obj->element && obj1->element)
if (!serviceHasBackend(obj->element, obj1->element))
serviceAddBackend(obj->element, obj1->element);
obj1 = obj1->next;
}
s = strtok(NULL, ",");
}
}
if (roptions && obj->element)
{
char *s = strtok(roptions, ",");
serviceClearRouterOptions(obj->element);
while (s)
{
serviceAddRouterOption(obj->element, s);
s = strtok(NULL, ",");
}
}
}
else if (!strcmp(type, "listener"))
{
char *service = config_get_value(obj->parameters, "service");
char *port = config_get_value(obj->parameters, "port");
char *protocol = config_get_value(obj->parameters, "protocol");
if (service && port && protocol)
{
CONFIG_CONTEXT *ptr = context;
while (ptr && strcmp(ptr->object, service) != 0)
ptr = ptr->next;
if (ptr && ptr->element && serviceHasProtocol(ptr->element, protocol, atoi(port)) == 0)
{
serviceAddProtocol(ptr->element, protocol, atoi(port));
serviceStartProtocol(ptr->element, protocol, atoi(port));
}
}
}
obj = obj->next;
}
return 1;
}

View File

@ -83,9 +83,14 @@ static char* server_groups[] = {
/* The data directory we created for this gateway instance */ /* The data directory we created for this gateway instance */
static char datadir[1024] = ""; static char datadir[1024] = "";
/* basic signal handling */ /**
static void sighup_handler (int i) { * Handler for SIGHUP signal. Reload the configuration for the
skygw_log_write(NULL, LOGFILE_ERROR, "Signal SIGHUP %i received ...\n", i); * gateway.
*/
static void sighup_handler (int i)
{
skygw_log_write(NULL, LOGFILE_MESSAGE, "Refreshing configuration following SIGHUP\n");
config_reload();
} }
static void sigterm_handler (int i) { static void sigterm_handler (int i) {
@ -241,14 +246,14 @@ char ddopt[1024];
#endif #endif
atexit(datadir_cleanup); atexit(datadir_cleanup);
if ((home = getenv("GATEWAY_HOME")) != NULL) if ((home = getenv("MAXSCALE_HOME")) != NULL)
{ {
sprintf(buf, "%s/etc/gateway.cnf", home); sprintf(buf, "%s/etc/MaxScale.cnf", home);
if (access(buf, R_OK) == 0) if (access(buf, R_OK) == 0)
cnf_file = buf; cnf_file = buf;
} }
if (cnf_file == NULL && access("/etc/gateway.cnf", R_OK) == 0) if (cnf_file == NULL && access("/etc/MaxScale.cnf", R_OK) == 0)
cnf_file = "/etc/gateway.cnf"; cnf_file = "/etc/MaxScale.cnf";
/* /*
* Set a data directory for the mysqld library, we use * Set a data directory for the mysqld library, we use
@ -263,13 +268,13 @@ char ddopt[1024];
} }
else else
{ {
sprintf(datadir, "/tmp/gateway/data%d", getpid()); sprintf(datadir, "/tmp/MaxScale/data%d", getpid());
mkdir("/tmp/gateway", 0777); mkdir("/tmp/MaxScale", 0777);
mkdir(datadir, 0777); mkdir(datadir, 0777);
} }
/* /*
* If $GATEWAY_HOME is set then write the logs into $GATEWAY_HOME/log. * If $MAXSCALE_HOME is set then write the logs into $MAXSCALE_HOME/log.
* The skygw_logmanager_init expects to take arguments as passed to main * The skygw_logmanager_init expects to take arguments as passed to main
* and proesses them with getopt, therefore we need to give it a dummy * and proesses them with getopt, therefore we need to give it a dummy
* argv[0] * argv[0]
@ -281,7 +286,7 @@ char ddopt[1024];
sprintf(buf, "%s/log", home); sprintf(buf, "%s/log", home);
mkdir(buf, 0777); mkdir(buf, 0777);
argv[0] = "gateway"; argv[0] = "MaxScale";
argv[1] = "-g"; argv[1] = "-g";
argv[2] = buf; argv[2] = buf;
argv[3] = NULL; argv[3] = NULL;
@ -307,8 +312,8 @@ char ddopt[1024];
if (cnf_file == NULL) { if (cnf_file == NULL) {
skygw_log_write( skygw_log_write(
NULL, LOGFILE_ERROR, NULL, LOGFILE_ERROR,
"Fatal : Unable to find a gateway configuration file, either " "Fatal : Unable to find a MaxScale configuration file, either "
"install one in /etc/gateway.cnf, $GATEWAY_HOME/etc/gateway.cnf " "install one in /etc/MaxScale.cnf, $MAXSCALE_HOME/etc/MaxScale.cnf "
"or use the -c option. Exiting.\n"); "or use the -c option. Exiting.\n");
exit(1); exit(1);
} }
@ -328,7 +333,7 @@ char ddopt[1024];
skygw_log_write_flush( skygw_log_write_flush(
NULL, LOGFILE_ERROR, NULL, LOGFILE_ERROR,
"Fatal : mysql_library_init failed, %s. This is mandatory component, required " "Fatal : mysql_library_init failed, %s. This is mandatory component, required "
"by router services and the gateway core, the gateway can't continue without it. Exiting.\n" "by router services and the MaxScale core, the MaxScale can't continue without it. Exiting.\n"
"%s : %d\n", mysql_error(NULL), __FILE__, __LINE__); "%s : %d\n", mysql_error(NULL), __FILE__, __LINE__);
exit(1); exit(1);
} }
@ -337,7 +342,7 @@ char ddopt[1024];
{ {
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_ERROR, LOGFILE_ERROR,
"Failed to load gateway configuration file %s\n", cnf_file); "Failed to load MaxScale configuration file %s\n", cnf_file);
exit(1); exit(1);
} }
@ -368,7 +373,7 @@ char ddopt[1024];
gw_daemonize(); gw_daemonize();
} }
skygw_log_write(NULL, LOGFILE_MESSAGE, "GATEWAY is starting, PID %i\n", getpid()); skygw_log_write(NULL, LOGFILE_MESSAGE, "MaxScale is starting, PID %i\n", getpid());
poll_init(); poll_init();
@ -390,7 +395,7 @@ char ddopt[1024];
for (n = 0; n < n_threads - 1; n++) for (n = 0; n < n_threads - 1; n++)
thread_wait(threads[n]); thread_wait(threads[n]);
skygw_log_write(NULL, LOGFILE_MESSAGE, "GATEWAY shutdown, PID %i\n", getpid()); skygw_log_write(NULL, LOGFILE_MESSAGE, "MaxScale shutdown, PID %i\n", getpid());
return 0; return 0;
} // End of main } // End of main

View File

@ -184,10 +184,10 @@ unsigned char *ptr, *eptr;
} }
/** /**
* Copy the contents of one bitmap to another.
* *
* @param bitmask Pointer the bitmask * @param dest Bitmap tp update
* @param value Value to be added * @param src Bitmap to copy
* @return The value of *variable before the add occured
*/ */
void void
bitmask_copy(GWBITMASK *dest, GWBITMASK *src) bitmask_copy(GWBITMASK *dest, GWBITMASK *src)

View File

@ -48,7 +48,7 @@ static void unregister_module(const char *module);
/** /**
* Load the dynamic library related to a gateway module. The routine * Load the dynamic library related to a gateway module. The routine
* will look for library files in the current directory, * will look for library files in the current directory,
* $GATEWAY_HOME/modules and /usr/local/skysql/gateway/modules. * $MAXSCALE_HOME/modules and /usr/local/skysql/MaxScale/modules.
* *
* @param module Name of the module to load * @param module Name of the module to load
* @param type Type of module, used purely for registration * @param type Type of module, used purely for registration
@ -74,8 +74,8 @@ MODULES *mod;
sprintf(fname, "./lib%s.so", module); sprintf(fname, "./lib%s.so", module);
if (access(fname, F_OK) == -1) if (access(fname, F_OK) == -1)
{ {
if ((home = getenv("GATEWAY_HOME")) == NULL) if ((home = getenv("MAXSCALE_HOME")) == NULL)
home = "/usr/local/skysql/gateway"; home = "/usr/local/skysql/MaxScale";
sprintf(fname, "%s/modules/lib%s.so", home, module); sprintf(fname, "%s/modules/lib%s.so", home, module);
if (access(fname, F_OK) == -1) if (access(fname, F_OK) == -1)
{ {

View File

@ -43,6 +43,7 @@ static SPINLOCK monLock = SPINLOCK_INIT;
* and start execution on the monitor. * and start execution on the monitor.
* *
* @param name The name of the monitor module to load * @param name The name of the monitor module to load
* @param module The module to load
* @return The newly created monitor * @return The newly created monitor
*/ */
MONITOR * MONITOR *
@ -56,7 +57,6 @@ MONITOR *mon;
} }
mon->name = strdup(name); mon->name = strdup(name);
mon->module = strdup(module);
if ((mon->module = load_module(module, MODULE_MONITOR)) == NULL) if ((mon->module = load_module(module, MODULE_MONITOR)) == NULL)
{ {
fprintf(stderr, "Unable to load monitor module '%s'\n", name); fprintf(stderr, "Unable to load monitor module '%s'\n", name);

View File

@ -132,7 +132,7 @@ struct epoll_event ev;
* deschedule a process if a timeout is included, but will not do this if a 0 timeout * deschedule a process if a timeout is included, but will not do this if a 0 timeout
* value is given. this improves performance when the gateway is under heavy load. * value is given. this improves performance when the gateway is under heavy load.
* *
* @parm arg The thread ID passed as a void * to satisfy the threading package * @param arg The thread ID passed as a void * to satisfy the threading package
*/ */
void void
poll_waitevents(void *arg) poll_waitevents(void *arg)

View File

@ -34,6 +34,8 @@
#include <server.h> #include <server.h>
#include <spinlock.h> #include <spinlock.h>
#include <dcb.h> #include <dcb.h>
#include <skygw_utils.h>
#include <log_manager.h>
static SPINLOCK server_spin = SPINLOCK_INIT; static SPINLOCK server_spin = SPINLOCK_INIT;
static SERVER *allServers = NULL; static SERVER *allServers = NULL;
@ -107,6 +109,30 @@ SERVER *ptr;
return 1; return 1;
} }
/**
* Find an existing server
*
* @param servname The Server name or address
* @param port The server port
* @return The server or NULL if not found
*/
SERVER *
server_find(char *servname, unsigned short port)
{
SERVER *server;
spinlock_acquire(&server_spin);
server = allServers;
while (server)
{
if (strcmp(server->name, servname) == 0 && server->port == port)
break;
server = server->next;
}
spinlock_release(&server_spin);
return server;
}
/** /**
* Print details of an individual server * Print details of an individual server
* *
@ -253,3 +279,38 @@ serverAddMonUser(SERVER *server, char *user, char *passwd)
server->monuser = strdup(user); server->monuser = strdup(user);
server->monpw = strdup(passwd); server->monpw = strdup(passwd);
} }
/**
* Check and update a server definition following a configuration
* update. Changes will not affect any current connections to this
* server, however all new connections will use the new settings.
*
* If the new settings are different from those already applied to the
* server then a message will be written to the log.
*
* @param server The server to update
* @param protocol The new protocol for the server
* @param user The monitor user for the server
* @param passwd The password to use for the monitor user
*/
void
server_update(SERVER *server, char *protocol, char *user, char *passwd)
{
if (!strcmp(server->protocol, protocol))
{
skygw_log_write(NULL, LOGFILE_MESSAGE, "Update server protocol for server %s to protocol %s",
server->name, protocol);
free(server->protocol);
server->protocol = strdup(protocol);
}
if (strcmp(server->monuser, user) == 0 || strcmp(server->monpw, passwd) == 0)
{
skygw_log_write(NULL, LOGFILE_MESSAGE, "Update server monitor credentials for server %s",
server->name);
free(server->monuser);
free(server->monpw);
serverAddMonUser(server, user, passwd);
}
}

View File

@ -40,6 +40,8 @@
#include <users.h> #include <users.h>
#include <dbusers.h> #include <dbusers.h>
#include <poll.h> #include <poll.h>
#include <skygw_utils.h>
#include <log_manager.h>
static SPINLOCK service_spin = SPINLOCK_INIT; static SPINLOCK service_spin = SPINLOCK_INIT;
static SERVICE *allServices = NULL; static SERVICE *allServices = NULL;
@ -87,33 +89,22 @@ SERVICE *service;
} }
/** /**
* Start a service * Start an individual port/protocol pair
* *
* This function loads the protocol modules for each port on which the * @param service The service
* service listens and starts the listener on that port * @param port The port to start
* * @return The number of listeners started
* Also create the router_instance for the service.
*
* @param service The Service that should be started
* @return Returns the number of listeners created
*/ */
int static int
serviceStart(SERVICE *service) serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{ {
SERV_PROTOCOL *port;
int listeners = 0; int listeners = 0;
char config_bind[40]; char config_bind[40];
GWPROTOCOL *funcs; GWPROTOCOL *funcs;
service->router_instance = service->router->createInstance(service,
service->routerOptions);
port = service->ports;
while (port)
{
if ((port->listener = dcb_alloc()) == NULL) if ((port->listener = dcb_alloc()) == NULL)
{ {
break; return 0;
} }
if (strcmp(port->protocol, "MySQLClient") == 0) { if (strcmp(port->protocol, "MySQLClient") == 0) {
@ -121,7 +112,7 @@ GWPROTOCOL *funcs;
loaded = load_mysql_users(service); loaded = load_mysql_users(service);
fprintf(stderr, "@@@@ MySQL Users loaded: %i\n", loaded); skygw_log_write(NULL, LOGFILE_MESSAGE, "MySQL Users loaded: %i\n", loaded);
} }
if ((funcs = (GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL) if ((funcs = (GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
@ -137,6 +128,33 @@ GWPROTOCOL *funcs;
port->listener->session = session_alloc(service, port->listener); port->listener->session = session_alloc(service, port->listener);
port->listener->session->state = SESSION_STATE_LISTENER; port->listener->session->state = SESSION_STATE_LISTENER;
return listeners;
}
/**
* Start a service
*
* This function loads the protocol modules for each port on which the
* service listens and starts the listener on that port
*
* Also create the router_instance for the service.
*
* @param service The Service that should be started
* @return Returns the number of listeners created
*/
int
serviceStart(SERVICE *service)
{
SERV_PROTOCOL *port;
int listeners = 0;
service->router_instance = service->router->createInstance(service,
service->routerOptions);
port = service->ports;
while (port)
{
listeners += serviceStartPort(service, port);
port = port->next; port = port->next;
} }
if (listeners) if (listeners)
@ -145,6 +163,28 @@ GWPROTOCOL *funcs;
return listeners; return listeners;
} }
/**
* Start an individual listener
*
* @param service The service to start the listener for
* @param protocol The name of the protocol
* @param port The port number
*/
void
serviceStartProtocol(SERVICE *service, char *protocol, int port)
{
SERV_PROTOCOL *ptr;
ptr = service->ports;
while (ptr)
{
if (strcmp(ptr->protocol, protocol) == 0 && ptr->port == port)
serviceStartPort(service, ptr);
ptr = ptr->next;
}
}
/** /**
* Start all the services * Start all the services
* *
@ -289,6 +329,32 @@ SERV_PROTOCOL *proto;
return 1; return 1;
} }
/**
* Check if a protocol/port pair si part of the service
*
* @param service The service
* @param protocol The name of the protocol module
* @param port The port to listen on
* @return TRUE if the protocol/port is already part of the service
*/
int
serviceHasProtocol(SERVICE *service, char *protocol, unsigned short port)
{
SERV_PROTOCOL *proto;
spinlock_acquire(&service->spin);
proto = service->ports;
while (proto)
{
if (strcmp(proto->protocol, protocol) == 0 && proto->port == port)
break;
proto = proto->next;
}
spinlock_release(&service->spin);
return proto != NULL;
}
/** /**
* Add a backend database server to a service * Add a backend database server to a service
* *
@ -304,6 +370,27 @@ serviceAddBackend(SERVICE *service, SERVER *server)
spinlock_release(&service->spin); spinlock_release(&service->spin);
} }
/**
* Test if a server is part of a service
*
* @param service The service to add the server to
* @param server The server to add
* @return Non-zero if the server is already part of the service
*/
int
serviceHasBackend(SERVICE *service, SERVER *server)
{
SERVER *ptr;
spinlock_acquire(&service->spin);
ptr = service->databases;
while (ptr && ptr != server)
ptr = ptr->nextdb;
spinlock_release(&service->spin);
return ptr != NULL;
}
/** /**
* Add a router option to a service * Add a router option to a service
* *
@ -334,6 +421,23 @@ int i;
spinlock_release(&service->spin); spinlock_release(&service->spin);
} }
/**
* Remove the router options for the service
*
* @param service The service to remove the options from
*/
void
serviceClearRouterOptions(SERVICE *service)
{
int i;
spinlock_acquire(&service->spin);
for (i = 0; service->routerOptions[i]; i++)
free(service->routerOptions[i]);
free(service->routerOptions);
service->routerOptions = NULL;
spinlock_release(&service->spin);
}
/** /**
* Set the service user that is used to log in to the backebd servers * Set the service user that is used to log in to the backebd servers
* associated with this service. * associated with this service.
@ -378,6 +482,27 @@ serviceGetUser(SERVICE *service, char **user, char **auth)
return 1; return 1;
} }
/**
* Return a named service
*
* @param servname The name of the service to find
* @return The service or NULL if not found
*/
SERVICE *
service_find(char *servname)
{
SERVICE *service;
spinlock_acquire(&service_spin);
service = allServices;
while (service && strcmp(service->name, servname) != 0)
service = service->next;
spinlock_release(&service_spin);
return service;
}
/** /**
* Print details of an individual service * Print details of an individual service
* *
@ -462,3 +587,39 @@ SERVICE *ptr;
} }
spinlock_release(&service_spin); spinlock_release(&service_spin);
} }
/**
* Update the definition of a service
*
* @param service The service to update
* @param router The router module to use
* @param user The user to use to extract information from the database
* @param auth The password for the user above
*/
void
service_update(SERVICE *service, char *router, char *user, char *auth)
{
void *router_obj;
if (!strcmp(service->routerModule, router))
{
if ((router_obj = load_module(router, MODULE_ROUTER)) == NULL)
{
skygw_log_write(NULL, LOGFILE_ERROR, "Failed to update router for service %s to %s",
service->name, router);
}
else
{
skygw_log_write(NULL, LOGFILE_MESSAGE, "Update router for service %s to %s",
service->name, router);
free(service->routerModule);
service->routerModule = strdup(router);
service->router = router_obj;
}
}
if (strcmp(service->credentials.name, user) == 0 || strcmp(service->credentials.authdata, auth) == 0)
{
skygw_log_write(NULL, LOGFILE_MESSAGE, "Update credentials for service %s", service->name);
serviceSetUser(service, user, auth);
}
}

View File

@ -58,5 +58,6 @@ typedef struct {
} GATEWAY_CONF; } GATEWAY_CONF;
extern int config_load(char *); extern int config_load(char *);
extern int config_reload();
extern int config_threadcount(); extern int config_threadcount();
#endif #endif

View File

@ -96,6 +96,7 @@ typedef struct server {
extern SERVER *server_alloc(char *, char *, unsigned short); extern SERVER *server_alloc(char *, char *, unsigned short);
extern int server_free(SERVER *); extern int server_free(SERVER *);
extern SERVER *server_find(char *, unsigned short);
extern void printServer(SERVER *); extern void printServer(SERVER *);
extern void printAllServers(); extern void printAllServers();
extern void dprintAllServers(DCB *); extern void dprintAllServers(DCB *);
@ -104,4 +105,5 @@ extern char *server_status(SERVER *);
extern void server_set_status(SERVER *, int); extern void server_set_status(SERVER *, int);
extern void server_clear_status(SERVER *, int); extern void server_clear_status(SERVER *, int);
extern void serverAddMonUser(SERVER *, char *, char *); extern void serverAddMonUser(SERVER *, char *, char *);
extern void server_update(SERVER *, char *, char *, char *);
#endif #endif

View File

@ -109,15 +109,21 @@ typedef struct service {
extern SERVICE *service_alloc(char *, char *); extern SERVICE *service_alloc(char *, char *);
extern int service_free(SERVICE *); extern int service_free(SERVICE *);
extern SERVICE *service_find(char *);
extern int serviceAddProtocol(SERVICE *, char *, unsigned short); extern int serviceAddProtocol(SERVICE *, char *, unsigned short);
extern int serviceHasProtocol(SERVICE *, char *, unsigned short);
extern void serviceAddBackend(SERVICE *, SERVER *); extern void serviceAddBackend(SERVICE *, SERVER *);
extern int serviceHasBackend(SERVICE *, SERVER *);
extern void serviceAddRouterOption(SERVICE *, char *); extern void serviceAddRouterOption(SERVICE *, char *);
extern void serviceClearRouterOptions(SERVICE *);
extern int serviceStart(SERVICE *); extern int serviceStart(SERVICE *);
extern int serviceStartAll(); extern int serviceStartAll();
extern void serviceStartProtocol(SERVICE *, char *, int);
extern int serviceStop(SERVICE *); extern int serviceStop(SERVICE *);
extern int serviceRestart(SERVICE *); extern int serviceRestart(SERVICE *);
extern int serviceSetUser(SERVICE *, char *, char *); extern int serviceSetUser(SERVICE *, char *, char *);
extern int serviceGetUser(SERVICE *, char **, char **); extern int serviceGetUser(SERVICE *, char **, char **);
extern void service_update(SERVICE *, char *, char *, char *);
extern void printService(SERVICE *); extern void printService(SERVICE *);
extern void printAllServices(); extern void printAllServices();
extern void dprintAllServices(DCB *); extern void dprintAllServices(DCB *);

View File

@ -55,6 +55,6 @@ depend:
cc -M $(CFLAGS) $(SRCS) > depend.mk cc -M $(CFLAGS) $(SRCS) > depend.mk
install: $(MODULES) install: $(MODULES)
install -D $< $(DEST)/gateway/modules install -D $(MODULES) $(DEST)/MaxScale/modules
include depend.mk include depend.mk

View File

@ -111,7 +111,7 @@ MYSQL_MONITOR *handle;
/** /**
* Stop a running monitor * Stop a running monitor
* *
* @param handle Handle on thr running monior * @param arg Handle on thr running monior
*/ */
static void static void
stopMonitor(void *arg) stopMonitor(void *arg)
@ -125,7 +125,7 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
* Register a server that must be added to the monitored servers for * Register a server that must be added to the monitored servers for
* a monitoring module. * a monitoring module.
* *
* @param handle A handle on the running monitor module * @param arg A handle on the running monitor module
* @param server The server to add * @param server The server to add
*/ */
static void static void
@ -155,7 +155,7 @@ MONITOR_SERVERS *ptr, *db;
/** /**
* Remove a server from those being monitored by a monitoring module * Remove a server from those being monitored by a monitoring module
* *
* @param handle A handle on the running monitor module * @param arg A handle on the running monitor module
* @param server The server to remove * @param server The server to remove
*/ */
static void static void

View File

@ -72,7 +72,7 @@ tags:
ctags $(SRCS) $(HDRS) ctags $(SRCS) $(HDRS)
install: $(MODULES) install: $(MODULES)
install -D $< $(DEST)/gateway/modules install -D $(MODULES) $(DEST)/MaxScale/modules
depend: depend:
rm -f depend.mk rm -f depend.mk

View File

@ -43,8 +43,7 @@ DEBUGCLIOBJ=$(DEBUGCLISRCS:.c=.o)
SRCS=$(TESTSRCS) $(READCONSRCS) $(DEBUGCLISRCS) SRCS=$(TESTSRCS) $(READCONSRCS) $(DEBUGCLISRCS)
OBJ=$(SRCS:.c=.o) OBJ=$(SRCS:.c=.o)
LIBS=$(UTILSPATH)/skygw_utils.o -lssl -llog_manager LIBS=$(UTILSPATH)/skygw_utils.o -lssl -llog_manager
MODULES=libtestroute.so libreadconnroute.so libdebugcli.so \ MODULES= libdebugcli.so libreadconnroute.so libtestroute.so
libreadwritesplit.so
all: $(MODULES) all: $(MODULES)
@ -78,6 +77,7 @@ depend:
(cd readwritesplit; make depend) (cd readwritesplit; make depend)
install: $(MODULES) install: $(MODULES)
install -D $< $(DEST)/gateway/modules install -D $(MODULES) $(DEST)/MaxScale/modules
(cd readwritesplit; make DEST=$(DEST) install)
include depend.mk include depend.mk

View File

@ -159,7 +159,7 @@ CLI_SESSION *client;
session->state = SESSION_STATE_READY; session->state = SESSION_STATE_READY;
dcb_printf(session->client, "Welcome the SkySQL Gateway Debug Interface (%s).\n", dcb_printf(session->client, "Welcome the SkySQL MaxScale Debug Interface (%s).\n",
version_str); version_str);
dcb_printf(session->client, "Type help for a list of available commands.\n\n"); dcb_printf(session->client, "Type help for a list of available commands.\n\n");
@ -226,7 +226,7 @@ CLI_SESSION *session = (CLI_SESSION *)router_session;
if (strrchr(session->cmdbuf, '\n')) if (strrchr(session->cmdbuf, '\n'))
{ {
if (execute_cmd(session)) if (execute_cmd(session))
dcb_printf(session->session->client, "Gateway> "); dcb_printf(session->session->client, "MaxScale> ");
else else
session->session->client->func.close(session->session->client); session->session->client->func.close(session->session->client);
} }

View File

@ -107,6 +107,8 @@ static void shutdown_service(DCB *dcb, SERVICE *service);
struct subcommand shutdownoptions[] = { struct subcommand shutdownoptions[] = {
{ "gateway", 0, shutdown_gateway, "Shutdown the gateway", { "gateway", 0, shutdown_gateway, "Shutdown the gateway",
{0, 0, 0} }, {0, 0, 0} },
{ "maxscale", 0, shutdown_gateway, "Shutdown the MaxScale gateway",
{0, 0, 0} },
{ "service", 1, shutdown_service, "Shutdown a service, e.g. shutdown service 0x4838320", { "service", 1, shutdown_service, "Shutdown a service, e.g. shutdown service 0x4838320",
{ARG_TYPE_ADDRESS, 0, 0} }, {ARG_TYPE_ADDRESS, 0, 0} },
{ NULL, 0, NULL, NULL, { NULL, 0, NULL, NULL,

View File

@ -58,6 +58,6 @@ depend:
cc -M $(CFLAGS) $(SRCS) > depend.mk cc -M $(CFLAGS) $(SRCS) > depend.mk
install: $(MODULES) install: $(MODULES)
install -D $< $(DEST)/gateway/modules install -D $(MODULES) $(DEST)/MaxScale/modules
include depend.mk include depend.mk

View File

@ -23,10 +23,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <mysql.h> #include <mysql.h>
#if defined(SS_DEBUG)
#include <skygw_utils.h> #include <skygw_utils.h>
#include <log_manager.h> #include <log_manager.h>
#endif
#include <query_classifier.h> #include <query_classifier.h>
#include <dcb.h> #include <dcb.h>
#include <spinlock.h> #include <spinlock.h>
@ -306,7 +304,7 @@ static void* newSession(
* by which a router may cleanup data structure etc. * by which a router may cleanup data structure etc.
* *
* @param instance The router instance data * @param instance The router instance data
* @param session The session being closed * @param router_session The session being closed
*/ */
static void closeSession( static void closeSession(
ROUTER* instance, ROUTER* instance,
@ -362,7 +360,7 @@ static void closeSession(
* contain the remainder, or part thereof of the query. * contain the remainder, or part thereof of the query.
* *
* @param instance The query router instance * @param instance The query router instance
* @param session The session associated with the client * @param router_session The session associated with the client
* @param queue Gateway buffer queue with the packets received * @param queue Gateway buffer queue with the packets received
* *
* @return The number of queries forwarded * @return The number of queries forwarded
@ -423,34 +421,34 @@ static int routeQuery(
break; break;
} }
#if defined(SS_DEBUG_) #if defined(SS_DEBUG_)
skygw_log_write(NULL, LOGFILE_TRACE, "String\t\"%s\"", querystr); skygw_log_write(NULL, LOGFILE_TRACE, "String\t\"%s\"", querystr);
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_TRACE, LOGFILE_TRACE,
"Packet type\t%s", "Packet type\t%s",
STRPACKETTYPE(packet_type)); STRPACKETTYPE(packet_type));
#endif #endif
switch (qtype) { switch (qtype) {
case QUERY_TYPE_WRITE: case QUERY_TYPE_WRITE:
#if defined(SS_DEBUG_) #if defined(SS_DEBUG_)
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_TRACE, LOGFILE_TRACE,
"Query type\t%s, routing to Master.", "Query type\t%s, routing to Master.",
STRQTYPE(qtype)); STRQTYPE(qtype));
#endif #endif
ret = session->masterconn->func.write(session->masterconn, queue); ret = session->masterconn->func.write(session->masterconn, queue);
atomic_add(&inst->stats.n_master, 1); atomic_add(&inst->stats.n_master, 1);
goto return_ret; goto return_ret;
break; break;
case QUERY_TYPE_READ: case QUERY_TYPE_READ:
#if defined(SS_DEBUG_) #if defined(SS_DEBUG_)
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_TRACE, LOGFILE_TRACE,
"Query type\t%s, routing to Slave.", "Query type\t%s, routing to Slave.",
STRQTYPE(qtype)); STRQTYPE(qtype));
#endif #endif
ret = session->slaveconn->func.write(session->slaveconn, queue); ret = session->slaveconn->func.write(session->slaveconn, queue);
atomic_add(&inst->stats.n_slave, 1); atomic_add(&inst->stats.n_slave, 1);
goto return_ret; goto return_ret;
@ -458,12 +456,12 @@ static int routeQuery(
case QUERY_TYPE_SESSION_WRITE: case QUERY_TYPE_SESSION_WRITE:
#if defined(SS_DEBUG_) #if defined(SS_DEBUG_)
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_TRACE, LOGFILE_TRACE,
"Query type\t%s, routing to All servers.", "Query type\t%s, routing to All servers.",
STRQTYPE(qtype)); STRQTYPE(qtype));
#endif #endif
/** /**
* TODO! Connection to all servers must be established, and * TODO! Connection to all servers must be established, and
* the command must be executed in them. * the command must be executed in them.
@ -484,12 +482,12 @@ static int routeQuery(
break; break;
default: default:
#if defined(SS_DEBUG_) #if defined(SS_DEBUG_)
skygw_log_write(NULL, skygw_log_write(NULL,
LOGFILE_TRACE, LOGFILE_TRACE,
"Query type\t%s, routing to Master by default.", "Query type\t%s, routing to Master by default.",
STRQTYPE(qtype)); STRQTYPE(qtype));
#endif #endif
/** Is this really ok? */ /** Is this really ok? */
ret = session->masterconn->func.write(session->masterconn, queue); ret = session->masterconn->func.write(session->masterconn, queue);
atomic_add(&inst->stats.n_master, 1); atomic_add(&inst->stats.n_master, 1);