Remove yang-test
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / dependencyresolver / DependencyResolverManager.java
1 /*
2  * Copyright (c) 2013, 2017 Cisco 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.config.manager.impl.dependencyresolver;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.reflect.AbstractInvocationHandler;
12 import com.google.common.reflect.Reflection;
13 import java.lang.reflect.InvocationTargetException;
14 import java.lang.reflect.Method;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import javax.annotation.concurrent.GuardedBy;
21 import javax.management.InstanceAlreadyExistsException;
22 import javax.management.MBeanServer;
23 import org.opendaylight.controller.config.api.DependencyResolver;
24 import org.opendaylight.controller.config.api.DependencyResolverFactory;
25 import org.opendaylight.controller.config.api.JmxAttribute;
26 import org.opendaylight.controller.config.api.ModuleIdentifier;
27 import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
28 import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
29 import org.opendaylight.controller.config.manager.impl.CommitInfo;
30 import org.opendaylight.controller.config.manager.impl.DeadlockMonitor;
31 import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo;
32 import org.opendaylight.controller.config.manager.impl.TransactionIdentifier;
33 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
34 import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration;
35 import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
36 import org.opendaylight.controller.config.spi.Module;
37 import org.opendaylight.controller.config.spi.ModuleFactory;
38 import org.osgi.framework.BundleContext;
39
40 /**
41  * Holds information about modules being created and destroyed within this
42  * transaction. Observes usage of DependencyResolver within modules to figure
43  * out dependency tree.
44  */
45 public class DependencyResolverManager implements DependencyResolverFactory, AutoCloseable {
46     @GuardedBy("this")
47     private final Map<ModuleIdentifier, DependencyResolverImpl>
48         moduleIdentifiersToDependencyResolverMap = new HashMap<>();
49     private final TransactionIdentifier transactionIdentifier;
50     private final ModulesHolder modulesHolder;
51     private final TransactionStatus transactionStatus;
52     private final ServiceReferenceReadableRegistry readableRegistry;
53     private final BindingContextProvider bindingContextProvider;
54     private final DeadlockMonitor deadlockMonitor;
55     private final MBeanServer beanServer;
56
57     public DependencyResolverManager(final TransactionIdentifier transactionIdentifier,
58             final TransactionStatus transactionStatus, final ServiceReferenceReadableRegistry readableRegistry,
59             final BindingContextProvider bindingContextProvider, final MBeanServer beanServer) {
60         this.transactionIdentifier = transactionIdentifier;
61         this.modulesHolder = new ModulesHolder(transactionIdentifier);
62         this.transactionStatus = transactionStatus;
63         this.readableRegistry = readableRegistry;
64         this.bindingContextProvider = bindingContextProvider;
65         this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier);
66         this.beanServer = beanServer;
67     }
68
69     @Override
70     public DependencyResolver createDependencyResolver(final ModuleIdentifier moduleIdentifier) {
71         return getOrCreate(moduleIdentifier);
72     }
73
74     public synchronized DependencyResolverImpl getOrCreate(final ModuleIdentifier name) {
75         DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
76         if (dependencyResolver == null) {
77             transactionStatus.checkNotCommitted();
78             dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry,
79                     bindingContextProvider, transactionIdentifier.getName(), beanServer);
80             moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
81         }
82         return dependencyResolver;
83     }
84
85     /**
86      * Get all dependency resolvers, including those that belong to destroyed
87      * things?.
88      */
89     private List<DependencyResolverImpl> getAllSorted() {
90         transactionStatus.checkCommitStarted();
91         List<DependencyResolverImpl> sorted = new ArrayList<>(moduleIdentifiersToDependencyResolverMap.values());
92         for (DependencyResolverImpl dri : sorted) {
93             dri.countMaxDependencyDepth(this);
94         }
95         Collections.sort(sorted);
96         return sorted;
97     }
98
99     public List<ModuleIdentifier> getSortedModuleIdentifiers() {
100         List<ModuleIdentifier> result = new ArrayList<>(moduleIdentifiersToDependencyResolverMap.size());
101         for (DependencyResolverImpl dri : getAllSorted()) {
102             ModuleIdentifier driName = dri.getIdentifier();
103             result.add(driName);
104         }
105         return result;
106     }
107
108     public ModuleInternalTransactionalInfo destroyModule(final ModuleIdentifier moduleIdentifier) {
109         transactionStatus.checkNotCommitted();
110         ModuleInternalTransactionalInfo found = modulesHolder.destroyModule(moduleIdentifier);
111         moduleIdentifiersToDependencyResolverMap.remove(moduleIdentifier);
112         return found;
113     }
114
115     // protect write access
116
117     private static final class ModuleInvocationHandler extends AbstractInvocationHandler {
118         private final DeadlockMonitor deadlockMonitor;
119         private final ModuleIdentifier moduleIdentifier;
120         private final Module module;
121
122         // optimization: subsequent calls to getInstance MUST return the same value
123         // during transaction,
124         // so it is safe to cache the response
125         private Object cachedInstance;
126
127         ModuleInvocationHandler(final DeadlockMonitor deadlockMonitor, final ModuleIdentifier moduleIdentifier,
128                 final Module module) {
129             this.deadlockMonitor = Preconditions.checkNotNull(deadlockMonitor);
130             this.moduleIdentifier = Preconditions.checkNotNull(moduleIdentifier);
131             this.module = Preconditions.checkNotNull(module);
132         }
133
134         @Override
135         @SuppressWarnings("checkstyle:avoidHidingCauseException")
136         protected Object handleInvocation(final Object proxy, final Method method, final Object[] args)
137                 throws Throwable {
138             boolean isGetInstance = "getInstance".equals(method.getName());
139             if (isGetInstance) {
140                 if (cachedInstance != null) {
141                     return cachedInstance;
142                 }
143
144                 Preconditions.checkState(deadlockMonitor.isAlive(), "Deadlock monitor is not alive");
145                 deadlockMonitor.setCurrentlyInstantiatedModule(moduleIdentifier);
146             }
147             try {
148                 Object response = method.invoke(module, args);
149                 if (isGetInstance) {
150                     cachedInstance = response;
151                 }
152                 return response;
153             } catch (final InvocationTargetException e) {
154                 throw e.getCause();
155             } finally {
156                 if (isGetInstance) {
157                     deadlockMonitor.setCurrentlyInstantiatedModule(null);
158                 }
159             }
160         }
161     }
162
163     public void put(final ModuleIdentifier moduleIdentifier, final Module module, final ModuleFactory moduleFactory,
164             final ModuleInternalInfo maybeOldInternalInfo,
165             final TransactionModuleJMXRegistration transactionModuleJMXRegistration, final boolean isDefaultBean,
166             final BundleContext bundleContext) {
167         transactionStatus.checkNotCommitted();
168
169         Class<? extends Module> moduleClass = Module.class;
170         if (module instanceof RuntimeBeanRegistratorAwareModule) {
171             moduleClass = RuntimeBeanRegistratorAwareModule.class;
172         }
173         Module proxiedModule = Reflection.newProxy(moduleClass,
174                 new ModuleInvocationHandler(deadlockMonitor, moduleIdentifier, module));
175         ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo(
176                 moduleIdentifier, proxiedModule, moduleFactory, maybeOldInternalInfo, transactionModuleJMXRegistration,
177                 isDefaultBean, module, bundleContext);
178         modulesHolder.put(moduleInternalTransactionalInfo);
179     }
180
181     // wrapped methods:
182
183     public CommitInfo toCommitInfo() {
184         return modulesHolder.toCommitInfo();
185     }
186
187     public Module findModule(final ModuleIdentifier moduleIdentifier, final JmxAttribute jmxAttributeForReporting) {
188         return modulesHolder.findModule(moduleIdentifier, jmxAttributeForReporting);
189     }
190
191     public ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo(
192             final ModuleIdentifier moduleIdentifier) {
193         return modulesHolder.findModuleInternalTransactionalInfo(moduleIdentifier);
194     }
195
196     public ModuleFactory findModuleFactory(final ModuleIdentifier moduleIdentifier,
197             final JmxAttribute jmxAttributeForReporting) {
198         return modulesHolder.findModuleFactory(moduleIdentifier, jmxAttributeForReporting);
199     }
200
201     public Map<ModuleIdentifier, Module> getAllModules() {
202         return modulesHolder.getAllModules();
203     }
204
205     public void assertNotExists(final ModuleIdentifier moduleIdentifier) throws InstanceAlreadyExistsException {
206         modulesHolder.assertNotExists(moduleIdentifier);
207     }
208
209     public List<ModuleIdentifier> findAllByFactory(final ModuleFactory factory) {
210         List<ModuleIdentifier> result = new ArrayList<>();
211         for (ModuleInternalTransactionalInfo info : modulesHolder.getAllInfos()) {
212             if (factory.equals(info.getModuleFactory())) {
213                 result.add(info.getIdentifier());
214             }
215         }
216         return result;
217     }
218
219     @Override
220     public void close() {
221         modulesHolder.close();
222         deadlockMonitor.close();
223     }
224 }

©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.