Return-Path: X-Original-To: apmail-brooklyn-commits-archive@minotaur.apache.org Delivered-To: apmail-brooklyn-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4D49310BDA for ; Tue, 27 May 2014 10:35:38 +0000 (UTC) Received: (qmail 73784 invoked by uid 500); 27 May 2014 10:35:38 -0000 Delivered-To: apmail-brooklyn-commits-archive@brooklyn.apache.org Received: (qmail 73760 invoked by uid 500); 27 May 2014 10:35:38 -0000 Mailing-List: contact commits-help@brooklyn.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.incubator.apache.org Delivered-To: mailing list commits@brooklyn.incubator.apache.org Received: (qmail 73753 invoked by uid 99); 27 May 2014 10:35:38 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 May 2014 10:35:38 +0000 X-ASF-Spam-Status: No, hits=-2000.7 required=5.0 tests=ALL_TRUSTED,RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Tue, 27 May 2014 10:35:37 +0000 Received: (qmail 73403 invoked by uid 99); 27 May 2014 10:35:12 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 May 2014 10:35:12 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 8E99C9A6947; Tue, 27 May 2014 10:35:12 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: richard@apache.org To: commits@brooklyn.incubator.apache.org Date: Tue, 27 May 2014 10:35:17 -0000 Message-Id: In-Reply-To: <3845b4f8fe6f44578a64770ea8b2e86a@git.apache.org> References: <3845b4f8fe6f44578a64770ea8b2e86a@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [6/9] git commit: Adds timeout to Brooklyn shutdown hook X-Virus-Checked: Checked by ClamAV on apache.org Adds timeout to Brooklyn shutdown hook Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/577dfdaf Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/577dfdaf Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/577dfdaf Branch: refs/heads/master Commit: 577dfdafc98a11875e4dc3e71e2c718262d4f9f7 Parents: b361ea4 Author: Aled Sage Authored: Mon May 26 22:55:09 2014 +0100 Committer: Aled Sage Committed: Mon May 26 22:55:09 2014 +0100 ---------------------------------------------------------------------- .../entity/basic/BrooklynShutdownHooks.java | 33 +++++++++++++++----- .../entity/basic/BrooklynShutdownHooksTest.java | 20 ++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/577dfdaf/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java index df6045b..aa25858 100644 --- a/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java +++ b/core/src/main/java/brooklyn/entity/basic/BrooklynShutdownHooks.java @@ -16,6 +16,7 @@ import brooklyn.util.collections.MutableMap; import brooklyn.util.exceptions.Exceptions; import brooklyn.util.exceptions.RuntimeInterruptedException; import brooklyn.util.javalang.Threads; +import brooklyn.util.time.Duration; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; @@ -24,11 +25,27 @@ public class BrooklynShutdownHooks { private static final Logger log = LoggerFactory.getLogger(BrooklynShutdownHooks.class); + private static final Duration DEFAULT_SHUTDOWN_TIMEOUT = Duration.TWO_MINUTES; + private static final AtomicBoolean isShutdownHookRegistered = new AtomicBoolean(); private static final List entitiesToStopOnShutdown = Lists.newArrayList(); - private static final List managementContextsToTermianteOnShutdown = Lists.newArrayList(); + private static final List managementContextsToTerminateOnShutdown = Lists.newArrayList(); + /** + * Max time to wait for shutdown to complete, when stopping the entities from {@link #invokeStopOnShutdown(Entity)}. + * Default is two minutes - deliberately long because stopping cloud VMs can often take a minute. + */ + private static volatile Duration shutdownTimeout = DEFAULT_SHUTDOWN_TIMEOUT; + + public static void setShutdownTimeout(Duration val) { + shutdownTimeout = val; + } + public static void invokeStopOnShutdown(Entity entity) { + if (!(entity instanceof Startable)) { + log.warn("Not adding entity {} for stop-on-shutdown as not an instance of {}", entity, Startable.class.getSimpleName()); + return; + } synchronized (entitiesToStopOnShutdown) { entitiesToStopOnShutdown.add(entity); } @@ -36,8 +53,8 @@ public class BrooklynShutdownHooks { } public static void invokeTerminateOnShutdown(ManagementContext managementContext) { - synchronized (entitiesToStopOnShutdown) { - managementContextsToTermianteOnShutdown.add((ManagementContextInternal) managementContext); + synchronized (managementContextsToTerminateOnShutdown) { + managementContextsToTerminateOnShutdown.add((ManagementContextInternal) managementContext); } addShutdownHookIfNotAlready(); } @@ -65,9 +82,11 @@ public class BrooklynShutdownHooks { } } try { + long endTime = System.currentTimeMillis() + shutdownTimeout.toMilliseconds(); for (Task t: stops) { + Duration remainingTime = Duration.max(Duration.untilUtc(endTime), Duration.ONE_MILLISECOND); try { - Object result = t.get(); + Object result = t.get(remainingTime); if (log.isDebugEnabled()) log.debug("stopOnShutdown of {} completed: {}", t, result); } catch (Exception e) { if (log.isDebugEnabled()) log.debug("stopOnShutdown of "+t+" returned error (continuing): "+e, e); @@ -81,9 +100,9 @@ public class BrooklynShutdownHooks { } // Then terminate management contexts - synchronized (managementContextsToTermianteOnShutdown) { - log.info("Brooklyn terminateOnShutdown shutdown-hook invoked: terminating management contexts: "+managementContextsToTermianteOnShutdown); - for (ManagementContextInternal managementContext: managementContextsToTermianteOnShutdown) { + synchronized (managementContextsToTerminateOnShutdown) { + log.info("Brooklyn terminateOnShutdown shutdown-hook invoked: terminating management contexts: "+managementContextsToTerminateOnShutdown); + for (ManagementContextInternal managementContext: managementContextsToTerminateOnShutdown) { try { managementContext.terminate(); } catch (RuntimeException e) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/577dfdaf/core/src/test/java/brooklyn/entity/basic/BrooklynShutdownHooksTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/brooklyn/entity/basic/BrooklynShutdownHooksTest.java b/core/src/test/java/brooklyn/entity/basic/BrooklynShutdownHooksTest.java index 7961cf6..1ff903f 100644 --- a/core/src/test/java/brooklyn/entity/basic/BrooklynShutdownHooksTest.java +++ b/core/src/test/java/brooklyn/entity/basic/BrooklynShutdownHooksTest.java @@ -3,14 +3,19 @@ package brooklyn.entity.basic; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import brooklyn.entity.proxying.EntitySpec; import brooklyn.management.ManagementContext; +import brooklyn.test.entity.BlockingEntity; import brooklyn.test.entity.TestApplication; import brooklyn.test.entity.TestEntity; +import brooklyn.util.time.Duration; public class BrooklynShutdownHooksTest { @@ -40,6 +45,21 @@ public class BrooklynShutdownHooksTest { } @Test + public void testInvokeStopEntityTimesOutOnShutdown() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + BlockingEntity blockingEntity = app.createAndManageChild(EntitySpec.create(BlockingEntity.class) + .configure(BlockingEntity.SHUTDOWN_LATCH, latch)); + + // It will timeout after shutdown-timeout + BrooklynShutdownHooks.setShutdownTimeout(Duration.of(100, TimeUnit.MILLISECONDS)); + BrooklynShutdownHooks.invokeStopOnShutdown(blockingEntity); + BrooklynShutdownHooks.BrooklynShutdownHookJob job = new BrooklynShutdownHooks.BrooklynShutdownHookJob(); + job.run(); + + latch.countDown(); + } + + @Test public void testInvokeTerminateManagementContextOnShutdown() throws Exception { BrooklynShutdownHooks.invokeTerminateOnShutdown(managementContext); BrooklynShutdownHooks.BrooklynShutdownHookJob job = new BrooklynShutdownHooks.BrooklynShutdownHookJob();