Merge "Adding another constructor to ContainerFlowConfig to take dlVlan. Being an...
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / ConfigRegistryImpl.java
index 97d57a459199e2bf0ee9912f64b6c505b0f395ca..84c2c6dd4dd46b57372d1fbf14a46f43ed225181 100644 (file)
@@ -7,32 +7,11 @@
  */
 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;
@@ -45,22 +24,44 @@ import org.opendaylight.controller.config.manager.impl.osgi.BeanToOsgiServiceMan
 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")
@@ -98,6 +99,9 @@ public class ConfigRegistryImpl implements AutoCloseable,
     // 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) {
@@ -112,6 +116,7 @@ public class ConfigRegistryImpl implements AutoCloseable,
         this.resolver = resolver;
         this.beanToOsgiServiceManager = new BeanToOsgiServiceManager(
                 bundleContext);
+        this.bundleContext = bundleContext;
         this.configMBeanServer = configMBeanServer;
         this.baseJMXRegistrator = baseJMXRegistrator;
         this.registryMBeanServer = MBeanServerFactory
@@ -130,30 +135,21 @@ public class ConfigRegistryImpl implements AutoCloseable,
 
     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;
     }
@@ -162,20 +158,15 @@ public class ConfigRegistryImpl implements AutoCloseable,
      * {@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));
@@ -190,33 +181,28 @@ public class ConfigRegistryImpl implements AutoCloseable,
         }
         // 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
@@ -226,7 +212,7 @@ public class ConfigRegistryImpl implements AutoCloseable,
                                    // runtime jmx registrator),
             // also closes osgi registration and ModuleJMXRegistrator
             // registration
-            currentConfig.remove(toBeDestroyed.getName());
+            currentConfig.remove(toBeDestroyed.getIdentifier());
         }
 
         // set RuntimeBeanRegistrators on beans implementing
@@ -289,6 +275,7 @@ public class ConfigRegistryImpl implements AutoCloseable,
             ModuleJMXRegistrator newModuleJMXRegistrator = baseJMXRegistrator
                     .createModuleJMXRegistrator();
 
+            OsgiRegistration osgiRegistration = null;
             if (entry.hasOldModule()) {
                 ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
                 DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
@@ -296,19 +283,21 @@ public class ConfigRegistryImpl implements AutoCloseable,
                 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 {
@@ -330,10 +319,10 @@ public class ConfigRegistryImpl implements AutoCloseable,
             }
 
             // 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());