*/
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.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;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager;
import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceManager.OsgiRegistration;
import org.opendaylight.controller.config.manager.impl.util.LookupBeansUtil;
+import org.opendaylight.controller.config.manager.impl.util.ModuleQNameUtil;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
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.
private final ModuleFactoriesResolver resolver;
private final MBeanServer configMBeanServer;
+ private final CodecRegistry codecRegistry;
+
@GuardedBy("this")
private long version = 0;
@GuardedBy("this")
// internal jmx server shared by all transactions
private final MBeanServer transactionsMBeanServer;
+ // Used for finding new factory instances for default module functionality
@GuardedBy("this")
private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
+ @GuardedBy("this") // switched in every 2ndPC
+ private CloseableServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
+
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- BundleContext bundleContext, MBeanServer configMBeanServer) {
- this(resolver, bundleContext, configMBeanServer,
- new BaseJMXRegistrator(configMBeanServer));
+ MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
+ this(resolver, configMBeanServer,
+ new BaseJMXRegistrator(configMBeanServer), codecRegistry);
}
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- BundleContext bundleContext, MBeanServer configMBeanServer,
- BaseJMXRegistrator baseJMXRegistrator) {
+ MBeanServer configMBeanServer,
+ BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
this.resolver = resolver;
- this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(
- bundleContext);
+ this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
this.configMBeanServer = configMBeanServer;
this.baseJMXRegistrator = baseJMXRegistrator;
+ this.codecRegistry = codecRegistry;
this.registryMBeanServer = MBeanServerFactory
.createMBeanServer("ConfigRegistry" + configMBeanServer.getDefaultDomain());
this.transactionsMBeanServer = MBeanServerFactory
*/
@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);
- List<ModuleFactory> allCurrentFactories = Collections.unmodifiableList(resolver.getAllFactories());
+ final String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
+
+ TransactionJMXRegistratorFactory factory = new TransactionJMXRegistratorFactory() {
+ @Override
+ public TransactionJMXRegistrator create() {
+ return baseJMXRegistrator.createTransactionJMXRegistrator(transactionName);
+ }
+ };
+
+ Map<String, Map.Entry<ModuleFactory, BundleContext>> allCurrentFactories = Collections.unmodifiableMap(
+ resolver.getAllFactories());
+ ConfigTransactionLookupRegistry txLookupRegistry = new ConfigTransactionLookupRegistry(new TransactionIdentifier(
+ transactionName), factory, allCurrentFactories);
+ ServiceReferenceWritableRegistry writableRegistry = ServiceReferenceRegistryImpl.createSRWritableRegistry(
+ readableSRRegistry, txLookupRegistry, allCurrentFactories);
+
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
- transactionName, transactionRegistrator, version,
- versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer);
+ txLookupRegistry, version, codecRegistry,
+ versionCounter, allCurrentFactories, transactionsMBeanServer,
+ configMBeanServer, blankTransaction, writableRegistry);
try {
- transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName());
+ txLookupRegistry.registerMBean(transactionController, transactionController.getControllerObjectName());
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
-
transactionController.copyExistingModulesAndProcessFactoryDiff(currentConfig.getEntries(), lastListOfFactories);
-
transactionsHolder.add(transactionName, transactionController);
return transactionController;
}
throws ConflictingVersionException, ValidationException {
final String transactionName = ObjectNameUtil
.getTransactionName(transactionControllerON);
- logger.info("About to commit {}. Current parentVersion: {}, versionCounter {}", transactionName, version, versionCounter);
+ logger.trace("About to commit {}. Current parentVersion: {}, versionCounter {}", transactionName, version, versionCounter);
// find ConfigTransactionController
Map<String, ConfigTransactionControllerInternal> transactions = transactionsHolder.getCurrentTransactions();
// runtime jmx registrator),
// also closes osgi registration and ModuleJMXRegistrator
// registration
- currentConfig.remove(toBeDestroyed.getName());
+ currentConfig.remove(toBeDestroyed.getIdentifier());
}
// set RuntimeBeanRegistrators on beans implementing
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator;
if (entry.hasOldModule() == false) {
runtimeBeanRegistrator = baseJMXRegistrator
- .createRuntimeBeanRegistrator(entry.getName());
+ .createRuntimeBeanRegistrator(entry.getIdentifier());
} else {
// reuse old JMX registrator
runtimeBeanRegistrator = entry.getOldInternalInfo()
.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
// 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
ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator
.createModuleJMXRegistrator();
+ OsgiRegistration osgiRegistration = null;
if (entry.hasOldModule()) {
ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
- DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
- .getReadableModule();
- currentConfig.remove(entry.getName());
+ DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo.getReadableModule();
+ 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 {
}
// 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++;
// update version
version = configTransactionController.getVersion();
+
+ // switch readable Service Reference Registry
+ this.readableSRRegistry.close();
+ this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(
+ configTransactionController.getWritableRegistry(), this, baseJMXRegistrator);
+
return new CommitStatus(newInstances, reusedInstances,
recreatedInstances);
}
/**
* 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
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 serviceInterfaceQName, String refName) {
+ return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
+ }
+
+ @Override
+ public synchronized Map<String, Map<String, ObjectName>> getServiceMapping() {
+ return readableSRRegistry.getServiceMapping();
+ }
+
+ @Override
+ public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+ return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
+ }
+
+ @Override
+ public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+ return readableSRRegistry.lookupServiceInterfaceNames(objectName);
+ }
+
+ @Override
+ public synchronized String getServiceInterfaceName(String namespace, String localName) {
+ return readableSRRegistry.getServiceInterfaceName(namespace, localName);
+ }
+
+ @Override
+ public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+ readableSRRegistry.checkServiceReferenceExists(objectName);
+ }
+
+ @Override
+ public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+ return readableSRRegistry.getServiceReference(serviceInterfaceQName, refName);
+ }
+
+ @Override
+ public Set<String> getAvailableModuleFactoryQNames() {
+ return ModuleQNameUtil.getQNames(resolver.getAllFactories());
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigRegistryImpl{" +
+ "versionCounter=" + versionCounter +
+ ", version=" + version +
+ '}';
+ }
}
/**
}
private void add(ModuleInternalInfo configInfo) {
- ModuleInternalInfo oldValue = currentConfig.put(configInfo.getName(),
+ ModuleInternalInfo oldValue = currentConfig.put(configInfo.getIdentifier(),
configInfo);
if (oldValue != null) {
throw new IllegalStateException(
"Cannot overwrite module with same name:"
- + configInfo.getName() + ":" + configInfo);
+ + configInfo.getIdentifier() + ":" + configInfo);
}
}
Collections.sort(result);
return result;
}
+
+
}
/**