X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fconfig%2Fconfig-manager%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fconfig%2Fmanager%2Fimpl%2FConfigRegistryImpl.java;h=18326d91f21b8df58afd905746b2efc606ebb1ce;hb=404d4fc52adf17bad6b53aaeedf59d1db85780bc;hp=97d57a459199e2bf0ee9912f64b6c505b0f395ca;hpb=9fb64948564e252018f9b1e13e7cea2c92f991aa;p=controller.git diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java index 97d57a4591..18326d91f2 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java @@ -7,32 +7,13 @@ */ package org.opendaylight.controller.config.manager.impl; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.NotThreadSafe; -import javax.annotation.concurrent.ThreadSafe; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; - import org.opendaylight.controller.config.api.ConflictingVersionException; 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.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.CommitStatus; -import org.opendaylight.controller.config.api.jmx.ConfigRegistryMXBean; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicReadableWrapper; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder; @@ -45,22 +26,44 @@ import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceMan import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration; import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil; import org.opendaylight.controller.config.spi.Module; +import org.opendaylight.controller.config.spi.ModuleFactory; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.NotThreadSafe; +import javax.annotation.concurrent.ThreadSafe; +import javax.management.InstanceAlreadyExistsException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + /** * Singleton that is responsible for creating and committing Config * Transactions. It is registered in Platform MBean Server. */ @ThreadSafe -public class ConfigRegistryImpl implements AutoCloseable, - ConfigRegistryImplMXBean { - private static final Logger logger = LoggerFactory - .getLogger(ConfigRegistryImpl.class); +public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBean { + private static final Logger logger = LoggerFactory.getLogger(ConfigRegistryImpl.class); private final ModuleFactoriesResolver resolver; private final MBeanServer configMBeanServer; + + @GuardedBy("this") + private final BundleContext bundleContext; + @GuardedBy("this") private long version = 0; @GuardedBy("this") @@ -98,6 +101,12 @@ public class ConfigRegistryImpl implements AutoCloseable, // internal jmx server shared by all transactions private final MBeanServer transactionsMBeanServer; + @GuardedBy("this") + private List lastListOfFactories = Collections.emptyList(); + + @GuardedBy("this") // switched in every 2ndPC + private ServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry(); + // constructor public ConfigRegistryImpl(ModuleFactoriesResolver resolver, BundleContext bundleContext, MBeanServer configMBeanServer) { @@ -110,8 +119,8 @@ public class ConfigRegistryImpl implements AutoCloseable, BundleContext bundleContext, MBeanServer configMBeanServer, BaseJMXRegistrator baseJMXRegistrator) { this.resolver = resolver; - this.beanToOsgiServiceManager = new BeanToOsgiServiceManager( - bundleContext); + this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(); + this.bundleContext = bundleContext; this.configMBeanServer = configMBeanServer; this.baseJMXRegistrator = baseJMXRegistrator; this.registryMBeanServer = MBeanServerFactory @@ -125,35 +134,45 @@ public class ConfigRegistryImpl implements AutoCloseable, */ @Override public synchronized ObjectName beginConfig() { - return beginConfigInternal().getControllerObjectName(); + return beginConfig(false); } - private synchronized ConfigTransactionControllerInternal beginConfigInternal() { + /** + * @param blankTransaction true if this transaction is created automatically by + * org.opendaylight.controller.config.manager.impl.osgi.BlankTransactionServiceTracker + */ + public synchronized ObjectName beginConfig(boolean blankTransaction) { + return beginConfigInternal(blankTransaction).getControllerObjectName(); + } + + private synchronized ConfigTransactionControllerInternal beginConfigInternal(boolean blankTransaction) { versionCounter++; - String transactionName = "ConfigTransaction-" + version + "-" - + versionCounter; - TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator - .createTransactionJMXRegistrator(transactionName); + final String transactionName = "ConfigTransaction-" + version + "-" + versionCounter; + + TransactionJMXRegistratorFactory factory = new TransactionJMXRegistratorFactory() { + @Override + public TransactionJMXRegistrator create() { + return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName); + } + }; + + ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier( + transactionName), factory); + Map> allCurrentFactories = Collections.unmodifiableMap( + resolver.getAllFactories()); + ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry( + readableSRRegistry, txLookupRegistry, allCurrentFactories); + ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl( - transactionName, transactionRegistrator, version, - versionCounter, resolver.getAllFactories(), - transactionsMBeanServer, configMBeanServer); + txLookupRegistry, version, + versionCounter, allCurrentFactories, transactionsMBeanServer, + configMBeanServer, blankTransaction, writableRegistry); try { - transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName - ()); + txLookupRegistry.registerMBean(transactionController, transactionController.getControllerObjectName()); } catch (InstanceAlreadyExistsException e) { throw new IllegalStateException(e); } - - // copy old configuration to this server - for (ModuleInternalInfo oldConfigInfo : currentConfig.getEntries()) { - try { - transactionController.copyExistingModule(oldConfigInfo); - } catch (InstanceAlreadyExistsException e) { - throw new IllegalStateException("Error while copying " - + oldConfigInfo, e); - } - } + transactionController.copyExistingModulesAndProcessFactoryDiff(currentConfig.getEntries(), lastListOfFactories); transactionsHolder.add(transactionName, transactionController); return transactionController; } @@ -162,20 +181,15 @@ public class ConfigRegistryImpl implements AutoCloseable, * {@inheritDoc} */ @Override - public synchronized CommitStatus commitConfig( - ObjectName transactionControllerON) + public synchronized CommitStatus commitConfig(ObjectName transactionControllerON) throws ConflictingVersionException, ValidationException { final String transactionName = ObjectNameUtil .getTransactionName(transactionControllerON); - logger.info( - "About to commit {}. Current parentVersion: {}, versionCounter {}", - transactionName, version, versionCounter); + logger.info("About to commit {}. Current parentVersion: {}, versionCounter {}", transactionName, version, versionCounter); // find ConfigTransactionController - Map transactions = transactionsHolder - .getCurrentTransactions(); - ConfigTransactionControllerInternal configTransactionController = transactions - .get(transactionName); + Map transactions = transactionsHolder.getCurrentTransactions(); + ConfigTransactionControllerInternal configTransactionController = transactions.get(transactionName); if (configTransactionController == null) { throw new IllegalArgumentException(String.format( "Transaction with name '%s' not found", transactionName)); @@ -190,33 +204,28 @@ public class ConfigRegistryImpl implements AutoCloseable, } // optimistic lock ok - CommitInfo commitInfo = configTransactionController - .validateBeforeCommitAndLockTransaction(); - final ConfigRegistryImpl a = this; + CommitInfo commitInfo = configTransactionController.validateBeforeCommitAndLockTransaction(); + lastListOfFactories = Collections.unmodifiableList(configTransactionController.getCurrentlyRegisteredFactories()); // non recoverable from here: try { - final CommitStatus secondPhaseCommitStatus = secondPhaseCommit( + return secondPhaseCommit( configTransactionController, commitInfo); - - return secondPhaseCommitStatus; } catch (Throwable t) { // some libs throw Errors: e.g. // javax.xml.ws.spi.FactoryFinder$ConfigurationError isHealthy = false; - logger.error( - "Configuration Transaction failed on 2PC, server is unhealthy", - t); - if (t instanceof RuntimeException) + logger.error("Configuration Transaction failed on 2PC, server is unhealthy", t); + if (t instanceof RuntimeException) { throw (RuntimeException) t; - else if (t instanceof Error) + } else if (t instanceof Error) { throw (Error) t; - else + } else { throw new RuntimeException(t); + } } } - private CommitStatus secondPhaseCommit( - ConfigTransactionControllerInternal configTransactionController, - CommitInfo commitInfo) { + private CommitStatus secondPhaseCommit(ConfigTransactionControllerInternal configTransactionController, + CommitInfo commitInfo) { // close instances which were destroyed by the user, including // (hopefully) runtime beans @@ -226,7 +235,7 @@ public class ConfigRegistryImpl implements AutoCloseable, // runtime jmx registrator), // also closes osgi registration and ModuleJMXRegistrator // registration - currentConfig.remove(toBeDestroyed.getName()); + currentConfig.remove(toBeDestroyed.getIdentifier()); } // set RuntimeBeanRegistrators on beans implementing @@ -238,7 +247,7 @@ public class ConfigRegistryImpl implements AutoCloseable, RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator; if (entry.hasOldModule() == false) { runtimeBeanRegistrator = baseJMXRegistrator - .createRuntimeBeanRegistrator(entry.getName()); + .createRuntimeBeanRegistrator(entry.getIdentifier()); } else { // reuse old JMX registrator runtimeBeanRegistrator = entry.getOldInternalInfo() @@ -251,7 +260,7 @@ public class ConfigRegistryImpl implements AutoCloseable, .setRuntimeBeanRegistrator(runtimeBeanRegistrator); } // save it to info so it is accessible afterwards - runtimeRegistrators.put(entry.getName(), runtimeBeanRegistrator); + runtimeRegistrators.put(entry.getIdentifier(), runtimeBeanRegistrator); } // can register runtime beans @@ -279,8 +288,7 @@ public class ConfigRegistryImpl implements AutoCloseable, // determine if current instance was recreated or reused or is new // rules for closing resources: - // osgi registration - will be (re)created every time, so it needs - // to be closed here + // osgi registration - will be reused if possible. // module jmx registration - will be (re)created every time, needs // to be closed here // runtime jmx registration - should be taken care of by module @@ -289,26 +297,29 @@ public class ConfigRegistryImpl implements AutoCloseable, ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator .createModuleJMXRegistrator(); + OsgiRegistration osgiRegistration = null; if (entry.hasOldModule()) { ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo(); DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo .getReadableModule(); - currentConfig.remove(entry.getName()); + currentConfig.remove(entry.getIdentifier()); // test if old instance == new instance - if (oldReadableConfigBean.getInstance().equals( - module.getInstance())) { + if (oldReadableConfigBean.getInstance().equals(module.getInstance())) { // reused old instance: // wrap in readable dynamic mbean reusedInstances.add(primaryReadOnlyON); + osgiRegistration = oldInternalInfo.getOsgiRegistration(); } else { // recreated instance: // it is responsibility of module to call the old instance - // we just need to unregister configbean recreatedInstances.add(primaryReadOnlyON); + + // close old osgi registration + oldInternalInfo.getOsgiRegistration().close(); } - // close old osgi registration in any case - oldInternalInfo.getOsgiRegistration().close(); + // close old module jmx registrator oldInternalInfo.getModuleJMXRegistrator().close(); } else { @@ -330,17 +341,25 @@ public class ConfigRegistryImpl implements AutoCloseable, } // register to OSGi - OsgiRegistration osgiRegistration = beanToOsgiServiceManager - .registerToOsgi(module.getClass(), - newReadableConfigBean.getInstance(), - entry.getName()); + if (osgiRegistration == null) { + ModuleFactory moduleFactory = entry.getModuleFactory(); + if(moduleFactory != null) { + BundleContext bc = configTransactionController. + getModuleFactoryBundleContext(moduleFactory.getImplementationName()); + osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(), + newReadableConfigBean.getInstance(), entry.getIdentifier(), bc); + } else { + throw new NullPointerException(entry.getIdentifier().getFactoryName() + " ModuleFactory not found."); + } + + } RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators - .get(entry.getName()); + .get(entry.getIdentifier()); ModuleInternalInfo newInfo = new ModuleInternalInfo( - entry.getName(), newReadableConfigBean, osgiRegistration, + entry.getIdentifier(), newReadableConfigBean, osgiRegistration, runtimeBeanRegistrator, newModuleJMXRegistrator, - orderingIdx); + orderingIdx, entry.isDefaultBean()); newConfigEntries.put(module, newInfo); orderingIdx++; @@ -349,6 +368,10 @@ public class ConfigRegistryImpl implements AutoCloseable, // update version version = configTransactionController.getVersion(); + + // switch readable Service Reference Registry + this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(configTransactionController.getWritableRegistry(), this); + return new CommitStatus(newInstances, reusedInstances, recreatedInstances); } @@ -371,7 +394,7 @@ public class ConfigRegistryImpl implements AutoCloseable, /** * Abort open transactions and unregister read only modules. Since this * class is not responsible for registering itself under - * {@link ConfigRegistryMXBean#OBJECT_NAME}, it will not unregister itself + * {@link org.opendaylight.controller.config.api.ConfigRegistry#OBJECT_NAME}, it will not unregister itself * here. */ @Override @@ -490,6 +513,43 @@ public class ConfigRegistryImpl implements AutoCloseable, return baseJMXRegistrator.queryNames(namePattern, null); } + @Override + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + ObjectNameUtil.checkDomain(objectName); + ObjectNameUtil.checkType(objectName, ObjectNameUtil.TYPE_MODULE); + String transactionName = ObjectNameUtil.getTransactionName(objectName); + if (transactionName != null) { + throw new IllegalArgumentException("Transaction attribute not supported in registry, wrong ObjectName: " + objectName); + } + // make sure exactly one match is found: + LookupBeansUtil.lookupConfigBean(this, ObjectNameUtil.getFactoryName(objectName), ObjectNameUtil.getInstanceName(objectName)); + } + + // service reference functionality: + @Override + public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public synchronized Map> getServiceMapping() { + return readableSRRegistry.getServiceMapping(); + } + + @Override + public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return readableSRRegistry.lookupServiceInterfaceNames(objectName); + } + + @Override + public synchronized String getServiceInterfaceName(String namespace, String localName) { + return readableSRRegistry.getServiceInterfaceName(namespace, localName); + } } /**