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 5119c90..08a8da0 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.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;
@@ -49,7 +48,7 @@ import org.slf4j.LoggerFactory;
  *
  * @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/";
@@ -161,10 +160,7 @@ public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCus
     }
 
     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
-    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;
         }
 
@@ -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.
-        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",
-                        event.getProperty(EventConstants.BUNDLE));
+                        bundle);
 
                 restartService.restartContainer(bundle, paths);
             }
index 4448c44..05a7968 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.Dictionary;
 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.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;
@@ -88,12 +87,13 @@ class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintCo
     }
 
     public void restartContainer(final Bundle bundle, final List<Object> paths) {
+        LOG.debug("restartContainer for bundle {}", bundle);
+
         if (restartExecutor.isShutdown()) {
+            LOG.debug("Already closed - returning");
             return;
         }
 
-        LOG.debug("restartContainer for bundle {}", bundle);
-
         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 -> {
-            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();
+                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);
+
+        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();
     }
 
-    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() {
+        LOG.debug("Closing");
+
         restartExecutor.shutdownNow();
     }
 }

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.