You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by gn...@apache.org on 2009/07/03 16:41:15 UTC

svn commit: r790932 - /geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java

Author: gnodet
Date: Fri Jul  3 14:41:15 2009
New Revision: 790932

URL: http://svn.apache.org/viewvc?rev=790932&view=rev
Log:
Fix extender shutdown

Modified:
    geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java

Modified: geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java?rev=790932&r1=790931&r2=790932&view=diff
==============================================================================
--- geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java (original)
+++ geronimo/sandbox/blueprint/blueprint-core/src/main/java/org/apache/geronimo/blueprint/container/BlueprintExtender.java Fri Jul  3 14:41:15 2009
@@ -24,6 +24,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Comparator;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 
@@ -37,6 +38,7 @@
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.Constants;
 import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.service.blueprint.container.BlueprintEvent;
 import org.slf4j.Logger;
@@ -88,21 +90,58 @@
 
     public void stop(BundleContext context) {
         LOGGER.debug("Stopping blueprint extender...");
-        // TODO: we should order the blueprint container destruction wrt service exports / dependencies
-        // TODO: also if a blueprint bundle is being stopped at the same time (this could happen if the framework
-        // TODO: is shut down, we should not wait for the blueprint container to be destroyed if it is already being
-        // TODO: destroyed by the extender
-        List<Bundle> bundles = new ArrayList<Bundle>(containers.keySet());
-        for (Bundle bundle : bundles) {
+        context.removeBundleListener(this);
+        // Orderly shutdown of containers
+        while (!containers.isEmpty()) {
+            Bundle bundle = getBundleToDestroy();
             destroyContext(bundle);
         }
-        context.removeBundleListener(this);
         this.eventDispatcher.destroy();
         this.handlers.destroy();
         executors.shutdown();
         LOGGER.debug("Blueprint extender stopped");
     }
 
+    private Bundle getBundleToDestroy() {
+        Bundle bundleToDestroy = null;
+        for (Bundle bundle : containers.keySet()) {
+            ServiceReference[] references = bundle.getRegisteredServices();
+            int usage = 0;
+            if (references != null) {
+                for (ServiceReference reference : references) {
+                    Bundle[] usingBundles = reference.getUsingBundles();
+                    if (usingBundles != null) {
+                        usage += usingBundles.length;
+                    }
+                }
+            }
+            LOGGER.debug("Usage for bundle {} is {}", bundle, usage);
+            if (usage == 0) {
+                if (bundleToDestroy == null) {
+                    LOGGER.debug("Currently selecting bundle {} for destroy (first bundle with no usage)", bundle);
+                    bundleToDestroy = bundle;
+                } else if (bundle.getLastModified() > bundleToDestroy.getLastModified()) {
+                    LOGGER.debug("Currently selecting bundle {} for destroy (it has been installed more recently)", bundle);
+                    bundleToDestroy = bundle;
+                }
+            }
+        }
+        if (bundleToDestroy == null) {
+            ServiceReference ref = null;
+            for (Bundle bundle : containers.keySet()) {
+                ServiceReference[] references = bundle.getRegisteredServices();
+                for (ServiceReference reference : references) {
+                    if (ref == null || reference.compareTo(ref) > 0) {
+                        LOGGER.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
+                        ref = reference;
+                    }
+                }
+            }
+            bundleToDestroy = ref.getBundle();
+        }
+        return bundleToDestroy;
+    }
+
     public void bundleChanged(BundleEvent event) {
         Bundle bundle = event.getBundle();
         if (event.getType() == BundleEvent.LAZY_ACTIVATION) {