*/
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.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
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;
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.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;
-
-import static com.google.common.base.Preconditions.checkNotNull;
/**
* This is a JMX bean representing current transaction. It contains
* transaction identifier, unique version and parent version for
ConfigTransactionControllerInternal,
ConfigTransactionControllerImplMXBean,
Identifiable<TransactionIdentifier> {
- private static final Logger logger = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigTransactionControllerImpl.class);
private final ConfigTransactionLookupRegistry txLookupRegistry;
private final ObjectName controllerON;
private final SearchableServiceReferenceWritableRegistry writableSRRegistry;
public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
- long parentVersion, CodecRegistry codecRegistry, long currentVersion,
+ long parentVersion, BindingContextProvider bindingContextProvider, long currentVersion,
Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
boolean blankTransaction, SearchableServiceReferenceWritableRegistry writableSRRegistry) {
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
- transactionStatus, writableSRRegistry, codecRegistry);
+ transactionStatus, writableSRRegistry, bindingContextProvider, transactionsMBeanServer);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
this.blankTransaction = blankTransaction;
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) {
throw new IllegalStateException(e);
}
+
+ // register default module as every possible service
+ final Set<ServiceInterfaceAnnotation> serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory);
+ for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) {
+ try {
+ saveServiceReference(qname, module.getIdentifier().getInstanceName(), objectName);
+ } catch (InstanceNotFoundException e) {
+ throw new IllegalStateException("Unable to register default module instance " + module + " as a service of " + qname, e);
+ }
+ }
}
}
for (ModuleFactory removedFactory : toBeRemoved) {
List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
for (ModuleIdentifier name : modulesOfRemovedFactory) {
+ // remove service refs
+ final ModuleFactory moduleFactory = dependencyResolverManager.findModuleInternalTransactionalInfo(name).getModuleFactory();
+ final Set<ServiceInterfaceAnnotation> serviceInterfaceAnnotations = InterfacesHelper.getServiceInterfaceAnnotations(moduleFactory);
+ for (String qname : InterfacesHelper.getQNames(serviceInterfaceAnnotations)) {
+ try {
+ removeServiceReference(qname, name.getInstanceName());
+ } catch (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(ModuleInternalInfo oldConfigBeanInfo)
+ throws InstanceAlreadyExistsException {
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
try {
moduleFactory = factoriesHolder.findByModuleName(moduleIdentifier.getFactoryName());
bc = getModuleFactoryBundleContext(moduleFactory.getImplementationName());
- } catch (InstanceNotFoundException e) {
+ } catch (ModuleFactoryNotFoundException e) {
throw new IllegalStateException(e);
}
}
@Override
- public synchronized ObjectName createModule(String factoryName,
- String instanceName) throws InstanceAlreadyExistsException {
+ public synchronized ObjectName createModule(String factoryName, String instanceName)
+ throws InstanceAlreadyExistsException {
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
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,
boolean isDefaultBean, BundleContext bundleContext)
throws InstanceAlreadyExistsException {
- logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
+ LOG.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());
}
private synchronized void destroyModule(ModuleIdentifier moduleIdentifier) {
- logger.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
+ LOG.debug("Destroying module {} in transaction {}", moduleIdentifier, this);
transactionStatus.checkNotAborted();
ModuleInternalTransactionalInfo found = dependencyResolverManager.findModuleInternalTransactionalInfo(moduleIdentifier);
- if (blankTransaction == false) {
-
- if (found.isDefaultBean()) {
- logger.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
- }
+ if (blankTransaction == false &&
+ found.isDefaultBean()) {
+ LOG.warn("Warning: removing default bean. This will be forbidden in next version of config-subsystem");
}
// first remove refNames, it checks for objectname existence
writableSRRegistry.removeServiceReferences(
ObjectNameUtil.createTransactionModuleON(getTransactionName(), moduleIdentifier));
} catch (InstanceNotFoundException e) {
- logger.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry);
+ LOG.error("Possible code error: cannot find {} in {}", moduleIdentifier, writableSRRegistry);
throw new IllegalStateException("Possible code error: cannot find " + moduleIdentifier, e);
}
}
configBeanModificationDisabled.set(true);
try {
- validate_noLocks();
+ validateNoLocks();
} finally {
configBeanModificationDisabled.set(false);
}
}
- private void validate_noLocks() throws ValidationException {
+ private void validateNoLocks() throws ValidationException {
transactionStatus.checkNotAborted();
- logger.trace("Validating transaction {}", getTransactionIdentifier());
+ LOG.trace("Validating transaction {}", getTransactionIdentifier());
// call validate()
List<ValidationException> collectedExceptions = new ArrayList<>();
for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
try {
module.validate();
} catch (Exception e) {
- logger.warn("Validation exception in {}", getTransactionName(),
+ LOG.warn("Validation exception in {}", getTransactionName(),
e);
collectedExceptions.add(ValidationException
.createForSingleException(name, e));
}
}
- if (collectedExceptions.size() > 0) {
+ if (!collectedExceptions.isEmpty()) {
throw ValidationException
.createFromCollectedValidationExceptions(collectedExceptions);
}
- logger.trace("Validated transaction {}", getTransactionIdentifier());
+ LOG.trace("Validated transaction {}", getTransactionIdentifier());
}
/**
transactionStatus.checkNotCommitStarted();
configBeanModificationDisabled.set(true);
try {
- validate_noLocks();
+ validateNoLocks();
} catch (ValidationException e) {
- logger.trace("Commit failed on validation");
+ LOG.trace("Commit failed on validation");
configBeanModificationDisabled.set(false); // recoverable error
throw e;
}
+ "to obtain a lock");
}
- logger.trace("Committing transaction {}", getTransactionIdentifier());
+ LOG.trace("Committing transaction {}", getTransactionIdentifier());
+
+ Map<ModuleIdentifier, Module> 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<ModuleIdentifier> sortedModuleIdentifiers = Lists.reverse(dependencyResolverManager.getSortedModuleIdentifiers());
+ for (ModuleIdentifier moduleIdentifier : sortedModuleIdentifiers) {
+ Module module = allModules.get(moduleIdentifier);
- // call getInstance()
- for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
- .getAllModules().entrySet()) {
- Module module = entry.getValue();
- ModuleIdentifier name = entry.getKey();
try {
- logger.debug("About to commit {} in transaction {}",
- name, getTransactionIdentifier());
+ LOG.debug("About to commit {} in transaction {}",
+ moduleIdentifier, getTransactionIdentifier());
AutoCloseable instance = module.getInstance();
- checkNotNull(instance, "Instance is null:{} in transaction {}", name, getTransactionIdentifier());
+ checkNotNull(instance, "Instance is null:{} in transaction {}", moduleIdentifier, getTransactionIdentifier());
} catch (Exception e) {
- logger.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);
+ moduleIdentifier, getTransactionIdentifier()), e);
}
}
- // count dependency order
-
- logger.trace("Committed configuration {}", getTransactionIdentifier());
+ LOG.trace("Committed configuration {}", getTransactionIdentifier());
transactionStatus.setCommitted();
- return dependencyResolverManager.getSortedModuleIdentifiers();
+ return sortedModuleIdentifiers;
}
@Override
}
private void internalAbort() {
- logger.trace("Aborting {}", this);
+ LOG.trace("Aborting {}", this);
transactionStatus.setAborted();
close();
}
+ @Override
public void close() {
dependencyResolverManager.close();
txLookupRegistry.close();
public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
txLookupRegistry.checkConfigBeanExists(objectName);
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans() {
+ return txLookupRegistry.lookupRuntimeBeans();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ObjectName> lookupRuntimeBeans(String moduleName,
+ String instanceName) {
+ return txLookupRegistry.lookupRuntimeBeans(moduleName, instanceName);
+ }
+
// --
/**