X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fconfig%2Fconfig-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fmanager%2Fimpl%2Fdependencyresolver%2FDependencyResolverManager.java;h=1a2c6b7b22f20cea8e3d309cde933ba45e7a588e;hp=645aab37ff770cfc3cbe6399f139a7cf68a07470;hb=f43b01b81319959b1907e3e04537f5169e7f33d8;hpb=623cd31f93e611196be65a6c0d09676a2868d195 diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java index 645aab37ff..1a2c6b7b22 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013, 2017 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,67 +7,88 @@ */ package org.opendaylight.controller.config.manager.impl.dependencyresolver; +import com.google.common.base.Preconditions; +import com.google.common.reflect.AbstractInvocationHandler; +import com.google.common.reflect.Reflection; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.concurrent.GuardedBy; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanServer; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.DependencyResolverFactory; import org.opendaylight.controller.config.api.JmxAttribute; import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule; +import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry; import org.opendaylight.controller.config.manager.impl.CommitInfo; -import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo; +import org.opendaylight.controller.config.manager.impl.DeadlockMonitor; +import org.opendaylight.controller.config.manager.impl.ModuleInternalInfo; +import org.opendaylight.controller.config.manager.impl.TransactionIdentifier; import org.opendaylight.controller.config.manager.impl.TransactionStatus; +import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator.TransactionModuleJMXRegistration; +import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; - -import javax.annotation.concurrent.GuardedBy; -import javax.management.InstanceAlreadyExistsException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import org.osgi.framework.BundleContext; /** * Holds information about modules being created and destroyed within this * transaction. Observes usage of DependencyResolver within modules to figure * out dependency tree. */ -public class DependencyResolverManager implements TransactionHolder, DependencyResolverFactory { +public class DependencyResolverManager implements DependencyResolverFactory, AutoCloseable { @GuardedBy("this") - private final Map moduleIdentifiersToDependencyResolverMap = new HashMap<>(); + private final Map + moduleIdentifiersToDependencyResolverMap = new HashMap<>(); + private final TransactionIdentifier transactionIdentifier; private final ModulesHolder modulesHolder; private final TransactionStatus transactionStatus; - - public DependencyResolverManager(String transactionName, - TransactionStatus transactionStatus) { - this.modulesHolder = new ModulesHolder(transactionName); + private final ServiceReferenceReadableRegistry readableRegistry; + private final BindingContextProvider bindingContextProvider; + private final DeadlockMonitor deadlockMonitor; + private final MBeanServer beanServer; + + public DependencyResolverManager(final TransactionIdentifier transactionIdentifier, + final TransactionStatus transactionStatus, final ServiceReferenceReadableRegistry readableRegistry, + final BindingContextProvider bindingContextProvider, final MBeanServer beanServer) { + this.transactionIdentifier = transactionIdentifier; + this.modulesHolder = new ModulesHolder(transactionIdentifier); this.transactionStatus = transactionStatus; + this.readableRegistry = readableRegistry; + this.bindingContextProvider = bindingContextProvider; + this.deadlockMonitor = new DeadlockMonitor(transactionIdentifier); + this.beanServer = beanServer; } @Override - public DependencyResolver createDependencyResolver(ModuleIdentifier moduleIdentifier) { + public DependencyResolver createDependencyResolver(final ModuleIdentifier moduleIdentifier) { return getOrCreate(moduleIdentifier); } - public synchronized DependencyResolverImpl getOrCreate(ModuleIdentifier name) { - DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap - .get(name); + public synchronized DependencyResolverImpl getOrCreate(final ModuleIdentifier name) { + DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name); if (dependencyResolver == null) { transactionStatus.checkNotCommitted(); - dependencyResolver = new DependencyResolverImpl(name, - transactionStatus, modulesHolder); - moduleIdentifiersToDependencyResolverMap.put(name, - dependencyResolver); + dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry, + bindingContextProvider, transactionIdentifier.getName(), beanServer); + moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver); } return dependencyResolver; } /** * Get all dependency resolvers, including those that belong to destroyed - * things? + * things?. */ private List getAllSorted() { - transactionStatus.checkCommitted(); - List sorted = new ArrayList<>( - moduleIdentifiersToDependencyResolverMap.values()); + transactionStatus.checkCommitStarted(); + List sorted = new ArrayList<>(moduleIdentifiersToDependencyResolverMap.values()); for (DependencyResolverImpl dri : sorted) { dri.countMaxDependencyDepth(this); } @@ -76,8 +97,7 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR } public List getSortedModuleIdentifiers() { - List result = new ArrayList<>( - moduleIdentifiersToDependencyResolverMap.size()); + List result = new ArrayList<>(moduleIdentifiersToDependencyResolverMap.size()); for (DependencyResolverImpl dri : getAllSorted()) { ModuleIdentifier driName = dri.getIdentifier(); result.add(driName); @@ -85,68 +105,120 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR return result; } - @Override - public ModuleInternalTransactionalInfo destroyModule( - ModuleIdentifier moduleIdentifier) { + public ModuleInternalTransactionalInfo destroyModule(final ModuleIdentifier moduleIdentifier) { transactionStatus.checkNotCommitted(); - ModuleInternalTransactionalInfo found = modulesHolder - .destroyModule(moduleIdentifier); + ModuleInternalTransactionalInfo found = modulesHolder.destroyModule(moduleIdentifier); moduleIdentifiersToDependencyResolverMap.remove(moduleIdentifier); return found; } // protect write access - @Override - public void put( - ModuleInternalTransactionalInfo moduleInternalTransactionalInfo) { + + private static final class ModuleInvocationHandler extends AbstractInvocationHandler { + private final DeadlockMonitor deadlockMonitor; + private final ModuleIdentifier moduleIdentifier; + private final Module module; + + // optimization: subsequent calls to getInstance MUST return the same value + // during transaction, + // so it is safe to cache the response + private Object cachedInstance; + + ModuleInvocationHandler(final DeadlockMonitor deadlockMonitor, final ModuleIdentifier moduleIdentifier, + final Module module) { + this.deadlockMonitor = Preconditions.checkNotNull(deadlockMonitor); + this.moduleIdentifier = Preconditions.checkNotNull(moduleIdentifier); + this.module = Preconditions.checkNotNull(module); + } + + @Override + @SuppressWarnings("checkstyle:avoidHidingCauseException") + protected Object handleInvocation(final Object proxy, final Method method, final Object[] args) + throws Throwable { + boolean isGetInstance = "getInstance".equals(method.getName()); + if (isGetInstance) { + if (cachedInstance != null) { + return cachedInstance; + } + + Preconditions.checkState(deadlockMonitor.isAlive(), "Deadlock monitor is not alive"); + deadlockMonitor.setCurrentlyInstantiatedModule(moduleIdentifier); + } + try { + Object response = method.invoke(module, args); + if (isGetInstance) { + cachedInstance = response; + } + return response; + } catch (final InvocationTargetException e) { + throw e.getCause(); + } finally { + if (isGetInstance) { + deadlockMonitor.setCurrentlyInstantiatedModule(null); + } + } + } + } + + public void put(final ModuleIdentifier moduleIdentifier, final Module module, final ModuleFactory moduleFactory, + final ModuleInternalInfo maybeOldInternalInfo, + final TransactionModuleJMXRegistration transactionModuleJMXRegistration, final boolean isDefaultBean, + final BundleContext bundleContext) { transactionStatus.checkNotCommitted(); + + Class moduleClass = Module.class; + if (module instanceof RuntimeBeanRegistratorAwareModule) { + moduleClass = RuntimeBeanRegistratorAwareModule.class; + } + Module proxiedModule = Reflection.newProxy(moduleClass, + new ModuleInvocationHandler(deadlockMonitor, moduleIdentifier, module)); + ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo( + moduleIdentifier, proxiedModule, moduleFactory, maybeOldInternalInfo, transactionModuleJMXRegistration, + isDefaultBean, module, bundleContext); modulesHolder.put(moduleInternalTransactionalInfo); } // wrapped methods: - @Override public CommitInfo toCommitInfo() { return modulesHolder.toCommitInfo(); } - @Override - public Module findModule(ModuleIdentifier moduleIdentifier, - JmxAttribute jmxAttributeForReporting) { - return modulesHolder.findModule(moduleIdentifier, - jmxAttributeForReporting); + public Module findModule(final ModuleIdentifier moduleIdentifier, final JmxAttribute jmxAttributeForReporting) { + return modulesHolder.findModule(moduleIdentifier, jmxAttributeForReporting); } - @Override - public ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo(ModuleIdentifier moduleIdentifier) { + public ModuleInternalTransactionalInfo findModuleInternalTransactionalInfo( + final ModuleIdentifier moduleIdentifier) { return modulesHolder.findModuleInternalTransactionalInfo(moduleIdentifier); } - @Override - public ModuleFactory findModuleFactory(ModuleIdentifier moduleIdentifier, - JmxAttribute jmxAttributeForReporting) { - return modulesHolder.findModuleFactory(moduleIdentifier, - jmxAttributeForReporting); + public ModuleFactory findModuleFactory(final ModuleIdentifier moduleIdentifier, + final JmxAttribute jmxAttributeForReporting) { + return modulesHolder.findModuleFactory(moduleIdentifier, jmxAttributeForReporting); } - @Override public Map getAllModules() { return modulesHolder.getAllModules(); } - @Override - public void assertNotExists(ModuleIdentifier moduleIdentifier) - throws InstanceAlreadyExistsException { + public void assertNotExists(final ModuleIdentifier moduleIdentifier) throws InstanceAlreadyExistsException { modulesHolder.assertNotExists(moduleIdentifier); } - public List findAllByFactory(ModuleFactory factory) { + public List findAllByFactory(final ModuleFactory factory) { List result = new ArrayList<>(); - for( ModuleInternalTransactionalInfo info : modulesHolder.getAllInfos()) { + for (ModuleInternalTransactionalInfo info : modulesHolder.getAllInfos()) { if (factory.equals(info.getModuleFactory())) { result.add(info.getIdentifier()); } } return result; } + + @Override + public void close() { + modulesHolder.close(); + deadlockMonitor.close(); + } }