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>
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;
*
* @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/";
}
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<>());
- * 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());
// 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));
restartService.restartContainer(bundle, paths);
}
restartService.restartContainer(bundle, paths);
}
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;
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;
}
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");
- 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);
// 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());
// 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);
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();
}
}