ShutdownHookManager { @VisibleForTesting @InterfaceAudience.Private ShutdownHookManager() { } @VisibleForTesting @InterfaceAudience.Private  ShutdownHookManager(); @InterfaceAudience.Public static ShutdownHookManager get(); @InterfaceAudience.Public @InterfaceStability.Stable void addShutdownHook(Runnable shutdownHook, int priority); @InterfaceAudience.Public @InterfaceStability.Stable void addShutdownHook(Runnable shutdownHook, int priority, long timeout,
      TimeUnit unit); @InterfaceAudience.Public @InterfaceStability.Stable boolean removeShutdownHook(Runnable shutdownHook); @InterfaceAudience.Public @InterfaceStability.Stable boolean hasShutdownHook(Runnable shutdownHook); @InterfaceAudience.Public @InterfaceStability.Stable boolean isShutdownInProgress(); @InterfaceAudience.Public @InterfaceStability.Stable void clearShutdownHooks(); static final long TIMEOUT_MINIMUM; static final TimeUnit TIME_UNIT_DEFAULT; }
@Test public void shutdownHookManager() { assertNotNull("No ShutdownHookManager", mgr); assertEquals(0, mgr.getShutdownHooksInOrder().size()); Hook hook1 = new Hook("hook1", 0, false); Hook hook2 = new Hook("hook2", 0, false); Hook hook3 = new Hook("hook3", 1000, false); Hook hook4 = new Hook("hook4", 25000, true); Hook hook5 = new Hook("hook5", (SERVICE_SHUTDOWN_TIMEOUT_DEFAULT + 1) * 1000, true); mgr.addShutdownHook(hook1, 0); assertTrue(mgr.hasShutdownHook(hook1)); assertEquals(1, mgr.getShutdownHooksInOrder().size()); assertEquals(hook1, mgr.getShutdownHooksInOrder().get(0).getHook()); assertTrue(mgr.removeShutdownHook(hook1)); assertFalse(mgr.hasShutdownHook(hook1)); assertFalse(mgr.removeShutdownHook(hook1)); mgr.addShutdownHook(hook1, 0); assertTrue(mgr.hasShutdownHook(hook1)); assertEquals(1, mgr.getShutdownHooksInOrder().size()); assertEquals(SERVICE_SHUTDOWN_TIMEOUT_DEFAULT, mgr.getShutdownHooksInOrder().get(0).getTimeout()); mgr.addShutdownHook(hook2, 1); assertTrue(mgr.hasShutdownHook(hook1)); assertTrue(mgr.hasShutdownHook(hook2)); assertEquals(2, mgr.getShutdownHooksInOrder().size()); assertEquals(hook2, mgr.getShutdownHooksInOrder().get(0).getHook()); assertEquals(hook1, mgr.getShutdownHooksInOrder().get(1).getHook()); mgr.addShutdownHook(hook3, 2, 4, TimeUnit.SECONDS); assertTrue(mgr.hasShutdownHook(hook3)); assertEquals(hook3, mgr.getShutdownHooksInOrder().get(0).getHook()); assertEquals(4, mgr.getShutdownHooksInOrder().get(0).getTimeout()); int hook4timeout = 2; mgr.addShutdownHook(hook4, 3, hook4timeout, TimeUnit.SECONDS); assertTrue(mgr.hasShutdownHook(hook4)); assertEquals(hook4, mgr.getShutdownHooksInOrder().get(0).getHook()); assertEquals(2, mgr.getShutdownHooksInOrder().get(0).getTimeout()); mgr.addShutdownHook(hook5, 5); ShutdownHookManager.HookEntry hookEntry5 = mgr.getShutdownHooksInOrder() .get(0); assertEquals(hook5, hookEntry5.getHook()); assertEquals("default timeout not used", ShutdownHookManager.getShutdownTimeout(new Configuration()), hookEntry5.getTimeout()); assertEquals("hook priority", 5, hookEntry5.getPriority()); assertTrue("failed to remove " + hook5, mgr.removeShutdownHook(hook5)); INVOCATION_COUNT.set(0); LOG.info("invoking executeShutdown()"); int timeouts = mgr.executeShutdown(); LOG.info("Shutdown completed"); assertEquals("Number of timed out hooks", 1, timeouts); List<ShutdownHookManager.HookEntry> hooks = mgr.getShutdownHooksInOrder(); for (ShutdownHookManager.HookEntry entry : hooks) { Hook hook = (Hook) entry.getHook(); assertTrue("Was not invoked " + hook, hook.invoked); hook.maybeThrowAssertion(); } assertEquals("Expected to be invoked first " + hook4, 1, hook4.invokedOrder); assertFalse("Expected to time out " + hook4, hook4.completed); assertTrue("Expected to complete " + hook1, hook1.completed); long invocationInterval = hook1.startTime - hook4.startTime; assertTrue("invocation difference too short " + invocationInterval, invocationInterval >= hook4timeout * 1000); assertTrue("sleeping hook4 blocked other threads for " + invocationInterval, invocationInterval < hook4.sleepTime); mgr.clearShutdownHooks(); assertFalse(mgr.hasShutdownHook(hook1)); assertEquals("shutdown hook list is not empty", 0, mgr.getShutdownHooksInOrder().size()); }