2 * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.blueprint;
10 import com.google.common.collect.Lists;
11 import com.google.common.util.concurrent.ThreadFactoryBuilder;
12 import java.util.ArrayList;
13 import java.util.LinkedHashSet;
14 import java.util.List;
16 import java.util.concurrent.ExecutorService;
17 import java.util.concurrent.Executors;
18 import org.apache.aries.blueprint.services.BlueprintExtenderService;
19 import org.osgi.framework.Bundle;
20 import org.osgi.framework.ServiceReference;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Implementation of the BlueprintContainerRestartService.
27 * @author Thomas Pantelis
29 class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintContainerRestartService {
30 private static final Logger LOG = LoggerFactory.getLogger(BlueprintContainerRestartServiceImpl.class);
32 private final ExecutorService restartExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().
33 setDaemon(true).setNameFormat("BlueprintContainerRestartService").build());
34 private final BlueprintExtenderService blueprintExtenderService;
36 BlueprintContainerRestartServiceImpl(BlueprintExtenderService blueprintExtenderService) {
37 this.blueprintExtenderService = blueprintExtenderService;
41 public void restartContainerAndDependents(final Bundle bundle) {
42 LOG.debug("restartContainerAndDependents for bundle {}", bundle);
44 restartExecutor.execute(new Runnable() {
47 restartContainerAndDependentsInternal(bundle);
53 private void restartContainerAndDependentsInternal(Bundle forBundle) {
54 // We use a LinkedHashSet to preserve insertion order as we walk the service usage hierarchy.
55 Set<Bundle> containerBundlesSet = new LinkedHashSet<>();
56 findDependentContainersRecursively(forBundle, containerBundlesSet);
58 List<Bundle> containerBundles = new ArrayList<>(containerBundlesSet);
60 LOG.info("Restarting blueprint containers for bundle {} and its dependent bundles {}", forBundle,
61 containerBundles.subList(1, containerBundles.size()));
63 // Destroy the containers in reverse order with 'forBundle' last, ie bottom-up in the service tree.
64 for(Bundle bundle: Lists.reverse(containerBundles)) {
65 blueprintExtenderService.destroyContainer(bundle, blueprintExtenderService.getContainer(bundle));
68 // Restart the containers top-down starting with 'forBundle'.
69 for(Bundle bundle: containerBundles) {
70 List<Object> paths = BlueprintBundleTracker.findBlueprintPaths(bundle);
72 LOG.info("Restarting blueprint container for bundle {} with paths {}", bundle, paths);
74 blueprintExtenderService.createContainer(bundle, paths);
79 * Recursively finds the services registered by the given bundle and the bundles using those services.
80 * User bundles that have an associated blueprint container are added to containerBundles.
82 * @param bundle the bundle to traverse
83 * @param containerBundles the current set of bundles containing blueprint containers
85 private void findDependentContainersRecursively(Bundle bundle, Set<Bundle> containerBundles) {
86 if(!containerBundles.add(bundle)) {
87 // Already seen this bundle...
91 ServiceReference<?>[] references = bundle.getRegisteredServices();
92 if (references != null) {
93 for (ServiceReference<?> reference : references) {
94 Bundle[] usingBundles = reference.getUsingBundles();
95 if(usingBundles != null) {
96 for(Bundle usingBundle: usingBundles) {
97 if(blueprintExtenderService.getContainer(usingBundle) != null) {
98 findDependentContainersRecursively(usingBundle, containerBundles);
107 public void close() {
108 restartExecutor.shutdownNow();