diff --git a/include/maxscale/service.h b/include/maxscale/service.h index 9beb1b717..fb0d29c78 100644 --- a/include/maxscale/service.h +++ b/include/maxscale/service.h @@ -225,6 +225,15 @@ bool serviceLaunchListener(SERVICE *service, SERV_LISTENER *port); */ bool serviceStopListener(SERVICE *service, const char *name); +/** + * @brief Restart a stopped listener + * + * @param service Service where the listener is linked + * @param name Name of the listener + * @return True if listener was restarted + */ +bool serviceStartListener(SERVICE *service, const char *name); + /** * Utility functions */ diff --git a/server/core/service.c b/server/core/service.c index f3eaca089..381f95d79 100644 --- a/server/core/service.c +++ b/server/core/service.c @@ -520,6 +520,31 @@ bool serviceStopListener(SERVICE *service, const char *name) return rval; } +bool serviceStartListener(SERVICE *service, const char *name) +{ + bool rval = false; + + spinlock_acquire(&service->spin); + + for (SERV_LISTENER *port = service->ports; port; port = port->next) + { + if (strcmp(port->name, name) == 0) + { + if (port->listener && port->listener->session->state == SESSION_STATE_LISTENER_STOPPED && + poll_add_dcb(port->listener) == 0) + { + port->listener->session->state = SESSION_STATE_LISTENER; + rval = true; + } + break; + } + } + + spinlock_release(&service->spin); + + return rval; +} + int service_launch_all() { SERVICE *ptr; @@ -1422,18 +1447,20 @@ dListListeners(DCB *dcb) if (service) { dcb_printf(dcb, "Listeners.\n"); - dcb_printf(dcb, "---------------------+--------------------+-----------------+-------+--------\n"); - dcb_printf(dcb, "%-20s | %-18s | %-15s | Port | State\n", - "Service Name", "Protocol Module", "Address"); - dcb_printf(dcb, "---------------------+--------------------+-----------------+-------+--------\n"); + dcb_printf(dcb, "---------------------+---------------------+" + "--------------------+-----------------+-------+--------\n"); + dcb_printf(dcb, "%-20s | %-19s | %-18s | %-15s | Port | State\n", + "Name", "Service Name", "Protocol Module", "Address"); + dcb_printf(dcb, "---------------------+---------------------+" + "--------------------+-----------------+-------+--------\n"); } while (service) { lptr = service->ports; while (lptr) { - dcb_printf(dcb, "%-20s | %-18s | %-15s | %5d | %s\n", - service->name, lptr->protocol, + dcb_printf(dcb, "%-20s | %-19s | %-18s | %-15s | %5d | %s\n", + lptr->name, service->name, lptr->protocol, (lptr && lptr->address) ? lptr->address : "*", lptr->port, (!lptr->listener || @@ -1447,7 +1474,8 @@ dListListeners(DCB *dcb) } if (allServices) { - dcb_printf(dcb, "---------------------+--------------------+-----------------+-------+--------\n\n"); + dcb_printf(dcb, "---------------------+---------------------+" + "--------------------+-----------------+-------+--------\n\n"); } spinlock_release(&service_spin); } diff --git a/server/modules/routing/debugcli/debugcmd.c b/server/modules/routing/debugcli/debugcmd.c index fb584b268..9505346e3 100644 --- a/server/modules/routing/debugcli/debugcmd.c +++ b/server/modules/routing/debugcli/debugcmd.c @@ -423,6 +423,19 @@ static void shutdown_server() static void shutdown_service(DCB *dcb, SERVICE *service); static void shutdown_monitor(DCB *dcb, MONITOR *monitor); +static void +shutdown_listener(DCB *dcb, SERVICE *service, const char *name) +{ + if (serviceStopListener(service, name)) + { + dcb_printf(dcb, "Stopped listener '%s'\n", name); + } + else + { + dcb_printf(dcb, "Failed to stop listener '%s'\n", name); + } +} + /** * The subcommands of the shutdown command */ @@ -452,6 +465,14 @@ struct subcommand shutdownoptions[] = "E.g. shutdown service \"Sales Database\"", {ARG_TYPE_SERVICE, 0, 0} }, + { + "listener", + 2, 2, + shutdown_listener, + "Stop a listener", + "E.g. shutdown listener \"RW Service\" \"RW Listener\"", + {ARG_TYPE_SERVICE, ARG_TYPE_STRING} + }, { EMPTY_OPTION } @@ -487,6 +508,20 @@ struct subcommand syncoptions[] = static void restart_service(DCB *dcb, SERVICE *service); static void restart_monitor(DCB *dcb, MONITOR *monitor); + +static void +restart_listener(DCB *dcb, SERVICE *service, const char *name) +{ + if (serviceStartListener(service, name)) + { + dcb_printf(dcb, "Restarted listener '%s'\n", name); + } + else + { + dcb_printf(dcb, "Failed to restart listener '%s'\n", name); + } +} + /** * The subcommands of the restart command */ @@ -504,6 +539,12 @@ struct subcommand restartoptions[] = "E.g. restart service \"Sales Database\"", {ARG_TYPE_SERVICE, 0, 0} }, + { + "listener", 2, 2, restart_listener, + "Restart a listener", + "E.g. restart listener \"RW Service\" \"RW Listener\"", + {ARG_TYPE_SERVICE, ARG_TYPE_STRING} + }, { EMPTY_OPTION } };