From 1ea998182b78ee8e857aa2974c554ca952f1f68f Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Sat, 16 Mar 2019 13:47:21 -0400 Subject: Make ServiceManager implement Startable Also added a "name" to the manager, for logger purposes. Change-Id: Ide57cdec1fafc36c43b7f7584c0baad6261e8412 Issue-ID: POLICY-1542 Signed-off-by: Jim Hahn --- .../common/utils/services/ServiceManager.java | 86 +++++++++++++++------- 1 file changed, 59 insertions(+), 27 deletions(-) (limited to 'utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java') diff --git a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java index 8bf89d56..13cd6de8 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java +++ b/utils/src/main/java/org/onap/policy/common/utils/services/ServiceManager.java @@ -31,9 +31,14 @@ import org.slf4j.LoggerFactory; * Manages a series of services. The services are started in order, and stopped in reverse * order. */ -public class ServiceManager { +public class ServiceManager implements Startable { private static final Logger logger = LoggerFactory.getLogger(ServiceManager.class); + /** + * Manager name. + */ + private final String name; + /** * Services to be started/stopped. */ @@ -44,6 +49,25 @@ public class ServiceManager { */ private boolean running; + /** + * Constructs the object, with a default name. + */ + public ServiceManager() { + this("service manager"); + } + + /** + * Constructs the object. + * @param name the manager's name, used for logging purposes + */ + public ServiceManager(String name) { + this.name = name; + } + + public String getName() { + return name; + } + /** * Adds a pair of service actions to the manager. * @@ -54,7 +78,7 @@ public class ServiceManager { */ public synchronized ServiceManager addAction(String stepName, RunnableWithEx starter, RunnableWithEx stopper) { if (running) { - throw new IllegalStateException("services are already running; cannot add " + stepName); + throw new IllegalStateException(name + " is already running; cannot add " + stepName); } items.add(new Service(stepName, starter, stopper)); @@ -71,44 +95,47 @@ public class ServiceManager { */ public synchronized ServiceManager addService(String stepName, Startable service) { if (running) { - throw new IllegalStateException("services are already running; cannot add " + stepName); + throw new IllegalStateException(name + " is already running; cannot add " + stepName); } items.add(new Service(stepName, () -> service.start(), () -> service.stop())); return this; } - /** - * Starts each service, in order. If a service throws an exception, then the - * previously started services are stopped, in reverse order. - * - * @throws ServiceManagerException if a service fails to start - */ - public synchronized void start() throws ServiceManagerException { + @Override + public synchronized boolean isAlive() { + return running; + } + + @Override + public synchronized boolean start() { if (running) { - throw new IllegalStateException("services are already running"); + throw new IllegalStateException(name + " is already running"); } + logger.info("{} starting", name); + // tracks the services that have been started so far Deque started = new LinkedList<>(); Exception ex = null; for (Service item : items) { try { - logger.info("starting {}", item.stepName); + logger.info("{} starting {}", name, item.stepName); item.starter.run(); started.add(item); } catch (Exception e) { - logger.error("failed to start {}; rewinding steps", item.stepName); + logger.error("{} failed to start {}; rewinding steps", name, item.stepName); ex = e; break; } } if (ex == null) { + logger.info("{} started", name); running = true; - return; + return true; } // one of the services failed to start - rewind those we've previously started @@ -116,26 +143,27 @@ public class ServiceManager { rewind(started); } catch (ServiceManagerException e) { - logger.error("rewind failed", e); + logger.error("{} rewind failed", name, e); } throw new ServiceManagerException(ex); } - /** - * Stops the services, in reverse order from which they were started. Stops all of the - * services, even if one of the "stop" functions throws an exception. Assumes that - * {@link #start()} has completed successfully. - * - * @throws ServiceManagerException if a service fails to stop - */ - public synchronized void stop() throws ServiceManagerException { + @Override + public synchronized boolean stop() { if (!running) { - throw new IllegalStateException("services are not running"); + throw new IllegalStateException(name + " is not running"); } running = false; rewind(items); + + return true; + } + + @Override + public void shutdown() { + stop(); } /** @@ -148,21 +176,25 @@ public class ServiceManager { private void rewind(Deque running) throws ServiceManagerException { Exception ex = null; + logger.info("{} stopping", name); + // stop everything, in reverse order Iterator it = running.descendingIterator(); while (it.hasNext()) { Service item = it.next(); try { - logger.info("stopping {}", item.stepName); + logger.info("{} stopping {}", name, item.stepName); item.stopper.run(); } catch (Exception e) { - logger.error("failed to stop {}", item.stepName); + logger.error("{} failed to stop {}", name, item.stepName); ex = e; // do NOT break or re-throw, as we must stop ALL remaining items } } + logger.info("{} stopped", name); + if (ex != null) { throw new ServiceManagerException(ex); } @@ -185,6 +217,6 @@ public class ServiceManager { @FunctionalInterface public static interface RunnableWithEx { - public void run() throws Exception; + void run() throws Exception; } } -- cgit 1.2.3-korg