Entities.destroyAll: stop apps concurrently

Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/0ecf677e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/0ecf677e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/0ecf677e

Branch: refs/heads/master
Commit: 0ecf677ee8fd26b2fc4d35187421bd155c7b8c11
Parents: c9693fe
Author: Aled Sage <[email protected]>
Authored: Fri Feb 6 15:06:16 2015 +0000
Committer: Aled Sage <[email protected]>
Committed: Fri Feb 6 15:06:16 2015 +0000

----------------------------------------------------------------------
 .../java/brooklyn/entity/basic/Entities.java    | 62 ++++++++++++++------
 1 file changed, 43 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0ecf677e/core/src/main/java/brooklyn/entity/basic/Entities.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/Entities.java 
b/core/src/main/java/brooklyn/entity/basic/Entities.java
index 7736d50..68b7912 100644
--- a/core/src/main/java/brooklyn/entity/basic/Entities.java
+++ b/core/src/main/java/brooklyn/entity/basic/Entities.java
@@ -34,6 +34,7 @@ import java.util.Set;
 import java.util.Stack;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -106,6 +107,11 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import com.google.common.reflect.TypeToken;
+import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 
 /**
  * Convenience methods for working with entities.
@@ -716,36 +722,54 @@ public class Entities {
 
     /**
      * Stops, destroys, and unmanages all apps in the given context, and then 
terminates the management context.
+     * 
+     * Apps will be stopped+destroyed+unmanaged concurrently, waiting for all 
to complete.
      */
-    public static void destroyAll(ManagementContext mgmt) {
-        Exception error = null;
+    public static void destroyAll(final ManagementContext mgmt) {
         if (mgmt instanceof NonDeploymentManagementContext) {
             // log here because it is easy for tests to 
destroyAll(app.getMgmtContext())
             // which will *not* destroy the mgmt context if the app has been 
stopped!
             log.warn("Entities.destroyAll invoked on non-deployment "+mgmt+" - 
not likely to have much effect! " +
-                    "(This usually means the mgmt context has been taken from 
entity has been destroyed. " +
+                    "(This usually means the mgmt context has been taken from 
an entity that has been destroyed. " +
                     "To destroy other things on the management context ensure 
you keep a handle to the context " +
                     "before the entity is destroyed, such as by creating the 
management context first.)");
         }
         if (!mgmt.isRunning()) return;
-        log.debug("destroying all apps in "+mgmt+": "+mgmt.getApplications());
-        for (Application app: mgmt.getApplications()) {
-            log.debug("destroying app "+app+" (managed? "+isManaged(app)+"; 
mgmt is "+mgmt+")");
-            try {
-                destroy(app);
-                log.debug("destroyed app "+app+"; mgmt now "+mgmt);
-            } catch (Exception e) {
-                log.warn("problems destroying app "+app+" (mgmt now "+mgmt+", 
will rethrow at least one exception): "+e);
-                if (error==null) error = e;
+        
+        ListeningExecutorService executor = 
MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
+        List<ListenableFuture<?>> futures = Lists.newArrayList();
+        final AtomicReference<Exception> error = Atomics.newReference();
+        try {
+            log.debug("destroying all apps in "+mgmt+": 
"+mgmt.getApplications());
+            for (final Application app: mgmt.getApplications()) {
+                futures.add(executor.submit(new Runnable() {
+                    public void run() {
+                        log.debug("destroying app "+app+" (managed? 
"+isManaged(app)+"; mgmt is "+mgmt+")");
+                        try {
+                            destroy(app);
+                            log.debug("destroyed app "+app+"; mgmt now "+mgmt);
+                        } catch (Exception e) {
+                            log.warn("problems destroying app "+app+" (mgmt 
now "+mgmt+", will rethrow at least one exception): "+e);
+                            error.compareAndSet(null, e);
+                        }
+                    }}));
             }
+            Futures.allAsList(futures).get();
+            
+            for (Location loc : mgmt.getLocationManager().getLocations()) {
+                destroyCatching(loc);
+            }
+            if (mgmt instanceof ManagementContextInternal) {
+                ((ManagementContextInternal)mgmt).terminate();
+            }
+            if (error.get() != null) throw Exceptions.propagate(error.get());
+        } catch (InterruptedException e) {
+            throw Exceptions.propagate(e);
+        } catch (ExecutionException e) {
+            throw Exceptions.propagate(e);
+        } finally {
+            executor.shutdownNow();
         }
-        for (Location loc : mgmt.getLocationManager().getLocations()) {
-            destroyCatching(loc);
-        }
-        if (mgmt instanceof ManagementContextInternal) {
-            ((ManagementContextInternal)mgmt).terminate();
-        }
-        if (error!=null) throw Exceptions.propagate(error);
     }
 
     /** Same as {@link #destroyAll(ManagementContext)} but catching all errors 
*/

Reply via email to