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;
+import org.opendaylight.controller.config.manager.impl.dependencyresolver.ModuleInternalTransactionalInfo;
import org.opendaylight.controller.config.manager.impl.dynamicmbean.DynamicWritableWrapper;
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;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
* 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
ConfigTransactionControllerInternal,
ConfigTransactionControllerImplMXBean,
- Identifiable<TransactionIdentifier>{
+ Identifiable<TransactionIdentifier> {
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<ModuleFactory> currentlyRegisteredFactories;
+ private final Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories;
/**
* Disables ability of {@link DynamicWritableWrapper} to change attributes
configBeanModificationDisabled);
private final MBeanServer configMBeanServer;
- private final BundleContext bundleContext;
-
- public ConfigTransactionControllerImpl(String transactionName,
- TransactionJMXRegistrator transactionRegistrator,
- long parentVersion, long currentVersion,
- List<ModuleFactory> currentlyRegisteredFactories,
- MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer, BundleContext bundleContext) {
+ private final boolean blankTransaction;
- this.transactionIdentifier = new TransactionIdentifier(transactionName);
- this.controllerON = ObjectNameUtil
- .createTransactionControllerON(transactionName);
- this.transactionRegistrator = transactionRegistrator;
- txModuleJMXRegistrator = transactionRegistrator
- .createTransactionModuleJMXRegistrator();
+ @GuardedBy("this")
+ private final ServiceReferenceWritableRegistry writableSRRegistry;
+
+ public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
+ long parentVersion, CodecRegistry codecRegistry, long currentVersion,
+ Map<String, Entry<ModuleFactory, BundleContext>> 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;
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
- this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus);
+ this.dependencyResolverManager = new DependencyResolverManager(txLookupRegistry.getTransactionIdentifier(),
+ transactionStatus, writableSRRegistry, codecRegistry);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
- this.bundleContext = bundleContext;
+ this.blankTransaction = blankTransaction;
+ this.writableSRRegistry = writableSRRegistry;
}
@Override
transactionStatus.checkNotAborted();
Set<ModuleFactory> oldSet = new HashSet<>(lastListOfFactories);
- Set<ModuleFactory> newSet = new HashSet<>(currentlyRegisteredFactories);
+ Set<ModuleFactory> newSet = new HashSet<>(factoriesHolder.getModuleFactories());
List<ModuleFactory> toBeAdded = new ArrayList<>();
List<ModuleFactory> toBeRemoved = new ArrayList<>();
- for(ModuleFactory moduleFactory: currentlyRegisteredFactories) {
- if (oldSet.contains(moduleFactory) == false){
+ for (ModuleFactory moduleFactory : factoriesHolder.getModuleFactories()) {
+ if (oldSet.contains(moduleFactory) == false) {
toBeAdded.add(moduleFactory);
}
}
- for(ModuleFactory moduleFactory: lastListOfFactories){
+ for (ModuleFactory moduleFactory : lastListOfFactories) {
if (newSet.contains(moduleFactory) == false) {
toBeRemoved.add(moduleFactory);
}
}
// add default modules
for (ModuleFactory moduleFactory : toBeAdded) {
- Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
+ Set<? extends Module> 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, dependencyResolver);
+ boolean defaultBean = true;
+ putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver, defaultBean);
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
}
// remove modules belonging to removed factories
- for(ModuleFactory removedFactory: toBeRemoved){
+ for (ModuleFactory removedFactory : toBeRemoved) {
List<ModuleIdentifier> modulesOfRemovedFactory = dependencyResolverManager.findAllByFactory(removedFactory);
for (ModuleIdentifier name : modulesOfRemovedFactory) {
destroyModule(name);
throws InstanceAlreadyExistsException {
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
- ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getName();
+ ModuleIdentifier moduleIdentifier = oldConfigBeanInfo.getIdentifier();
dependencyResolverManager.assertNotExists(moduleIdentifier);
ModuleFactory moduleFactory = factoriesHolder
.findByModuleName(moduleIdentifier.getFactoryName());
Module module;
- DependencyResolver dependencyResolver = dependencyResolverManager
- .getOrCreate(moduleIdentifier);
+ 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, dependencyResolver);
+ putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver,
+ oldConfigBeanInfo.isDefaultBean());
}
@Override
public synchronized ObjectName createModule(String factoryName,
- String instanceName) throws InstanceAlreadyExistsException {
+ String instanceName) throws InstanceAlreadyExistsException {
transactionStatus.checkNotCommitStarted();
transactionStatus.checkNotAborted();
// 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, dependencyResolver);
+ moduleFactory, null, dependencyResolver, defaultBean);
}
private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
ModuleIdentifier moduleIdentifier, Module module,
ModuleFactory moduleFactory,
- @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
+ @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver, boolean isDefaultBean)
throws InstanceAlreadyExistsException {
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
- if (moduleIdentifier.equals(module.getIdentifier())==false) {
+ if (moduleIdentifier.equals(module.getIdentifier()) == false) {
throw new IllegalStateException("Incorrect name reported by module. Expected "
- + moduleIdentifier + ", got " + module.getIdentifier());
+ + moduleIdentifier + ", got " + module.getIdentifier());
}
- if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+ 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);
- dependencyResolverManager.put(moduleInternalTransactionalInfo);
+ dependencyResolverManager.put(
+ moduleIdentifier, module, moduleFactory,
+ maybeOldConfigBeanInfo, transactionModuleJMXRegistration, isDefaultBean);
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();
@Override
public synchronized void validateConfig() throws ValidationException {
- if (configBeanModificationDisabled.get())
+ if (configBeanModificationDisabled.get()) {
throw new IllegalStateException("Cannot start validation");
+ }
configBeanModificationDisabled.set(true);
try {
validate_noLocks();
private void validate_noLocks() throws ValidationException {
transactionStatus.checkNotAborted();
- logger.info("Validating transaction {}", transactionIdentifier);
+ logger.trace("Validating transaction {}", getTransactionIdentifier());
// call validate()
List<ValidationException> collectedExceptions = new ArrayList<>();
for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
throw ValidationException
.createFromCollectedValidationExceptions(collectedExceptions);
}
- logger.info("Validated transaction {}", transactionIdentifier);
+ logger.trace("Validated transaction {}", getTransactionIdentifier());
}
/**
try {
validate_noLocks();
} catch (ValidationException e) {
- logger.info("Commit failed on validation");
+ logger.trace("Commit failed on validation");
configBeanModificationDisabled.set(false); // recoverable error
throw e;
}
+ "to obtain a lock");
}
- logger.info("Committing transaction {}", transactionIdentifier);
+ logger.trace("Committing transaction {}", getTransactionIdentifier());
// call getInstance()
for (Entry<ModuleIdentifier, Module> entry : dependencyResolverManager
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(
+ throw new IllegalStateException(
format("Error - getInstance() failed for %s in transaction %s",
- name, transactionIdentifier), e);
+ name, getTransactionIdentifier()), e);
}
}
// count dependency order
- logger.info("Committed configuration {}", transactionIdentifier);
+ logger.trace("Committed configuration {}", getTransactionIdentifier());
transactionStatus.setCommitted();
- // unregister this and all modules from jmx
- close();
return dependencyResolverManager.getSortedModuleIdentifiers();
}
close();
}
- private void close() {
- transactionRegistrator.close();
+ public void close() {
+ dependencyResolverManager.close();
}
@Override
@Override
public String getTransactionName() {
- return transactionIdentifier.getName();
+ return getTransactionIdentifier().getName();
}
/**
*/
@Override
public Set<ObjectName> lookupConfigBeans() {
- return lookupConfigBeans("*", "*");
+ return txLookupRegistry.lookupConfigBeans();
}
/**
*/
@Override
public Set<ObjectName> lookupConfigBeans(String moduleName) {
- return lookupConfigBeans(moduleName, "*");
+ return txLookupRegistry.lookupConfigBeans(moduleName);
}
/**
@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<ObjectName> lookupConfigBeans(String moduleName, String instanceName) {
+ return txLookupRegistry.lookupConfigBeans(moduleName, instanceName);
}
/**
* {@inheritDoc}
*/
@Override
- public Set<ObjectName> 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<String> getAvailableModuleNames() {
return factoriesHolder.getModuleNames();
// @VisibleForTesting
TransactionModuleJMXRegistrator getTxModuleJMXRegistrator() {
- return txModuleJMXRegistrator;
+ return txLookupRegistry.getTxModuleJMXRegistrator();
}
public TransactionIdentifier getName() {
- return transactionIdentifier;
+ return getTransactionIdentifier();
}
@Override
public List<ModuleFactory> getCurrentlyRegisteredFactories() {
- return currentlyRegisteredFactories;
+ return new ArrayList<>(factoriesHolder.getModuleFactories());
}
@Override
public TransactionIdentifier getIdentifier() {
- return transactionIdentifier;
+ return getTransactionIdentifier();
+ }
+
+ @Override
+ public BundleContext getModuleFactoryBundleContext(String factoryName) {
+ Map.Entry<ModuleFactory, BundleContext> 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 serviceInterfaceQName, String refName) {
+ return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
+ }
+
+ @Override
+ public synchronized Map<String, Map<String, ObjectName>> getServiceMapping() {
+ return writableSRRegistry.getServiceMapping();
+ }
+
+ @Override
+ public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+ return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
+ }
+
+ @Override
+ public synchronized Set<String> 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 ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
+ return writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, moduleON);
+ }
+
+ @Override
+ public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException {
+ 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;
+ }
+
+ @Override
+ public TransactionIdentifier getTransactionIdentifier() {
+ return txLookupRegistry.getTransactionIdentifier();
+ }
+
+ @Override
+ public Set<String> getAvailableModuleFactoryQNames() {
+ return txLookupRegistry.getAvailableModuleFactoryQNames();
+ }
+
+ @Override
+ public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+ writableSRRegistry.checkServiceReferenceExists(objectName);
+ }
+
+ @Override
+ public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+ return writableSRRegistry.getServiceReference(serviceInterfaceQName, refName);
}
}