107ea39c1c6c8f4753d38dd07db6da74775b9cf5
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / BlueprintContainerRestartServiceImpl.java
1 /*
2  * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.blueprint;
9
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;
15 import java.util.Set;
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;
23
24 /**
25  * Implementation of the BlueprintContainerRestartService.
26  *
27  * @author Thomas Pantelis
28  */
29 class BlueprintContainerRestartServiceImpl implements AutoCloseable, BlueprintContainerRestartService {
30     private static final Logger LOG = LoggerFactory.getLogger(BlueprintContainerRestartServiceImpl.class);
31
32     private final ExecutorService restartExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().
33             setDaemon(true).setNameFormat("BlueprintContainerRestartService").build());
34     private final BlueprintExtenderService blueprintExtenderService;
35
36     BlueprintContainerRestartServiceImpl(BlueprintExtenderService blueprintExtenderService) {
37         this.blueprintExtenderService = blueprintExtenderService;
38     }
39
40     @Override
41     public void restartContainerAndDependents(final Bundle bundle) {
42         LOG.debug("restartContainerAndDependents for bundle {}", bundle);
43
44         restartExecutor.execute(new Runnable() {
45             @Override
46             public void run() {
47                 restartContainerAndDependentsInternal(bundle);
48
49             }
50         });
51     }
52
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);
57
58         List<Bundle> containerBundles = new ArrayList<>(containerBundlesSet);
59
60         LOG.info("Restarting blueprint containers for bundle {} and its dependent bundles {}", forBundle,
61                 containerBundles.subList(1, containerBundles.size()));
62
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));
66         }
67
68         // Restart the containers top-down starting with 'forBundle'.
69         for(Bundle bundle: containerBundles) {
70             List<Object> paths = BlueprintBundleTracker.findBlueprintPaths(bundle);
71
72             LOG.info("Restarting blueprint container for bundle {} with paths {}", bundle, paths);
73
74             blueprintExtenderService.createContainer(bundle, paths);
75         }
76     }
77
78     /**
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.
81      *
82      * @param bundle the bundle to traverse
83      * @param containerBundles the current set of bundles containing blueprint containers
84      */
85     private void findDependentContainersRecursively(Bundle bundle, Set<Bundle> containerBundles) {
86         if(!containerBundles.add(bundle)) {
87             // Already seen this bundle...
88             return;
89         }
90
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);
99                         }
100                     }
101                 }
102             }
103         }
104     }
105
106     @Override
107     public void close() {
108         restartExecutor.shutdownNow();
109     }
110 }