From 0e0e2378d379e2fbc12d8f93ef41b3267e10f83a Mon Sep 17 00:00:00 2001 From: Tom Pantelis Date: Mon, 22 Jan 2018 17:15:22 -0500 Subject: [PATCH] Fix blueprint event handling 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 --- .../blueprint/BlueprintBundleTracker.java | 28 ++++++--------- .../BlueprintContainerRestartServiceImpl.java | 35 ++++++++++++------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java index 5119c90363..08a8da0bb6 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintBundleTracker.java @@ -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, EventHandler, +public class BlueprintBundleTracker implements BundleActivator, BundleTrackerCustomizer, 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 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 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); } diff --git a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintContainerRestartServiceImpl.java b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintContainerRestartServiceImpl.java index 4448c44287..05a796843a 100644 --- a/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintContainerRestartServiceImpl.java +++ b/opendaylight/blueprint/src/main/java/org/opendaylight/controller/blueprint/BlueprintContainerRestartServiceImpl.java @@ -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 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 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(); } } -- 2.36.6