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%2FConfigTransactionControllerImpl.java;h=7a1a74e75f26c4f8839e2b0661e9577f89e35590;hp=bb61c4acc70aa6506b6d3093748a519d5fa036be;hb=b712eb01354ddb5878008e2a2e8f03fb19b92555;hpb=597ffbbfe362fcea479b7fdb52f685289b7ea5fd diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java index bb61c4acc7..7a1a74e75f 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java @@ -7,9 +7,8 @@ */ package org.opendaylight.controller.config.manager.impl; -import static com.google.common.base.Preconditions.checkNotNull; -import static java.lang.String.format; - +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -26,8 +25,10 @@ import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; import javax.management.ObjectName; import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.ModuleFactoryNotFoundException; import org.opendaylight.controller.config.api.ModuleIdentifier; import org.opendaylight.controller.config.api.ValidationException; +import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager; import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo; @@ -37,13 +38,16 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtom import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder; import org.opendaylight.controller.config.manager.impl.jmx.TransactionModuleJMXRegistrator; 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.manager.impl.util.InterfacesHelper; +import org.opendaylight.controller.config.spi.AbstractModule; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.concepts.Identifiable; -import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * This is a JMX bean representing current transaction. It contains * transaction identifier, unique version and parent version for @@ -58,7 +62,8 @@ class ConfigTransactionControllerImpl implements private final ConfigTransactionLookupRegistry txLookupRegistry; private final ObjectName controllerON; - private final long parentVersion, currentVersion; + private final long parentVersion; + private final long currentVersion; private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder; private final DependencyResolverManager dependencyResolverManager; private final TransactionStatus transactionStatus; @@ -81,11 +86,11 @@ class ConfigTransactionControllerImpl implements @GuardedBy("this") private final SearchableServiceReferenceWritableRegistry writableSRRegistry; - public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry, - long parentVersion, CodecRegistry codecRegistry, long currentVersion, - Map> currentlyRegisteredFactories, - MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, - boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) { + public ConfigTransactionControllerImpl(final ConfigTransactionLookupRegistry txLookupRegistry, + final long parentVersion, final BindingContextProvider bindingContextProvider, final long currentVersion, + final Map> currentlyRegisteredFactories, + final MBeanServer transactionsMBeanServer, final MBeanServer configMBeanServer, + final boolean blankTransaction, final SearchableServiceReferenceWritableRegistry writableSRRegistry) { this.txLookupRegistry = txLookupRegistry; String transactionName = txLookupRegistry.getTransactionIdentifier().getName(); this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName); @@ -95,7 +100,7 @@ class ConfigTransactionControllerImpl implements this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories); this.transactionStatus = new TransactionStatus(); this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(), - transactionStatus, writableSRRegistry, codecRegistry, transactionsMBeanServer); + transactionStatus, writableSRRegistry, bindingContextProvider, transactionsMBeanServer); this.transactionsMBeanServer = transactionsMBeanServer; this.configMBeanServer = configMBeanServer; this.blankTransaction = blankTransaction; @@ -103,19 +108,19 @@ class ConfigTransactionControllerImpl implements } @Override - public void copyExistingModulesAndProcessFactoryDiff(Collection existingModules, List lastListOfFactories) { + public void copyExistingModulesAndProcessFactoryDiff(final Collection existingModules, final List lastListOfFactories) { // copy old configuration to this server for (ModuleInternalInfo oldConfigInfo : existingModules) { try { copyExistingModule(oldConfigInfo); - } catch (InstanceAlreadyExistsException e) { + } catch (final InstanceAlreadyExistsException e) { throw new IllegalStateException("Error while copying " + oldConfigInfo, e); } } processDefaultBeans(lastListOfFactories); } - private synchronized void processDefaultBeans(List lastListOfFactories) { + private synchronized void processDefaultBeans(final List lastListOfFactories) { transactionStatus.checkNotCommitStarted(); transactionStatus.checkNotAborted(); @@ -125,12 +130,12 @@ class ConfigTransactionControllerImpl implements List toBeAdded = new ArrayList<>(); List toBeRemoved = new ArrayList<>(); for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) { - if (oldSet.contains(moduleFactory) == false) { + if (!oldSet.contains(moduleFactory)) { toBeAdded.add(moduleFactory); } } for (ModuleFactory moduleFactory : lastListOfFactories) { - if (newSet.contains(moduleFactory) == false) { + if (!newSet.contains(moduleFactory)) { toBeRemoved.add(moduleFactory); } } @@ -142,13 +147,24 @@ class ConfigTransactionControllerImpl implements for (Module module : defaultModules) { // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier()); + final ObjectName objectName; try { boolean defaultBean = true; - putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, + objectName = putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean, bundleContext); - } catch (InstanceAlreadyExistsException e) { + } catch (final InstanceAlreadyExistsException e) { throw new IllegalStateException(e); } + + // register default module as every possible service + final Set serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory); + for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) { + try { + saveServiceReference(qname, module.getIdentifier().getInstanceName(), objectName); + } catch (final InstanceNotFoundException e) { + throw new IllegalStateException("Unable to register default module instance " + module + " as a service of " + qname, e); + } + } } } @@ -156,13 +172,26 @@ class ConfigTransactionControllerImpl implements for (ModuleFactory removedFactory : toBeRemoved) { List modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory); for (ModuleIdentifier name : modulesOfRemovedFactory) { + // remove service refs + final ModuleFactory moduleFactory = dependencyResolverManager.findModuleInternalTransactionalInfo(name).getModuleFactory(); + final Set serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory); + for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) { + try { + removeServiceReference(qname, name.getInstanceName()); + } catch (final InstanceNotFoundException e) { + throw new IllegalStateException("Unable to UNregister default module instance " + name + " as a service of " + qname, e); + } + } + + // close module destroyModule(name); } } } - private synchronized void copyExistingModule(ModuleInternalInfo oldConfigBeanInfo) throws InstanceAlreadyExistsException { + private synchronized void copyExistingModule(final ModuleInternalInfo oldConfigBeanInfo) + throws InstanceAlreadyExistsException { transactionStatus.checkNotCommitStarted(); transactionStatus.checkNotAborted(); @@ -174,7 +203,7 @@ class ConfigTransactionControllerImpl implements try { moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName()); bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); - } catch (InstanceNotFoundException e) { + } catch (final ModuleFactoryNotFoundException e) { throw new IllegalStateException(e); } @@ -185,8 +214,8 @@ class ConfigTransactionControllerImpl implements module = moduleFactory.createModule( moduleIdentifier.getInstanceName(), dependencyResolver, oldConfigBeanInfo.getReadableModule(), bc); - } catch (Exception e) { - throw new IllegalStateException(format( + } catch (final Exception e) { + throw new IllegalStateException(String.format( "Error while copying old configuration from %s to %s", oldConfigBeanInfo, moduleFactory), e); } @@ -195,8 +224,8 @@ class ConfigTransactionControllerImpl implements } @Override - public synchronized ObjectName createModule(String factoryName, - String instanceName) throws InstanceAlreadyExistsException { + public synchronized ObjectName createModule(final String factoryName, final String instanceName) + throws InstanceAlreadyExistsException { transactionStatus.checkNotCommitStarted(); transactionStatus.checkNotAborted(); @@ -204,12 +233,8 @@ class ConfigTransactionControllerImpl implements dependencyResolverManager.assertNotExists(moduleIdentifier); // find factory - ModuleFactory moduleFactory; - try { - moduleFactory = factoriesHolder.findByModuleName(factoryName); - } catch (InstanceNotFoundException e) { - throw new IllegalArgumentException(e); - } + ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName); + DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier); BundleContext bundleContext = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); Module module = moduleFactory.createModule(instanceName, dependencyResolver, @@ -219,24 +244,39 @@ class ConfigTransactionControllerImpl implements moduleFactory, null, dependencyResolver, defaultBean, bundleContext); } + @Override + public synchronized void reCreateModule(final ObjectName objectName) throws InstanceNotFoundException { + transactionStatus.checkNotCommitStarted(); + transactionStatus.checkNotAborted(); + checkTransactionName(objectName); + ObjectNameUtil.checkDomain(objectName); + ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, ObjectNameUtil.TYPE_MODULE); + + ModuleInternalTransactionalInfo txInfo = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier); + Module realModule = txInfo.getRealModule(); + if(realModule instanceof AbstractModule) { + ((AbstractModule)realModule).setCanReuseInstance(false); + } + } + private synchronized ObjectName putConfigBeanToJMXAndInternalMaps( - ModuleIdentifier moduleIdentifier, Module module, - ModuleFactory moduleFactory, - @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, - boolean isDefaultBean, BundleContext bundleContext) + final ModuleIdentifier moduleIdentifier, final Module module, + final ModuleFactory moduleFactory, + @Nullable final ModuleInternalInfo maybeOldConfigBeanInfo, final DependencyResolver dependencyResolver, + final boolean isDefaultBean, final BundleContext bundleContext) throws InstanceAlreadyExistsException { LOG.debug("Adding module {} to transaction {}", moduleIdentifier, this); - if (moduleIdentifier.equals(module.getIdentifier()) == false) { + if (!moduleIdentifier.equals(module.getIdentifier())) { throw new IllegalStateException("Incorrect name reported by module. Expected " + moduleIdentifier + ", got " + module.getIdentifier()); } - if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false) { + if (!dependencyResolver.getIdentifier().equals(moduleIdentifier)) { throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected " + moduleIdentifier + ", got " + dependencyResolver.getIdentifier()); } DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper( - module, moduleIdentifier, getTransactionIdentifier(), + module, moduleIdentifier, getTransactionIdentifier().getName(), readOnlyAtomicBoolean, transactionsMBeanServer, configMBeanServer); @@ -253,7 +293,7 @@ class ConfigTransactionControllerImpl implements } @Override - public synchronized void destroyModule(ObjectName objectName) throws InstanceNotFoundException { + public synchronized void destroyModule(final ObjectName objectName) throws InstanceNotFoundException { checkTransactionName(objectName); ObjectNameUtil.checkDomain(objectName); ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, @@ -261,21 +301,21 @@ class ConfigTransactionControllerImpl implements destroyModule(moduleIdentifier); } - private void checkTransactionName(ObjectName objectName) { + private void checkTransactionName(final ObjectName objectName) { String foundTransactionName = ObjectNameUtil .getTransactionName(objectName); - if (getTransactionIdentifier().getName().equals(foundTransactionName) == false) { + if (!getTransactionIdentifier().getName().equals(foundTransactionName)) { throw new IllegalArgumentException("Wrong transaction name " + objectName); } } - private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) { + private synchronized void destroyModule(final ModuleIdentifier moduleIdentifier) { LOG.debug("Destroying module {} in transaction {}", moduleIdentifier, this); transactionStatus.checkNotAborted(); ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier); - if (blankTransaction == false && + if (!blankTransaction && found.isDefaultBean()) { LOG.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem"); } @@ -284,7 +324,7 @@ class ConfigTransactionControllerImpl implements try { writableSRRegistry.removeServiceReferences( ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier)); - } catch (InstanceNotFoundException e) { + } catch (final InstanceNotFoundException e) { LOG.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry); throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e); } @@ -328,7 +368,7 @@ class ConfigTransactionControllerImpl implements Module module = entry.getValue(); try { module.validate(); - } catch (Exception e) { + } catch (final Exception e) { LOG.warn("Validation exception in {}", getTransactionName(), e); collectedExceptions.add(ValidationException @@ -357,9 +397,10 @@ class ConfigTransactionControllerImpl implements configBeanModificationDisabled.set(true); try { validateNoLocks(); - } catch (ValidationException e) { + } catch (final ValidationException e) { LOG.trace("Commit failed on validation"); - configBeanModificationDisabled.set(false); // recoverable error + // recoverable error + configBeanModificationDisabled.set(false); throw e; } // errors in this state are not recoverable. modules are not mutable @@ -375,7 +416,7 @@ class ConfigTransactionControllerImpl implements public synchronized List secondPhaseCommit() { transactionStatus.checkNotAborted(); transactionStatus.checkCommitStarted(); - if (configBeanModificationDisabled.get() == false) { + if (!configBeanModificationDisabled.get()) { throw new IllegalStateException( "Internal error - validateBeforeCommitAndLockTransaction should be called " + "to obtain a lock"); @@ -383,36 +424,38 @@ class ConfigTransactionControllerImpl implements LOG.trace("Committing transaction {}", getTransactionIdentifier()); - // call getInstance() - for (Entry entry : dependencyResolverManager - .getAllModules().entrySet()) { - Module module = entry.getValue(); - ModuleIdentifier name = entry.getKey(); + Map allModules = dependencyResolverManager.getAllModules(); + + // call getInstance() on all Modules from top to bottom (from source to target of the dependency relation) + // The source of a dependency closes itself and calls getInstance recursively on the dependencies (in case of reconfiguration) + // This makes close() calls from top to bottom while createInstance() calls are performed bottom to top + List sortedModuleIdentifiers = Lists.reverse(dependencyResolverManager.getSortedModuleIdentifiers()); + for (ModuleIdentifier moduleIdentifier : sortedModuleIdentifiers) { + Module module = allModules.get(moduleIdentifier); + try { LOG.debug("About to commit {} in transaction {}", - name, getTransactionIdentifier()); + moduleIdentifier, getTransactionIdentifier()); AutoCloseable instance = module.getInstance(); - checkNotNull(instance, "Instance is null:{} in transaction {}", name, getTransactionIdentifier()); + Preconditions.checkNotNull(instance, "Instance is null:%s in transaction %s", moduleIdentifier, getTransactionIdentifier()); } catch (Exception e) { - LOG.error("Commit failed on {} in transaction {}", name, + LOG.error("Commit failed on {} in transaction {}", moduleIdentifier, getTransactionIdentifier(), e); internalAbort(); throw new IllegalStateException( - format("Error - getInstance() failed for %s in transaction %s", - name, getTransactionIdentifier()), e); + String.format("Error - getInstance() failed for %s in transaction %s", + moduleIdentifier, getTransactionIdentifier()), e); } } - // count dependency order - LOG.trace("Committed configuration {}", getTransactionIdentifier()); transactionStatus.setCommitted(); - return dependencyResolverManager.getSortedModuleIdentifiers(); + return sortedModuleIdentifiers; } @Override - public synchronized void abortConfig() { + public void abortConfig() { transactionStatus.checkNotCommitStarted(); transactionStatus.checkNotAborted(); internalAbort(); @@ -424,6 +467,7 @@ class ConfigTransactionControllerImpl implements close(); } + @Override public void close() { dependencyResolverManager.close(); txLookupRegistry.close(); @@ -451,7 +495,7 @@ class ConfigTransactionControllerImpl implements * {@inheritDoc} */ @Override - public Set lookupConfigBeans(String moduleName) { + public Set lookupConfigBeans(final String moduleName) { return txLookupRegistry.lookupConfigBeans(moduleName); } @@ -459,7 +503,7 @@ class ConfigTransactionControllerImpl implements * {@inheritDoc} */ @Override - public ObjectName lookupConfigBean(String moduleName, String instanceName) + public ObjectName lookupConfigBean(final String moduleName, final String instanceName) throws InstanceNotFoundException { return txLookupRegistry.lookupConfigBean(moduleName, instanceName); } @@ -468,7 +512,7 @@ class ConfigTransactionControllerImpl implements * {@inheritDoc} */ @Override - public Set lookupConfigBeans(String moduleName, String instanceName) { + public Set lookupConfigBeans(final String moduleName, final String instanceName) { return txLookupRegistry.lookupConfigBeans(moduleName, instanceName); } @@ -476,9 +520,28 @@ class ConfigTransactionControllerImpl implements * {@inheritDoc} */ @Override - public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + public void checkConfigBeanExists(final ObjectName objectName) throws InstanceNotFoundException { txLookupRegistry.checkConfigBeanExists(objectName); } + + + /** + * {@inheritDoc} + */ + @Override + public Set lookupRuntimeBeans() { + return txLookupRegistry.lookupRuntimeBeans(); + } + + /** + * {@inheritDoc} + */ + @Override + public Set lookupRuntimeBeans(final String moduleName, + final String instanceName) { + return txLookupRegistry.lookupRuntimeBeans(moduleName, instanceName); + } + // -- /** @@ -523,7 +586,7 @@ class ConfigTransactionControllerImpl implements } @Override - public BundleContext getModuleFactoryBundleContext(String factoryName) { + public BundleContext getModuleFactoryBundleContext(final String factoryName) { Map.Entry factoryBundleContextEntry = this.currentlyRegisteredFactories.get(factoryName); if (factoryBundleContextEntry == null || factoryBundleContextEntry.getValue() == null) { throw new NullPointerException("Bundle context of " + factoryName + " ModuleFactory not found."); @@ -535,7 +598,7 @@ class ConfigTransactionControllerImpl implements @Override - public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) { + public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(final String serviceInterfaceQName, final String refName) { return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName); } @@ -545,27 +608,27 @@ class ConfigTransactionControllerImpl implements } @Override - public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) { + public synchronized Map lookupServiceReferencesByServiceInterfaceName(final String serviceInterfaceQName) { return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName); } @Override - public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + public synchronized Set lookupServiceInterfaceNames(final ObjectName objectName) throws InstanceNotFoundException { return writableSRRegistry.lookupServiceInterfaceNames(objectName); } @Override - public synchronized String getServiceInterfaceName(String namespace, String localName) { + public synchronized String getServiceInterfaceName(final String namespace, final String localName) { return writableSRRegistry.getServiceInterfaceName(namespace, localName); } @Override - public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException { + public synchronized ObjectName saveServiceReference(final String serviceInterfaceName, final String refName, final ObjectName moduleON) throws InstanceNotFoundException { return writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, moduleON); } @Override - public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException { + public synchronized void removeServiceReference(final String serviceInterfaceName, final String refName) throws InstanceNotFoundException { writableSRRegistry.removeServiceReference(serviceInterfaceName, refName); } @@ -575,7 +638,7 @@ class ConfigTransactionControllerImpl implements } @Override - public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + public boolean removeServiceReferences(final ObjectName objectName) throws InstanceNotFoundException { return writableSRRegistry.removeServiceReferences(objectName); } @@ -595,12 +658,12 @@ class ConfigTransactionControllerImpl implements } @Override - public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException { + public void checkServiceReferenceExists(final ObjectName objectName) throws InstanceNotFoundException { writableSRRegistry.checkServiceReferenceExists(objectName); } @Override - public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException { + public ObjectName getServiceReference(final String serviceInterfaceQName, final String refName) throws InstanceNotFoundException { return writableSRRegistry.getServiceReference(serviceInterfaceQName, refName); } }