Addition for shutdown mechanism for the gateway
Addition of stop and restart service Fix for telnetd in Makefile Fix for printing the server names in services
This commit is contained in:
@ -336,7 +336,7 @@ service.o: service.c /usr/include/stdio.h /usr/include/features.h \
|
|||||||
/usr/include/bits/setjmp.h ../include/dcb.h ../include/buffer.h \
|
/usr/include/bits/setjmp.h ../include/dcb.h ../include/buffer.h \
|
||||||
../include/server.h ../include/router.h ../include/modules.h \
|
../include/server.h ../include/router.h ../include/modules.h \
|
||||||
../include/users.h ../include/hashtable.h ../include/atomic.h \
|
../include/users.h ../include/hashtable.h ../include/atomic.h \
|
||||||
../include/dbusers.h
|
../include/dbusers.h ../include/poll.h
|
||||||
server.o: server.c /usr/include/stdio.h /usr/include/features.h \
|
server.o: server.c /usr/include/stdio.h /usr/include/features.h \
|
||||||
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
|
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
|
||||||
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
|
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
|
||||||
|
|||||||
@ -50,9 +50,10 @@ static void sighup_handler (int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sigterm_handler (int i) {
|
static void sigterm_handler (int i) {
|
||||||
|
extern void shutdown_gateway();
|
||||||
|
|
||||||
fprintf(stderr, "Signal SIGTERM %i received ...Exiting!\n", i);
|
fprintf(stderr, "Signal SIGTERM %i received ...Exiting!\n", i);
|
||||||
|
shutdown_gateway();
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wrapper for sigaction */
|
/* wrapper for sigaction */
|
||||||
@ -170,7 +171,8 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int daemon_mode = 1;
|
int daemon_mode = 1;
|
||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
int n;
|
int n, n_threads;
|
||||||
|
void **threads;
|
||||||
char buf[1024], *home, *cnf_file = NULL;
|
char buf[1024], *home, *cnf_file = NULL;
|
||||||
|
|
||||||
if ((home = getenv("GATEWAY_HOME")) != NULL)
|
if ((home = getenv("GATEWAY_HOME")) != NULL)
|
||||||
@ -250,8 +252,24 @@ char buf[1024], *home, *cnf_file = NULL;
|
|||||||
* Start the polling threads, note this is one less than is configured as the
|
* Start the polling threads, note this is one less than is configured as the
|
||||||
* main thread will also poll.
|
* main thread will also poll.
|
||||||
*/
|
*/
|
||||||
for (n = 0; n < config_threadcount() - 1; n++)
|
n_threads = config_threadcount();
|
||||||
thread_start(poll_waitevents);
|
threads = (void **)calloc(n_threads, sizeof(void *));
|
||||||
|
for (n = 0; n < n_threads - 1; n++)
|
||||||
|
threads[n] = thread_start(poll_waitevents);
|
||||||
poll_waitevents();
|
poll_waitevents();
|
||||||
|
for (n = 0; n < n_threads - 1; n++)
|
||||||
|
thread_wait(threads[n]);
|
||||||
|
|
||||||
|
printf("Gateway shutdown\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
} // End of main
|
} // End of main
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the gateway
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
shutdown_gateway()
|
||||||
|
{
|
||||||
|
poll_shutdown();
|
||||||
|
}
|
||||||
|
|||||||
26
core/poll.c
26
core/poll.c
@ -37,6 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int epoll_fd = -1; /**< The epoll file descriptor */
|
static int epoll_fd = -1; /**< The epoll file descriptor */
|
||||||
|
static int shutdown = 0; /**< Flag the shutdown of the poll subsystem */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The polling statistics
|
* The polling statistics
|
||||||
@ -117,12 +118,18 @@ int i, nfds;
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
atomic_add(&pollStats.n_polls, 1);
|
if ((nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, 0)) == -1)
|
||||||
if ((nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1)) == -1)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else
|
else if (nfds == 0)
|
||||||
{
|
{
|
||||||
|
if ((nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, EPOLL_TIMEOUT)) == -1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nfds > 0)
|
||||||
|
{
|
||||||
|
atomic_add(&pollStats.n_polls, 1);
|
||||||
for (i = 0; i < nfds; i++)
|
for (i = 0; i < nfds; i++)
|
||||||
{
|
{
|
||||||
DCB *dcb = (DCB *)events[i].data.ptr;
|
DCB *dcb = (DCB *)events[i].data.ptr;
|
||||||
@ -158,9 +165,22 @@ int i, nfds;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (shutdown)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown the polling loop
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
poll_shutdown()
|
||||||
|
{
|
||||||
|
shutdown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug routine to print the polling statistics
|
* Debug routine to print the polling statistics
|
||||||
*
|
*
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <users.h>
|
#include <users.h>
|
||||||
#include <dbusers.h>
|
#include <dbusers.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
static SPINLOCK service_spin = SPINLOCK_INIT;
|
static SPINLOCK service_spin = SPINLOCK_INIT;
|
||||||
static SERVICE *allServices = NULL;
|
static SERVICE *allServices = NULL;
|
||||||
@ -160,6 +161,61 @@ int n = 0;
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop a service
|
||||||
|
*
|
||||||
|
* This function stops the listener for the service
|
||||||
|
*
|
||||||
|
* @param service The Service that should be stopped
|
||||||
|
* @return Returns the number of listeners restarted
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
serviceStop(SERVICE *service)
|
||||||
|
{
|
||||||
|
SERV_PROTOCOL *port;
|
||||||
|
int listeners = 0;
|
||||||
|
|
||||||
|
port = service->ports;
|
||||||
|
while (port)
|
||||||
|
{
|
||||||
|
poll_remove_dcb(port->listener);
|
||||||
|
port->listener->session->state = SESSION_STATE_LISTENER_STOPPED;
|
||||||
|
listeners++;
|
||||||
|
|
||||||
|
port = port->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restart a service
|
||||||
|
*
|
||||||
|
* This function stops the listener for the service
|
||||||
|
*
|
||||||
|
* @param service The Service that should be restarted
|
||||||
|
* @return Returns the number of listeners restarted
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
serviceRestart(SERVICE *service)
|
||||||
|
{
|
||||||
|
SERV_PROTOCOL *port;
|
||||||
|
int listeners = 0;
|
||||||
|
|
||||||
|
port = service->ports;
|
||||||
|
while (port)
|
||||||
|
{
|
||||||
|
poll_add_dcb(port->listener);
|
||||||
|
port->listener->session->state = SESSION_STATE_LISTENER;
|
||||||
|
listeners++;
|
||||||
|
|
||||||
|
port = port->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocate the specified service
|
* Deallocate the specified service
|
||||||
*
|
*
|
||||||
@ -306,7 +362,7 @@ SERVER *ptr = service->databases;
|
|||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
printf("\t\t%s:%d Protocol: %s\n", ptr->name, ptr->port, ptr->protocol);
|
printf("\t\t%s:%d Protocol: %s\n", ptr->name, ptr->port, ptr->protocol);
|
||||||
ptr = ptr->next;
|
ptr = ptr->nextdb;
|
||||||
}
|
}
|
||||||
printf("\tTotal connections: %d\n", service->stats.n_sessions);
|
printf("\tTotal connections: %d\n", service->stats.n_sessions);
|
||||||
printf("\tCurrently connected: %d\n", service->stats.n_current);
|
printf("\tCurrently connected: %d\n", service->stats.n_current);
|
||||||
@ -360,7 +416,7 @@ SERVICE *ptr;
|
|||||||
{
|
{
|
||||||
dcb_printf(dcb, "\t\t%s:%d Protocol: %s\n", server->name, server->port,
|
dcb_printf(dcb, "\t\t%s:%d Protocol: %s\n", server->name, server->port,
|
||||||
server->protocol);
|
server->protocol);
|
||||||
server = server->next;
|
server = server->nextdb;
|
||||||
}
|
}
|
||||||
dcb_printf(dcb, "\tTotal connections: %d\n", ptr->stats.n_sessions);
|
dcb_printf(dcb, "\tTotal connections: %d\n", ptr->stats.n_sessions);
|
||||||
dcb_printf(dcb, "\tCurrently connected: %d\n", ptr->stats.n_current);
|
dcb_printf(dcb, "\tCurrently connected: %d\n", ptr->stats.n_current);
|
||||||
|
|||||||
@ -130,6 +130,7 @@ void
|
|||||||
printSession(SESSION *session)
|
printSession(SESSION *session)
|
||||||
{
|
{
|
||||||
printf("Session %p\n", session);
|
printf("Session %p\n", session);
|
||||||
|
printf("\tState: %s\n", session_state(session->state));
|
||||||
printf("\tService: %s (%p)\n", session->service->name, session->service);
|
printf("\tService: %s (%p)\n", session->service->name, session->service);
|
||||||
printf("\tClient DCB: %p\n", session->client);
|
printf("\tClient DCB: %p\n", session->client);
|
||||||
printf("\tConnected: %s", asctime(localtime(&session->stats.connect)));
|
printf("\tConnected: %s", asctime(localtime(&session->stats.connect)));
|
||||||
@ -174,6 +175,7 @@ SESSION *ptr;
|
|||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
dcb_printf(dcb, "Session %p\n", ptr);
|
dcb_printf(dcb, "Session %p\n", ptr);
|
||||||
|
dcb_printf(dcb, "\tState: %s\n", session_state(ptr->state));
|
||||||
dcb_printf(dcb, "\tService: %s (%p)\n", ptr->service->name, ptr->service);
|
dcb_printf(dcb, "\tService: %s (%p)\n", ptr->service->name, ptr->service);
|
||||||
dcb_printf(dcb, "\tClient DCB: %p\n", ptr->client);
|
dcb_printf(dcb, "\tClient DCB: %p\n", ptr->client);
|
||||||
if (ptr->client && ptr->client->remote)
|
if (ptr->client && ptr->client->remote)
|
||||||
@ -222,6 +224,8 @@ session_state(int state)
|
|||||||
return "Session Ready";
|
return "Session Ready";
|
||||||
case SESSION_STATE_LISTENER:
|
case SESSION_STATE_LISTENER:
|
||||||
return "Listener Session";
|
return "Listener Session";
|
||||||
|
case SESSION_STATE_LISTENER_STOPPED:
|
||||||
|
return "Stopped Listener Session";
|
||||||
default:
|
default:
|
||||||
return "Invalid State";
|
return "Invalid State";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,8 +49,9 @@ pthread_t thd;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for all running threads to complete.
|
* Wait for a running threads to complete.
|
||||||
*
|
*
|
||||||
|
* @param thd The thread handle
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
thread_wait(void *thd)
|
thread_wait(void *thd)
|
||||||
|
|||||||
@ -31,10 +31,12 @@
|
|||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
#define MAX_EVENTS 1000
|
#define MAX_EVENTS 1000
|
||||||
|
#define EPOLL_TIMEOUT 1000 /**< The epoll timeout we use (milliseconds) */
|
||||||
|
|
||||||
extern void poll_init();
|
extern void poll_init();
|
||||||
extern int poll_add_dcb(DCB *);
|
extern int poll_add_dcb(DCB *);
|
||||||
extern int poll_remove_dcb(DCB *);
|
extern int poll_remove_dcb(DCB *);
|
||||||
extern void poll_waitevents();
|
extern void poll_waitevents();
|
||||||
|
extern void poll_shutdown();
|
||||||
extern void dprintPollStats(DCB *);
|
extern void dprintPollStats(DCB *);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -112,6 +112,8 @@ extern int serviceAddProtocol(SERVICE *, char *, unsigned short);
|
|||||||
extern void serviceAddBackend(SERVICE *, SERVER *);
|
extern void serviceAddBackend(SERVICE *, SERVER *);
|
||||||
extern int serviceStart(SERVICE *);
|
extern int serviceStart(SERVICE *);
|
||||||
extern int serviceStartAll();
|
extern int serviceStartAll();
|
||||||
|
extern int serviceStop(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 printService(SERVICE *);
|
extern void printService(SERVICE *);
|
||||||
|
|||||||
@ -60,9 +60,10 @@ typedef struct session {
|
|||||||
struct session *next; /**< Linked list of all sessions */
|
struct session *next; /**< Linked list of all sessions */
|
||||||
} SESSION;
|
} SESSION;
|
||||||
|
|
||||||
#define SESSION_STATE_ALLOC 0
|
#define SESSION_STATE_ALLOC 0 /**< The session has been allocated */
|
||||||
#define SESSION_STATE_READY 1
|
#define SESSION_STATE_READY 1 /**< The session is ready to route queries */
|
||||||
#define SESSION_STATE_LISTENER 2
|
#define SESSION_STATE_LISTENER 2 /**< The session is a running listener */
|
||||||
|
#define SESSION_STATE_LISTENER_STOPPED 3 /**< The session listener is stopped */
|
||||||
|
|
||||||
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client, type)
|
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client, type)
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ MYSQLBACKENDSRCS=mysql_backend.c mysql_common.c
|
|||||||
MYSQLBACKENDOBJ=$(MYSQLBACKENDSRCS:.c=.o)
|
MYSQLBACKENDOBJ=$(MYSQLBACKENDSRCS:.c=.o)
|
||||||
TELNETDSRCS=telnetd.c
|
TELNETDSRCS=telnetd.c
|
||||||
TELNETDOBJ=$(TELNETDSRCS:.c=.o)
|
TELNETDOBJ=$(TELNETDSRCS:.c=.o)
|
||||||
SRCS=$(MYSQLCLIENTSRCS) $(MYSQLBACKENDSRCS)
|
SRCS=$(MYSQLCLIENTSRCS) $(MYSQLBACKENDSRCS) $(TELNETDSRCS)
|
||||||
OBJ=$(SRCS:.c=.o)
|
OBJ=$(SRCS:.c=.o)
|
||||||
LIBS=
|
LIBS=
|
||||||
MODULES=libMySQLClient.so libMySQLBackend.so libtelnetd.so
|
MODULES=libMySQLClient.so libMySQLBackend.so libtelnetd.so
|
||||||
|
|||||||
@ -80,6 +80,27 @@ struct subcommand showoptions[] = {
|
|||||||
{ NULL, 0, NULL, NULL }
|
{ NULL, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void shutdown_gateway();
|
||||||
|
static void shutdown_service(DCB *dcb, SERVICE *service);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subcommands of the shutdown command
|
||||||
|
*/
|
||||||
|
struct subcommand shutdownoptions[] = {
|
||||||
|
{ "gateway", 0, shutdown_gateway, "Shutdown the gateway" },
|
||||||
|
{ "service", 1, shutdown_service, "Shutdown a service, e.g. shutdown service 0x4838320" },
|
||||||
|
{ NULL, 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void restart_service(DCB *dcb, SERVICE *service);
|
||||||
|
/**
|
||||||
|
* The subcommands of the restart command
|
||||||
|
*/
|
||||||
|
struct subcommand restartoptions[] = {
|
||||||
|
{ "service", 1, restart_service, "Restart a service, e.g. restart service 0x4838320" },
|
||||||
|
{ NULL, 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The debug command table
|
* The debug command table
|
||||||
*/
|
*/
|
||||||
@ -88,6 +109,8 @@ static struct {
|
|||||||
struct subcommand *options;
|
struct subcommand *options;
|
||||||
} cmds[] = {
|
} cmds[] = {
|
||||||
{ "show", showoptions },
|
{ "show", showoptions },
|
||||||
|
{ "shutdown", shutdownoptions },
|
||||||
|
{ "restart", restartoptions },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -230,3 +253,27 @@ char *saveptr, *delim = " \t\r\n";
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug command to stop a service
|
||||||
|
*
|
||||||
|
* @param dcb The DCB to print any output to
|
||||||
|
* @param service The service to shutdown
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
shutdown_service(DCB *dcb, SERVICE *service)
|
||||||
|
{
|
||||||
|
serviceStop(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug command to restart a stopped service
|
||||||
|
*
|
||||||
|
* @param dcb The DCB to print any output to
|
||||||
|
* @param service The service to restart
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
restart_service(DCB *dcb, SERVICE *service)
|
||||||
|
{
|
||||||
|
serviceRestart(service);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user