*/
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.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.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")
// internal jmx server shared by all transactions
private final MBeanServer transactionsMBeanServer;
+ @GuardedBy("this")
+ private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
+
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
BundleContext bundleContext, MBeanServer configMBeanServer) {
this.resolver = resolver;
this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(
bundleContext);
+ this.bundleContext = bundleContext;
this.configMBeanServer = configMBeanServer;
this.baseJMXRegistrator = baseJMXRegistrator;
this.registryMBeanServer = MBeanServerFactory
private synchronized ConfigTransactionControllerInternal beginConfigInternal() {
versionCounter++;
- String transactionName = "ConfigTransaction-" + version + "-"
- + versionCounter;
+ String transactionName = "ConfigTransaction-" + version + "-" + versionCounter;
TransactionJMXRegistrator transactionRegistrator = baseJMXRegistrator
.createTransactionJMXRegistrator(transactionName);
+ List<ModuleFactory> allCurrentFactories = Collections.unmodifiableList(resolver.getAllFactories());
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
transactionName, transactionRegistrator, version,
- versionCounter, resolver.getAllFactories(),
- transactionsMBeanServer, configMBeanServer);
+ versionCounter, allCurrentFactories, transactionsMBeanServer, configMBeanServer, bundleContext);
try {
- transactionRegistrator.registerMBean(transactionController, transactionController.getControllerObjectName
- ());
+ transactionRegistrator.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;
}
* {@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<String, ConfigTransactionControllerInternal> transactions = transactionsHolder
- .getCurrentTransactions();
- ConfigTransactionControllerInternal configTransactionController = transactions
- .get(transactionName);
+ Map<String, ConfigTransactionControllerInternal> transactions = transactionsHolder.getCurrentTransactions();
+ ConfigTransactionControllerInternal configTransactionController = transactions.get(transactionName);
if (configTransactionController == null) {
throw new IllegalArgumentException(String.format(
"Transaction with name '%s' not found", transactionName));
}
// 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
// runtime jmx registrator),
// also closes osgi registration and ModuleJMXRegistrator
// registration
- currentConfig.remove(toBeDestroyed.getName());
+ currentConfig.remove(toBeDestroyed.getIdentifier());
}
// set RuntimeBeanRegistrators on beans implementing
ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator
.createModuleJMXRegistrator();
+ OsgiRegistration osgiRegistration = null;
if (entry.hasOldModule()) {
ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
currentConfig.remove(entry.getName());
// 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) {
+ osgiRegistration = beanToOsgiServiceManager.registerToOsgi(module.getClass(),
+ newReadableConfigBean.getInstance(), entry.getName());
+ }
RootRuntimeBeanRegistratorImpl runtimeBeanRegistrator = runtimeRegistrators
.get(entry.getName());