Fix blueprint event handling 44/67444/2
authorTom Pantelis <tompantelis@gmail.com>
Mon, 22 Jan 2018 22:15:22 +0000 (17:15 -0500)
committerStephen Kitt <skitt@redhat.com>
Tue, 23 Jan 2018 08:56:07 +0000 (08:56 +0000)
The BlueprintBundleTracker registers for blueprint events so it can
log when a bundle finished creating its container, successful or not,
and also has logic to restart the container on dependency failure.
However this was  broken due to changes in Aries. You now have to
register a specific BlueprintListener onstead of a general OGSI
EventHandler.

Also this affected the BlueprintContainerRestartServiceImpl as it
relies on blueprint events to now when all bundles have completed
restart.

Change-Id: Ibb121b3995147a56be7f606ed88e9c1f59e3cd4c
Signed-off-by: Tom Pantelis <tompantelis@gmail.com>
opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java
opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintContainerRestartServiceImpl.java

index 5119c90363794b2b71334e3fc4ac17d1e2d8ae29..08a8da0bb6d98575be91098e124ce85fe239a35f 100644 (file)
@@ -31,9 +31,8 @@ import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.service.blueprint.container.BlueprintContainer;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.SynchronousBundleListener;
 import org.osgi.service.blueprint.container.BlueprintContainer;
-import org.osgi.service.blueprint.container.EventConstants;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventHandler;
+import org.osgi.service.blueprint.container.BlueprintEvent;
+import org.osgi.service.blueprint.container.BlueprintListener;
 import org.osgi.util.tracker.BundleTracker;
 import org.osgi.util.tracker.BundleTrackerCustomizer;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.BundleTracker;
 import org.osgi.util.tracker.BundleTrackerCustomizer;
 import org.osgi.util.tracker.ServiceTracker;
@@ -49,7 +48,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author Thomas Pantelis
  */
  *
  * @author Thomas Pantelis
  */
