diff --git a/core/monitor.c b/core/monitor.c index 2216242d3..36b9c294e 100644 --- a/core/monitor.c +++ b/core/monitor.c @@ -66,7 +66,7 @@ MONITOR *mon; free(mon); return NULL; } - mon->handle = (*mon->module->startMonitor)(); + mon->handle = (*mon->module->startMonitor)(NULL); spinlock_acquire(&monLock); mon->next = allMonitors; @@ -104,6 +104,29 @@ MONITOR *ptr; free(mon); } + +/** + * Start an individual monitor that has previoulsy been stopped. + * + * @param monitor The Monitor that should be started + */ +void +monitorStart(MONITOR *monitor) +{ + monitor->handle = (*monitor->module->startMonitor)(monitor->handle); +} + +/** + * Stop a given monitor + * + * @param monitor The monitor to stop + */ +void +monitorStop(MONITOR *monitor) +{ + monitor->module->stopMonitor(monitor->handle); +} + /** * Shutdown all running monitors */ @@ -116,7 +139,7 @@ MONITOR *ptr; ptr = allMonitors; while (ptr) { - ptr->module->stopMonitor(ptr->handle); + monitorStop(ptr); ptr = ptr->next; } spinlock_release(&monLock); @@ -148,3 +171,26 @@ monitorAddUser(MONITOR *mon, char *user, char *passwd) { mon->module->defaultUser(mon->handle, user, passwd); } + +/** + * Show all monitors + * + * @param dcb DCB for printing output + */ +void +monitorShowAll(DCB *dcb) +{ +MONITOR *ptr; + + spinlock_acquire(&monLock); + ptr = allMonitors; + while (ptr) + { + dcb_printf(dcb, "Monitor: %p\n", ptr); + dcb_printf(dcb, "\tName: %s\n", ptr->name); + if (ptr->module->diagnostics) + ptr->module->diagnostics(dcb, ptr->handle); + ptr = ptr->next; + } + spinlock_release(&monLock); +} diff --git a/include/monitor.h b/include/monitor.h index 3b95bd1b8..6aa0f2430 100644 --- a/include/monitor.h +++ b/include/monitor.h @@ -18,6 +18,7 @@ * Copyright SkySQL Ab 2013 */ #include +#include /** * @file monitor.h The interface to the monitor module @@ -27,6 +28,7 @@ * * Date Who Description * 07/07/13 Mark Riddoch Initial implementation + * 25/07/13 Mark Riddoch Addition of diagnotics * * @endverbatim */ @@ -57,11 +59,12 @@ * monitored. */ typedef struct { - void *(*startMonitor)(); + void *(*startMonitor)(void *); void (*stopMonitor)(void *); void (*registerServer)(void *, SERVER *); void (*unregisterServer)(void *, SERVER *); void (*defaultUser)(void *, char *, char *); + void (*diagnostics)(DCB *, void *); } MONITOR_OBJECT; /** @@ -78,5 +81,8 @@ extern MONITOR *monitor_alloc(char *, char *); extern void monitor_free(MONITOR *); extern void monitorAddServer(MONITOR *, SERVER *); extern void monitorAddUser(MONITOR *, char *, char *); +extern void monitorStop(MONITOR *); +extern void monitorStart(MONITOR *); extern void monitorStopAll(); +extern void monitorShowAll(DCB *); #endif diff --git a/modules/monitor/galera_mon.c b/modules/monitor/galera_mon.c index daec03119..22b84d540 100644 --- a/modules/monitor/galera_mon.c +++ b/modules/monitor/galera_mon.c @@ -39,18 +39,20 @@ #include #include #include +#include static void monitorMain(void *); static char *version_str = "V1.0.0"; -static void *startMonitor(); +static void *startMonitor(void *); static void stopMonitor(void *); static void registerServer(void *, SERVER *); static void unregisterServer(void *, SERVER *); static void defaultUsers(void *, char *, char *); +static void daignostics(DCB *, void *); -static MONITOR_OBJECT MyObject = { startMonitor, stopMonitor, registerServer, unregisterServer, defaultUser }; +static MONITOR_OBJECT MyObject = { startMonitor, stopMonitor, registerServer, unregisterServer, defaultUser, daignostics }; /** * Implementation of the mandatory version entry point @@ -96,17 +98,25 @@ GetModuleObject() * @return A handle to use when interacting with the monitor */ static void * -startMonitor() +startMonitor(void *arg) { MYSQL_MONITOR *handle; - if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) - return NULL; - handle->databases = NULL; - handle->shutdown = 0; - handle->defaultUser = NULL; - handle->deaultPasswd = NULL; - spinlock_init(&handle->lock); + if (arg != NULL) + { + handle = (MYSQL_MONITOR *)arg; + handle->shutdown = 0; + } + else + { + if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) + return NULL; + handle->databases = NULL; + handle->shutdown = 0; + handle->defaultUser = NULL; + handle->deaultPasswd = NULL; + spinlock_init(&handle->lock); + } thread_start(monitorMain, handle); return handle; } @@ -194,6 +204,43 @@ MONITOR_SERVERS *ptr, *lptr; spinlock_release(&handle->lock); } +/** + * Diagnostic interface + * + * @param dcb DCB to send output + * @param arg The monitor handle + */ +static void +diagnostics(DCB *dcbm void *handle) +{ +MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; +MONITOR_SERVERS *db; +char *sep; + + switch (handle->status) + { + case MONITOR_RUNNING: + dcb_printf(dcb, "\tMonitor running\n"); + break; + case MONITOR_STOPPING: + dcb_printf(dcb, "\tMonitor stopping\n"); + break; + case MONITOR_STOPPED: + dcb_printf(dcb, "\tMonitor stopped\n"); + break; + } + dcb_printf(dcb, "\tMonitored servers: "); + db = handle->databases; + sep = ""; + while (db) + { + dcb_printf(dcb, "%s%s:%d", sep, db->server->name, db->server->port); + sep = ", "; + db = db->next; + } + dcb_printf(dcb, "\n"); +} + /** * Set the default username and password to use to monitor if the server does not * override this. @@ -292,11 +339,14 @@ MONITOR_SERVERS *ptr; "module. Exiting.\n"); return; } + handle->status = MONITOR_RUNNING; while (1) { if (handle->shutdown) { + handle->status = MONITOR_STOPPING; mysql_thread_end(); + handle->status = MONITOR_STOPPED; return; } ptr = handle->databases; diff --git a/modules/monitor/mysql_mon.c b/modules/monitor/mysql_mon.c index 4fa2dff4e..c3b1a80a8 100644 --- a/modules/monitor/mysql_mon.c +++ b/modules/monitor/mysql_mon.c @@ -26,6 +26,8 @@ * 08/07/13 Mark Riddoch Initial implementation * 11/07/13 Mark Riddoch Addition of code to check replication * status + * 25/07/13 Mark Riddoch Addition of decrypt for passwords and + * diagnostic interface * * @endverbatim */ @@ -41,18 +43,20 @@ #include #include #include +#include static void monitorMain(void *); static char *version_str = "V1.0.0"; -static void *startMonitor(); +static void *startMonitor(void *); static void stopMonitor(void *); static void registerServer(void *, SERVER *); static void unregisterServer(void *, SERVER *); static void defaultUser(void *, char *, char *); +static void diagnostics(DCB *, void *); -static MONITOR_OBJECT MyObject = { startMonitor, stopMonitor, registerServer, unregisterServer, defaultUser }; +static MONITOR_OBJECT MyObject = { startMonitor, stopMonitor, registerServer, unregisterServer, defaultUser, diagnostics }; /** * Implementation of the mandatory version entry point @@ -95,20 +99,29 @@ GetModuleObject() * * This function creates a thread to execute the actual monitoring. * + * @param arg The current handle - NULL if first start * @return A handle to use when interacting with the monitor */ static void * -startMonitor() +startMonitor(void *arg) { MYSQL_MONITOR *handle; - if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) - return NULL; - handle->databases = NULL; - handle->shutdown = 0; - handle->defaultUser = NULL; - handle->defaultPasswd = NULL; - spinlock_init(&handle->lock); + if (arg) + { + handle = arg; /* Must be a restart */ + handle->shutdown = 0; + } + else + { + if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) + return NULL; + handle->databases = NULL; + handle->shutdown = 0; + handle->defaultUser = NULL; + handle->defaultPasswd = NULL; + spinlock_init(&handle->lock); + } thread_start(monitorMain, handle); return handle; } @@ -217,6 +230,42 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; handle->defaultPasswd = strdup(passwd); } +/** + * Daignostic interface + * + * @param dcb DCB to print diagnostics + * @param arg The monitor handle + */ +static void diagnostics(DCB *dcb, void *arg) +{ +MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; +MONITOR_SERVERS *db; +char *sep; + + switch (handle->status) + { + case MONITOR_RUNNING: + dcb_printf(dcb, "\tMonitor running\n"); + break; + case MONITOR_STOPPING: + dcb_printf(dcb, "\tMonitor stopping\n"); + break; + case MONITOR_STOPPED: + dcb_printf(dcb, "\tMonitor stopped\n"); + break; + } + dcb_printf(dcb, "\tMonitored servers: "); + db = handle->databases; + sep = ""; + while (db) + { + dcb_printf(dcb, "%s%s:%d", sep, db->server->name, db->server->port); + sep = ", "; + db = db->next; + } + dcb_printf(dcb, "\n"); +} + /** * Monitor an individual server * @@ -328,11 +377,14 @@ MONITOR_SERVERS *ptr; "module. Exiting.\n"); return; } + handle->status = MONITOR_RUNNING; while (1) { if (handle->shutdown) { + handle->status = MONITOR_STOPPING; mysql_thread_end(); + handle->status = MONITOR_STOPPED; return; } ptr = handle->databases; diff --git a/modules/monitor/mysqlmon.h b/modules/monitor/mysqlmon.h index 28678ef71..141d205c7 100644 --- a/modules/monitor/mysqlmon.h +++ b/modules/monitor/mysqlmon.h @@ -50,8 +50,14 @@ typedef struct monitor_servers { typedef struct { SPINLOCK lock; /**< The monitor spinlock */ int shutdown; /**< Flag to shutdown the monitor thread */ + int status; /**< Monitor status */ char *defaultUser; /**< Default username for monitoring */ char *defaultPasswd; /**< Default password for monitoring */ MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */ } MYSQL_MONITOR; + +#define MONITOR_RUNNING 1 +#define MONITOR_STOPPING 2 +#define MONITOR_STOPPED 3 + #endif diff --git a/modules/routing/debugcmd.c b/modules/routing/debugcmd.c index 94708d19c..f1ebba0bb 100644 --- a/modules/routing/debugcmd.c +++ b/modules/routing/debugcmd.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #define MAXARGS 5 @@ -80,26 +81,28 @@ static void telnetdShowUsers(DCB *); * The subcommands of the show command */ struct subcommand showoptions[] = { - { "sessions", 0, dprintAllSessions, "Show all active sessions in MaxScale", - {0, 0, 0} }, - { "session", 1, dprintSession, "Show a single session in MaxScale, e.g. show session 0x284830", - {ARG_TYPE_ADDRESS, 0, 0} }, - { "services", 0, dprintAllServices, "Show all configured services in MaxScale", - {0, 0, 0} }, - { "servers", 0, dprintAllServers, "Show all configured servers", - {0, 0, 0} }, - { "server", 1, dprintServer, "Show details for a server, e.g. show server 0x485390", - {ARG_TYPE_ADDRESS, 0, 0} }, - { "modules", 0, dprintAllModules, "Show all currently loaded modules", - {0, 0, 0} }, { "dcbs", 0, dprintAllDCBs, "Show all descriptor control blocks (network connections)", {0, 0, 0} }, { "dcb", 1, dprintDCB, "Show a single descriptor control block e.g. show dcb 0x493340", {ARG_TYPE_ADDRESS, 0, 0} }, - { "epoll", 0, dprintPollStats, "Show the poll statistics", - {0, 0, 0} }, { "dbusers", 1, dcb_usersPrint, "Show statistics and user names for a service's user table", {ARG_TYPE_ADDRESS, 0, 0} }, + { "epoll", 0, dprintPollStats, "Show the poll statistics", + {0, 0, 0} }, + { "modules", 0, dprintAllModules, "Show all currently loaded modules", + {0, 0, 0} }, + { "monitors", 0, monitorShowAll, "Show the monitors that are configured", + {0, 0, 0} }, + { "server", 1, dprintServer, "Show details for a server, e.g. show server 0x485390", + {ARG_TYPE_ADDRESS, 0, 0} }, + { "servers", 0, dprintAllServers, "Show all configured servers", + {0, 0, 0} }, + { "services", 0, dprintAllServices, "Show all configured services in MaxScale", + {0, 0, 0} }, + { "session", 1, dprintSession, "Show a single session in MaxScale, e.g. show session 0x284830", + {ARG_TYPE_ADDRESS, 0, 0} }, + { "sessions", 0, dprintAllSessions, "Show all active sessions in MaxScale", + {0, 0, 0} }, { "users", 0, telnetdShowUsers, "Show statistics and user names for the debug interface", {ARG_TYPE_ADDRESS, 0, 0} }, { NULL, 0, NULL, NULL, @@ -108,6 +111,7 @@ struct subcommand showoptions[] = { extern void shutdown_gateway(); static void shutdown_service(DCB *dcb, SERVICE *service); +static void shutdown_monitor(DCB *dcb, MONITOR *monitor); /** * The subcommands of the shutdown command @@ -117,6 +121,8 @@ struct subcommand shutdownoptions[] = { {0, 0, 0} }, { "maxscale", 0, shutdown_gateway, "Shutdown the MaxScale gateway", {0, 0, 0} }, + { "monitor", 1, shutdown_monitor, "Shutdown a monitor, e.g. shutdown monitor 0x48381e0", + {ARG_TYPE_ADDRESS, 0, 0} }, { "service", 1, shutdown_service, "Shutdown a service, e.g. shutdown service 0x4838320", {ARG_TYPE_ADDRESS, 0, 0} }, { NULL, 0, NULL, NULL, @@ -124,10 +130,13 @@ struct subcommand shutdownoptions[] = { }; static void restart_service(DCB *dcb, SERVICE *service); +static void restart_monitor(DCB *dcb, MONITOR *monitor); /** * The subcommands of the restart command */ struct subcommand restartoptions[] = { + { "monitor", 1, restart_monitor, "Restart a monitor, e.g. restart monitor 0x48181e0", + {ARG_TYPE_ADDRESS, 0, 0} }, { "service", 1, restart_service, "Restart a service, e.g. restart service 0x4838320", {ARG_TYPE_ADDRESS, 0, 0} }, { NULL, 0, NULL, NULL, @@ -163,10 +172,10 @@ static void reload_config(DCB *dcb); * The subcommands of the reload command */ struct subcommand reloadoptions[] = { - { "users", 1, reload_users, "Reload the user data for a service. E.g. reload users 0x849420", - {ARG_TYPE_ADDRESS, 0, 0} }, { "config", 0, reload_config, "Reload the configuration data for MaxScale.", {ARG_TYPE_ADDRESS, 0, 0} }, + { "users", 1, reload_users, "Reload the user data for a service. E.g. reload users 0x849420", + {ARG_TYPE_ADDRESS, 0, 0} }, { NULL, 0, NULL, NULL, {0, 0, 0} } }; @@ -189,13 +198,13 @@ static struct { char *cmd; struct subcommand *options; } cmds[] = { - { "show", showoptions }, - { "shutdown", shutdownoptions }, + { "add", addoptions }, + { "clear", clearoptions }, { "restart", restartoptions }, { "set", setoptions }, - { "clear", clearoptions }, + { "show", showoptions }, + { "shutdown", shutdownoptions }, { "reload", reloadoptions }, - { "add", addoptions }, { NULL, NULL } }; @@ -537,3 +546,27 @@ telnetdShowUsers(DCB *dcb) dcb_printf(dcb, "Administration interface users:\n"); dcb_PrintAdminUsers(dcb); } + +/** + * Command to shutdown a running monitor + * + * @param dcb The DCB to use to print messages + * @param monitor The monitor to shutdown + */ +static void +shutdown_monitor(DCB *dcb, MONITOR *monitor) +{ + monitorStop(monitor); +} + +/** + * Command to restart a stopped monitor + * + * @param dcb The DCB to use to print messages + * @param monitor The monitor to restart + */ +static void +restart_monitor(DCB *dcb, MONITOR *monitor) +{ + monitorStart(monitor); +}