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=17ce0781546e231a5f81b2a8ca1b276f5a046d74;hp=ce0ca0312fac45d6f8834ece967b3e7a85bbdfaa;hb=d7c85bd358cf443737a1b272a78c5e46d66d8270;hpb=d105455084f43d9423b7c0e6af785302e6a3ea93 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 ce0ca0312f..17ce078154 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 @@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl; import org.opendaylight.controller.config.api.DependencyResolver; import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry; import org.opendaylight.controller.config.api.ValidationException; import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.config.manager.impl.dependencyresolver.DependencyResolverManager; @@ -16,10 +17,8 @@ import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWrita import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean; import org.opendaylight.controller.config.manager.impl.dynamicmbean.ReadOnlyAtomicBoolean.ReadOnlyAtomicBooleanImpl; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HierarchicalConfigMBeanFactoriesHolder; -import org.opendaylight.controller.config.manager.impl.jmx.TransactionJMXRegistrator; 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.util.LookupBeansUtil; import org.opendaylight.controller.config.spi.Module; import org.opendaylight.controller.config.spi.ModuleFactory; import org.opendaylight.yangtools.concepts.Identifiable; @@ -38,6 +37,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -46,7 +46,7 @@ import static java.lang.String.format; /** * This is a JMX bean representing current transaction. It contains - * {@link #transactionIdentifier}, unique version and parent version for + * transaction identifier, unique version and parent version for * optimistic locking. */ class ConfigTransactionControllerImpl implements @@ -55,16 +55,15 @@ class ConfigTransactionControllerImpl implements Identifiable{ private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class); - private final TransactionIdentifier transactionIdentifier; + private final ConfigTransactionLookupRegistry txLookupRegistry; private final ObjectName controllerON; - private final TransactionJMXRegistrator transactionRegistrator; - private final TransactionModuleJMXRegistrator txModuleJMXRegistrator; + private final long parentVersion, currentVersion; private final HierarchicalConfigMBeanFactoriesHolder factoriesHolder; private final DependencyResolverManager dependencyResolverManager; private final TransactionStatus transactionStatus; private final MBeanServer transactionsMBeanServer; - private final List currentlyRegisteredFactories; + private final Map> currentlyRegisteredFactories; /** * Disables ability of {@link DynamicWritableWrapper} to change attributes @@ -77,20 +76,20 @@ class ConfigTransactionControllerImpl implements configBeanModificationDisabled); private final MBeanServer configMBeanServer; - private final BundleContext bundleContext; + private final boolean blankTransaction; + + @GuardedBy("this") + private final ServiceReferenceWritableRegistry writableSRRegistry; - public ConfigTransactionControllerImpl(String transactionName, - TransactionJMXRegistrator transactionRegistrator, + public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry, long parentVersion, long currentVersion, - List currentlyRegisteredFactories, - MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, BundleContext bundleContext) { - - this.transactionIdentifier = new TransactionIdentifier(transactionName); - this.controllerON = ObjectNameUtil - .createTransactionControllerON(transactionName); - this.transactionRegistrator = transactionRegistrator; - txModuleJMXRegistrator = transactionRegistrator - .createTransactionModuleJMXRegistrator(); + Map> currentlyRegisteredFactories, + MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, + boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) { + + this.txLookupRegistry = txLookupRegistry; + String transactionName = txLookupRegistry.getTransactionIdentifier().getName(); + this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName); this.parentVersion = parentVersion; this.currentVersion = currentVersion; this.currentlyRegisteredFactories = currentlyRegisteredFactories; @@ -99,7 +98,8 @@ class ConfigTransactionControllerImpl implements this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus); this.transactionsMBeanServer = transactionsMBeanServer; this.configMBeanServer = configMBeanServer; - this.bundleContext = bundleContext; + this.blankTransaction = blankTransaction; + this.writableSRRegistry = writableSRRegistry; } @Override @@ -120,11 +120,11 @@ class ConfigTransactionControllerImpl implements transactionStatus.checkNotAborted(); Set oldSet = new HashSet<>(lastListOfFactories); - Set newSet = new HashSet<>(currentlyRegisteredFactories); + Set newSet = new HashSet<>(factoriesHolder.getModuleFactories()); List toBeAdded = new ArrayList<>(); List toBeRemoved = new ArrayList<>(); - for(ModuleFactory moduleFactory: currentlyRegisteredFactories) { + for(ModuleFactory moduleFactory: factoriesHolder.getModuleFactories()) { if (oldSet.contains(moduleFactory) == false){ toBeAdded.add(moduleFactory); } @@ -136,10 +136,14 @@ class ConfigTransactionControllerImpl implements } // add default modules for (ModuleFactory moduleFactory : toBeAdded) { - Set defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext); + Set defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, + getModuleFactoryBundleContext(moduleFactory.getImplementationName())); 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()); try { - putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null); + boolean defaultBean = true; + putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean); } catch (InstanceAlreadyExistsException e) { throw new IllegalStateException(e); } @@ -171,15 +175,17 @@ class ConfigTransactionControllerImpl implements DependencyResolver dependencyResolver = dependencyResolverManager .getOrCreate(moduleIdentifier); try { + BundleContext bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName()); module = moduleFactory.createModule( moduleIdentifier.getInstanceName(), dependencyResolver, - oldConfigBeanInfo.getReadableModule(), bundleContext); + oldConfigBeanInfo.getReadableModule(), bc); } catch (Exception e) { throw new IllegalStateException(format( "Error while copying old configuration from %s to %s", oldConfigBeanInfo, moduleFactory), e); } - putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo); + putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver, + oldConfigBeanInfo.isDefaultBean()); } @Override @@ -194,57 +200,84 @@ class ConfigTransactionControllerImpl implements // find factory ModuleFactory moduleFactory = factoriesHolder.findByModuleName(factoryName); DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier); - Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext); + Module module = moduleFactory.createModule(instanceName, dependencyResolver, + getModuleFactoryBundleContext(moduleFactory.getImplementationName())); + boolean defaultBean = false; return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, - moduleFactory, null); + moduleFactory, null, dependencyResolver, defaultBean); } private synchronized ObjectName putConfigBeanToJMXAndInternalMaps( ModuleIdentifier moduleIdentifier, Module module, ModuleFactory moduleFactory, - @Nullable ModuleInternalInfo maybeOldConfigBeanInfo) + @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, boolean isDefaultBean) throws InstanceAlreadyExistsException { + logger.debug("Adding module {} to transaction {}", moduleIdentifier, this); if (moduleIdentifier.equals(module.getIdentifier())==false) { throw new IllegalStateException("Incorrect name reported by module. Expected " + moduleIdentifier + ", got " + module.getIdentifier()); } + if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) { + throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected " + + moduleIdentifier + ", got " + dependencyResolver.getIdentifier()); + } DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper( - module, moduleIdentifier, transactionIdentifier, + module, moduleIdentifier, getTransactionIdentifier(), readOnlyAtomicBoolean, transactionsMBeanServer, configMBeanServer); ObjectName writableON = ObjectNameUtil.createTransactionModuleON( - transactionIdentifier.getName(), moduleIdentifier); + getTransactionIdentifier().getName(), moduleIdentifier); // put wrapper to jmx - TransactionModuleJMXRegistration transactionModuleJMXRegistration = txModuleJMXRegistrator + TransactionModuleJMXRegistration transactionModuleJMXRegistration = getTxModuleJMXRegistrator() .registerMBean(writableDynamicWrapper, writableON); ModuleInternalTransactionalInfo moduleInternalTransactionalInfo = new ModuleInternalTransactionalInfo( moduleIdentifier, module, moduleFactory, - maybeOldConfigBeanInfo, transactionModuleJMXRegistration); + maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean); dependencyResolverManager.put(moduleInternalTransactionalInfo); return writableON; } @Override - public void destroyModule(ObjectName objectName) - throws InstanceNotFoundException { + public synchronized void destroyModule(ObjectName objectName) throws InstanceNotFoundException { + checkTransactionName(objectName); + ObjectNameUtil.checkDomain(objectName); + ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, + ObjectNameUtil.TYPE_MODULE); + destroyModule(moduleIdentifier); + } + + private void checkTransactionName(ObjectName objectName) { String foundTransactionName = ObjectNameUtil .getTransactionName(objectName); - if (transactionIdentifier.getName().equals(foundTransactionName) == false) { + if (getTransactionIdentifier().getName().equals(foundTransactionName) == false) { throw new IllegalArgumentException("Wrong transaction name " + objectName); } - ObjectNameUtil.checkDomain(objectName); - ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(objectName, - ObjectNameUtil.TYPE_MODULE); - destroyModule(moduleIdentifier); } - private void destroyModule(ModuleIdentifier moduleIdentifier) { + private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) { logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this); transactionStatus.checkNotAborted(); + + if (blankTransaction == false) { + ModuleInternalTransactionalInfo found = + dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier); + if (found.isDefaultBean()) { + logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem"); + } + } + // first remove refNames, it checks for objectname existence + try { + writableSRRegistry.removeServiceReferences( + ObjectNameUtil.createTransactionModuleON(getTransactionName(),moduleIdentifier)); + } catch (InstanceNotFoundException e) { + logger.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry); + throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e); + } + ModuleInternalTransactionalInfo removedTInfo = dependencyResolverManager.destroyModule(moduleIdentifier); // remove from jmx removedTInfo.getTransactionModuleJMXRegistration().close(); @@ -274,7 +307,7 @@ class ConfigTransactionControllerImpl implements private void validate_noLocks() throws ValidationException { transactionStatus.checkNotAborted(); - logger.info("Validating transaction {}", transactionIdentifier); + logger.info("Validating transaction {}", getTransactionIdentifier()); // call validate() List collectedExceptions = new ArrayList<>(); for (Entry entry : dependencyResolverManager @@ -294,7 +327,7 @@ class ConfigTransactionControllerImpl implements throw ValidationException .createFromCollectedValidationExceptions(collectedExceptions); } - logger.info("Validated transaction {}", transactionIdentifier); + logger.info("Validated transaction {}", getTransactionIdentifier()); } /** @@ -336,7 +369,7 @@ class ConfigTransactionControllerImpl implements + "to obtain a lock"); } - logger.info("Committing transaction {}", transactionIdentifier); + logger.info("Committing transaction {}", getTransactionIdentifier()); // call getInstance() for (Entry entry : dependencyResolverManager @@ -345,21 +378,21 @@ class ConfigTransactionControllerImpl implements ModuleIdentifier name = entry.getKey(); try { logger.debug("About to commit {} in transaction {}", - name, transactionIdentifier); + name, getTransactionIdentifier()); module.getInstance(); } catch (Exception e) { logger.error("Commit failed on {} in transaction {}", name, - transactionIdentifier, e); + getTransactionIdentifier(), e); internalAbort(); throw new RuntimeException( format("Error - getInstance() failed for %s in transaction %s", - name, transactionIdentifier), e); + name, getTransactionIdentifier()), e); } } // count dependency order - logger.info("Committed configuration {}", transactionIdentifier); + logger.info("Committed configuration {}", getTransactionIdentifier()); transactionStatus.setCommitted(); // unregister this and all modules from jmx close(); @@ -380,7 +413,8 @@ class ConfigTransactionControllerImpl implements } private void close() { - transactionRegistrator.close(); + //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps + txLookupRegistry.close(); } @Override @@ -390,7 +424,7 @@ class ConfigTransactionControllerImpl implements @Override public String getTransactionName() { - return transactionIdentifier.getName(); + return getTransactionIdentifier().getName(); } /** @@ -398,7 +432,7 @@ class ConfigTransactionControllerImpl implements */ @Override public Set lookupConfigBeans() { - return lookupConfigBeans("*", "*"); + return txLookupRegistry.lookupConfigBeans(); } /** @@ -406,7 +440,7 @@ class ConfigTransactionControllerImpl implements */ @Override public Set lookupConfigBeans(String moduleName) { - return lookupConfigBeans(moduleName, "*"); + return txLookupRegistry.lookupConfigBeans(moduleName); } /** @@ -415,20 +449,29 @@ class ConfigTransactionControllerImpl implements @Override public ObjectName lookupConfigBean(String moduleName, String instanceName) throws InstanceNotFoundException { - return LookupBeansUtil.lookupConfigBean(this, moduleName, instanceName); + return txLookupRegistry.lookupConfigBean(moduleName, instanceName); + } + + /** + * {@inheritDoc} + */ + @Override + public Set lookupConfigBeans(String moduleName, String instanceName) { + return txLookupRegistry.lookupConfigBeans(moduleName, instanceName); } /** * {@inheritDoc} */ @Override - public Set lookupConfigBeans(String moduleName, - String instanceName) { - ObjectName namePattern = ObjectNameUtil.createModulePattern(moduleName, - instanceName, transactionIdentifier.getName()); - return txModuleJMXRegistrator.queryNames(namePattern, null); + public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException { + txLookupRegistry.checkConfigBeanExists(objectName); } + // -- + /** + * {@inheritDoc} + */ @Override public Set getAvailableModuleNames() { return factoriesHolder.getModuleNames(); @@ -450,20 +493,92 @@ class ConfigTransactionControllerImpl implements // @VisibleForTesting TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() { - return txModuleJMXRegistrator; + return txLookupRegistry.getTxModuleJMXRegistrator(); } public TransactionIdentifier getName() { - return transactionIdentifier; + return getTransactionIdentifier(); } @Override public List getCurrentlyRegisteredFactories() { - return currentlyRegisteredFactories; + return new ArrayList<>(factoriesHolder.getModuleFactories()); } @Override public TransactionIdentifier getIdentifier() { - return transactionIdentifier; + return getTransactionIdentifier(); + } + + @Override + public BundleContext getModuleFactoryBundleContext(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."); + } + return factoryBundleContextEntry.getValue(); + } + + // service reference functionality: + + + @Override + public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) { + return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName); + } + + @Override + public synchronized Map> getServiceMapping() { + return writableSRRegistry.getServiceMapping(); + } + + @Override + public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + } + + @Override + public synchronized Set lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + return writableSRRegistry.lookupServiceInterfaceNames(objectName); + } + + @Override + public synchronized String getServiceInterfaceName(String namespace, String localName) { + return writableSRRegistry.getServiceInterfaceName(namespace, localName); + } + + @Override + public synchronized void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException { + writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, objectName); } + + @Override + public synchronized boolean removeServiceReference(String serviceInterfaceName, String refName) { + return writableSRRegistry.removeServiceReference(serviceInterfaceName, refName); + } + + @Override + public synchronized void removeAllServiceReferences() { + writableSRRegistry.removeAllServiceReferences(); + } + + @Override + public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException { + return writableSRRegistry.removeServiceReferences(objectName); + } + + @Override + public ServiceReferenceWritableRegistry getWritableRegistry() { + return writableSRRegistry; + } + + public TransactionIdentifier getTransactionIdentifier() { + return txLookupRegistry.getTransactionIdentifier(); + } + + @Override + public Set getAvailableModuleFactoryQNames() { + return txLookupRegistry.getAvailableModuleFactoryQNames(); + } + }