-public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCustomizer<Bundle>, EventHandler,
+public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCustomizer<Bundle>, BlueprintListener,
         SynchronousBundleListener {
     private static final Logger LOG = LoggerFactory.getLogger(BlueprintBundleTracker.class);
     private static final String BLUEPRINT_FILE_PATH = "org/opendaylight/blueprint/";
         SynchronousBundleListener {
     private static final Logger LOG = LoggerFactory.getLogger(BlueprintBundleTracker.class);
     private static final String BLUEPRINT_FILE_PATH = "org/opendaylight/blueprint/";
@@ -161,10 +160,7 @@ public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCus
     }
 
     private void registerBlueprintEventHandler(final BundleContext context) {
     }
 
     private void registerBlueprintEventHandler(final BundleContext context) {
-        Dictionary<String, Object> props = new Hashtable<>();
-        props.put(org.osgi.service.event.EventConstants.EVENT_TOPIC,
-                new String[]{EventConstants.TOPIC_CREATED, EventConstants.TOPIC_FAILURE});
-        eventHandlerReg = context.registerService(EventHandler.class.getName(), this, props);
+        eventHandlerReg = context.registerService(BlueprintListener.class.getName(), this, new Hashtable<>());
     }
 
     /**
     }
 
     /**
@@ -231,15 +227,14 @@ public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCus
     }
 
     /**
     }
 
     /**
-     * Implemented from EventHandler to listen for blueprint events.
+     * Implemented from BlueprintListener to listen for blueprint events.
      *
      * @param event the event to handle
      */
     @Override
      *
      * @param event the event to handle
      */
     @Override
-    public void handleEvent(final Event event) {
-        if (EventConstants.TOPIC_CREATED.equals(event.getTopic())) {
-            LOG.info("Blueprint container for bundle {} was successfully created",
-                    event.getProperty(EventConstants.BUNDLE));
+    public void blueprintEvent(BlueprintEvent event) {
+        if (event.getType() == BlueprintEvent.CREATED) {
+            LOG.info("Blueprint container for bundle {} was successfully created", event.getBundle());
             return;
         }
 
             return;
         }
 
@@ -247,14 +242,13 @@ public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCus
         // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
         // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
         // be set at the bundle level in the manifest - there's no way to set it globally.
         // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
         // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
         // be set at the bundle level in the manifest - there's no way to set it globally.
-        if (EventConstants.TOPIC_FAILURE.equals(event.getTopic())
-                && event.getProperty(EventConstants.DEPENDENCIES) != null) {
-            Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
+        if (event.getType() == BlueprintEvent.FAILURE && event.getDependencies() != null) {
+            Bundle bundle = event.getBundle();
 
             List<Object> paths = findBlueprintPaths(bundle);
             if (!paths.isEmpty()) {
                 LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
 
             List<Object> paths = findBlueprintPaths(bundle);
             if (!paths.isEmpty()) {
                 LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
-                        event.getProperty(EventConstants.BUNDLE));
+                        bundle);
 
                 restartService.restartContainer(bundle, paths);
             }
 
                 restartService.restartContainer(bundle, paths);
             }
index 4448c44287890c8fd2d785465bbb7b7749828044..05a796843aeaa9f3a6f15c31011992a1c38ad930 100644 (file)
@@ -18,7 +18,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
-import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Hashtable;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -54,8 +53,8 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.blueprint.container.EventConstants;
-import org.osgi.service.event.EventHandler;
+import org.osgi.service.blueprint.container.BlueprintEvent;
+import org.osgi.service.blueprint.container.BlueprintListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -88,12 +87,13 @@ class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintCo
     }
 
     public void restartContainer(final Bundle bundle, final List<Object> paths) {
     }
 
     public void restartContainer(final Bundle bundle, final List<Object> paths) {
+        LOG.debug("restartContainer for bundle {}", bundle);
+
         if (restartExecutor.isShutdown()) {
         if (restartExecutor.isShutdown()) {
+            LOG.debug("Already closed - returning");
             return;
         }
 
             return;
         }
 
-        LOG.debug("restartContainer for bundle {}", bundle);
-
         restartExecutor.execute(() -> {
             blueprintExtenderService.destroyContainer(bundle, blueprintExtenderService.getContainer(bundle));
             blueprintExtenderService.createContainer(bundle, paths);
         restartExecutor.execute(() -> {
             blueprintExtenderService.destroyContainer(bundle, blueprintExtenderService.getContainer(bundle));
             blueprintExtenderService.createContainer(bundle, paths);
@@ -131,10 +131,17 @@ class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintCo
         // restart config modules.
         final CountDownLatch containerCreationComplete = new CountDownLatch(containerBundles.size());
         ServiceRegistration<?> eventHandlerReg = registerEventHandler(forBundle.getBundleContext(), event -> {
         // restart config modules.
         final CountDownLatch containerCreationComplete = new CountDownLatch(containerBundles.size());
         ServiceRegistration<?> eventHandlerReg = registerEventHandler(forBundle.getBundleContext(), event -> {
-            final Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
-            LOG.debug("handleEvent {} for bundle {}", event.getTopic(), bundle);
-            if (containerBundles.contains(bundle)) {
+            final Bundle bundle = event.getBundle();
+            if (event.isReplay()) {
+                LOG.trace("Got replay BlueprintEvent {} for bundle {}", event.getType(), bundle);
+                return;
+            }
+
+            LOG.debug("Got BlueprintEvent {} for bundle {}", event.getType(), bundle);
+            if (containerBundles.contains(bundle)
+                    && (event.getType() == BlueprintEvent.CREATED || event.getType() == BlueprintEvent.FAILURE)) {
                 containerCreationComplete.countDown();
                 containerCreationComplete.countDown();
+                LOG.debug("containerCreationComplete is now {}", containerCreationComplete.getCount());
             }
         });
 
             }
         });
 
@@ -160,6 +167,8 @@ class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintCo
 
         // Now restart any associated config system Modules.
         restartConfigModules(forBundle.getBundleContext(), configModules);
 
         // Now restart any associated config system Modules.
         restartConfigModules(forBundle.getBundleContext(), configModules);
+
+        LOG.info("Finished restarting blueprint containers for bundle {} and its dependent bundles", forBundle);
     }
 
     /**
     }
 
     /**
@@ -360,15 +369,15 @@ class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintCo
         return value.toString();
     }
 
         return value.toString();
     }
 
-    private ServiceRegistration<?> registerEventHandler(final BundleContext bundleContext, final EventHandler handler) {
-        Dictionary<String, Object> props = new Hashtable<>();
-        props.put(org.osgi.service.event.EventConstants.EVENT_TOPIC,
-                new String[]{EventConstants.TOPIC_CREATED, EventConstants.TOPIC_FAILURE});
-        return bundleContext.registerService(EventHandler.class.getName(), handler, props);
+    private ServiceRegistration<?> registerEventHandler(final BundleContext bundleContext,
+            final BlueprintListener listener) {
+        return bundleContext.registerService(BlueprintListener.class.getName(), listener, new Hashtable<>());
     }
 
     @Override
     public void close() {
     }
 
     @Override
     public void close() {
+        LOG.debug("Closing");
+
         restartExecutor.shutdownNow();
     }
 }
         restartExecutor.shutdownNow();
     }
 }