Persist service references as separate MBeans. 46/3746/3
authorTomas Olvecky <tolvecky@cisco.com>
Mon, 16 Dec 2013 10:39:41 +0000 (11:39 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 17 Dec 2013 01:31:54 +0000 (01:31 +0000)
Create dummy MBean - ServiceReferenceMXBean - that contains link to implementation of the service as an attribute.
Add support for resolving of SR to dependency resolver. Each time user saves SR, create MBean and
add the interface QName together with user defined reference name to ObjectName of the newly created SR MBean.

Change-Id: I71ddb762e00d9be8b426fb979ff5ade046d46050
Signed-off-by: Tomas Olvecky <tolvecky@cisco.com>
36 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java
opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java
opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl

index c257e55..2647513 100644 (file)
@@ -16,7 +16,7 @@ import javax.management.ObjectName;
 /**
  * Represents functionality provided by configuration transaction.
  */
-public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public interface ConfigTransactionController extends LookupRegistry, ServiceReferenceWritableRegistry {
 
     /**
      * Create new configuration bean.
index 772617e..376ecdb 100644 (file)
@@ -65,8 +65,9 @@ public interface LookupRegistry {
      */
     void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException;
 
+
     /**
-     * @return qnames of all ModuleFactory instances in the system
+     * @return qNames of all ModuleFactory instances in the system
      */
     Set<String> getAvailableModuleFactoryQNames();
 
index f84fcd4..d7e94e8 100644 (file)
@@ -16,24 +16,24 @@ public interface ServiceReferenceReadableRegistry {
 
     /**
      * Lookup object name by fully qualified service interface name and service reference name.
-     * @param serviceInterfaceName service interface name
+     * @param serviceInterfaceQName service interface name
      * @param refName service reference name supplied in
      * {@link org.opendaylight.controller.config.api.ConfigTransactionController#saveServiceReference(String, String, javax.management.ObjectName)}
      * @throws java.lang.IllegalArgumentException if module not found
      */
-    ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName);
+    ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName);
 
     /**
      * Get mapping of services to reference names and module object names.
      */
-    Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping();
+    Map<String /* serviceInterfaceQName */, Map<String/* refName */, ObjectName>> getServiceMapping();
 
     /**
      * Get current mapping between reference names and module object names for given service interface name.
-     * @param serviceInterfaceName service interface name
+     * @param serviceInterfaceQName service interface name
      * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
      */
-    Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName);
+    Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName);
 
     /**
      * Find all available service interface names of a module.
@@ -50,4 +50,13 @@ public interface ServiceReferenceReadableRegistry {
      */
     String getServiceInterfaceName(String namespace, String localName);
 
+    /**
+     * @return ObjectName with type=Service that was created using
+     * {@link org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry#saveServiceReference(String, String,
+     * javax.management.ObjectName)}
+     */
+    ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException;
+
+    void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException;
+
 }
index f3d6d16..fa2aa1f 100644 (file)
@@ -13,17 +13,18 @@ import javax.management.ObjectName;
 public interface ServiceReferenceWritableRegistry extends ServiceReferenceReadableRegistry {
     /**
      * Create or update reference name to objectName. Reference name is unique per service interface name.
+     * @return created or updated object name containing service name and reference name
      * @throws IllegalArgumentException if there is a mismatch between serviceInterfaceName and objectName
      * @throws InstanceNotFoundException if search did not find exactly one instance
      */
-    void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException;
+    ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException;
 
     /**
      * Remove service reference.
      * @return true iif removed
      * @throws IllegalArgumentException if service interface name is not advertised by any module
      */
-    boolean removeServiceReference(String serviceInterfaceName, String refName);
+    void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException;
 
     /**
      * Remove all service references.
index cc1d897..3baa103 100644 (file)
@@ -25,21 +25,23 @@ import java.util.Set;
  * is defined as {@link #ON_DOMAIN} and at least one key-value pair. The only
  * mandatory property is {@link #TYPE_KEY}. All transaction related mbeans have
  * {@link #TRANSACTION_NAME_KEY} property set.
- *
  */
 @ThreadSafe
 public class ObjectNameUtil {
 
     public static final String ON_DOMAIN = ConfigRegistryConstants.ON_DOMAIN;
     public static final String MODULE_FACTORY_NAME_KEY = "moduleFactoryName";
+    public static final String SERVICE_QNAME_KEY = "serviceQName";
     public static final String INSTANCE_NAME_KEY = "instanceName";
     public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
     public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
     public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
     public static final String TYPE_MODULE = "Module";
+    public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
     public static final String TYPE_RUNTIME_BEAN = "RuntimeBean";
-
     public static final String TRANSACTION_NAME_KEY = "TransactionName";
+    public static final String REF_NAME_KEY = "RefName";
+    private static final String REPLACED_QUOTATION_MARK = "\\?";
 
     public static ObjectName createON(String on) {
         try {
@@ -57,10 +59,10 @@ public class ObjectNameUtil {
         return ConfigRegistryConstants.createON(name, key, value);
     }
 
-    public static ObjectName createON(String name, Map<String, String> attribs) {
+    public static ObjectName createON(String domain, Map<String, String> attribs) {
         Hashtable<String, String> table = new Hashtable<>(attribs);
         try {
-            return new ObjectName(name, table);
+            return new ObjectName(domain, table);
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
@@ -76,21 +78,21 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            ModuleIdentifier moduleIdentifier) {
+                                                       ModuleIdentifier moduleIdentifier) {
         return createTransactionModuleON(transactionName,
                 moduleIdentifier.getFactoryName(),
                 moduleIdentifier.getInstanceName());
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            String moduleName, String instanceName) {
-        Map<String, String> onParams = createModuleON(moduleName, instanceName);
+                                                       String moduleName, String instanceName) {
+        Map<String, String> onParams = createModuleMap(moduleName, instanceName);
         onParams.put(TRANSACTION_NAME_KEY, transactionName);
         return createON(ON_DOMAIN, onParams);
     }
 
     public static ObjectName createTransactionModuleON(String transactionName,
-            ObjectName on) {
+                                                       ObjectName on) {
         return createTransactionModuleON(transactionName, getFactoryName(on),
                 getInstanceName(on));
     }
@@ -101,14 +103,73 @@ public class ObjectNameUtil {
                 moduleIdentifier.getInstanceName());
     }
 
+    public static ObjectName createReadOnlyServiceON(String serviceQName, String refName) {
+        Map<String, String> onParams = createServiceMap(serviceQName, refName);
+        return createON(ON_DOMAIN, onParams);
+    }
+
+    public static ObjectName createTransactionServiceON(String transactionName, String serviceQName, String refName) {
+        Map<String, String> onParams = createServiceON(transactionName, serviceQName, refName);
+        return createON(ON_DOMAIN, onParams);
+    }
+
+    public static String getServiceQName(ObjectName objectName) {
+        checkType(objectName, TYPE_SERVICE_REFERENCE);
+        String quoted = objectName.getKeyProperty(SERVICE_QNAME_KEY);
+        String result = unquoteAndUnescape(objectName, quoted);
+        return result;
+    }
+
+    // ObjectName supports quotation and ignores tokens like =, but fails to ignore ? sign.
+    // It must be replaced with another character that hopefully does not collide
+    // with actual value.
+    private static String unquoteAndUnescape(ObjectName objectName, String quoted) {
+        if (quoted == null) {
+            throw new IllegalArgumentException("Cannot find " + SERVICE_QNAME_KEY + " in " + objectName);
+        }
+        if (quoted.startsWith("\"") == false || quoted.endsWith("\"") == false) {
+            throw new IllegalArgumentException("Quotes not found in " + objectName);
+        }
+        String substring = quoted.substring(1);
+        substring = substring.substring(0, substring.length() - 1);
+        substring = substring.replace(REPLACED_QUOTATION_MARK, "?");
+        return substring;
+    }
+
+    private static String quoteAndEscapeValue(String serviceQName) {
+        return "\"" + serviceQName.replace("?", REPLACED_QUOTATION_MARK) + "\"";
+    }
+
+    public static String getReferenceName(ObjectName objectName) {
+        checkType(objectName, TYPE_SERVICE_REFERENCE);
+        return objectName.getKeyProperty(REF_NAME_KEY);
+    }
+
+    private static Map<String, String> createServiceON(String transactionName, String serviceQName,
+                                                       String refName) {
+        Map<String, String> result = new HashMap<>(createServiceMap(serviceQName, refName));
+        result.put(TRANSACTION_NAME_KEY, transactionName);
+        return result;
+    }
+
+    private static Map<String, String> createServiceMap(String serviceQName,
+                                                        String refName) {
+        Map<String, String> onParams = new HashMap<>();
+        onParams.put(TYPE_KEY, TYPE_SERVICE_REFERENCE);
+        onParams.put(SERVICE_QNAME_KEY, quoteAndEscapeValue(serviceQName));
+        onParams.put(REF_NAME_KEY, refName);
+        return onParams;
+    }
+
+
     public static ObjectName createReadOnlyModuleON(String moduleName,
-            String instanceName) {
-        Map<String, String> onParams = createModuleON(moduleName, instanceName);
+                                                    String instanceName) {
+        Map<String, String> onParams = createModuleMap(moduleName, instanceName);
         return createON(ON_DOMAIN, onParams);
     }
 
-    private static Map<String, String> createModuleON(String moduleName,
-            String instanceName) {
+    private static Map<String, String> createModuleMap(String moduleName,
+                                                       String instanceName) {
         Map<String, String> onParams = new HashMap<>();
         onParams.put(TYPE_KEY, TYPE_MODULE);
         onParams.put(MODULE_FACTORY_NAME_KEY, moduleName);
@@ -117,10 +178,12 @@ public class ObjectNameUtil {
     }
 
     public static String getFactoryName(ObjectName objectName) {
+        checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
         return objectName.getKeyProperty(MODULE_FACTORY_NAME_KEY);
     }
 
     public static String getInstanceName(ObjectName objectName) {
+        checkTypeOneOf(objectName, TYPE_MODULE, TYPE_RUNTIME_BEAN);
         return objectName.getKeyProperty(INSTANCE_NAME_KEY);
     }
 
@@ -132,6 +195,7 @@ public class ObjectNameUtil {
      * Sanitize on: keep only mandatory attributes of module + metadata.
      */
     public static ObjectName withoutTransactionName(ObjectName inputON) {
+        checkTypeOneOf(inputON, TYPE_MODULE, TYPE_SERVICE_REFERENCE);
         if (getTransactionName(inputON) == null) {
             throw new IllegalArgumentException(
                     "Expected ObjectName with transaction:" + inputON);
@@ -140,14 +204,18 @@ public class ObjectNameUtil {
             throw new IllegalArgumentException("Expected different domain: "
                     + inputON);
         }
-        String moduleName = getFactoryName(inputON);
-        String instanceName = getInstanceName(inputON);
-
-
+        Map<String, String> outputProperties;
+        if (inputON.getKeyProperty(TYPE_KEY).equals(TYPE_MODULE)) {
+            String moduleName = getFactoryName(inputON);
+            String instanceName = getInstanceName(inputON);
+            outputProperties = new HashMap<>(createModuleMap(moduleName, instanceName));
+        } else {
+            String serviceQName = getServiceQName(inputON);
+            String refName = getReferenceName(inputON);
+            outputProperties = new HashMap<>(createServiceMap(serviceQName, refName));
+        }
         Map<String, String> allProperties = getAdditionalProperties(inputON);
-        Map<String, String> outputProperties = new HashMap<>(createModuleON(moduleName, instanceName));
-
-        for(Entry<String, String> entry: allProperties.entrySet()) {
+        for (Entry<String, String> entry : allProperties.entrySet()) {
             if (entry.getKey().startsWith("X-")) {
                 outputProperties.put(entry.getKey(), entry.getValue());
             }
@@ -155,6 +223,13 @@ public class ObjectNameUtil {
         return createON(ON_DOMAIN, outputProperties);
     }
 
+    public static ObjectName withTransactionName(ObjectName inputON, String transactionName) {
+        Map<String, String> additionalProperties = getAdditionalProperties(inputON);
+        additionalProperties.put(TRANSACTION_NAME_KEY, transactionName);
+        return createON(inputON.getDomain(), additionalProperties);
+
+    }
+
     private static void assertDoesNotContain(
             Map<String, String> additionalProperties, String key) {
         if (additionalProperties.containsKey(key)) {
@@ -165,7 +240,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createRuntimeBeanName(String moduleName,
-            String instanceName, Map<String, String> additionalProperties) {
+                                                   String instanceName, Map<String, String> additionalProperties) {
         // check that there is no overwriting of default attributes
         assertDoesNotContain(additionalProperties, MODULE_FACTORY_NAME_KEY);
         assertDoesNotContain(additionalProperties, INSTANCE_NAME_KEY);
@@ -217,8 +292,18 @@ public class ObjectNameUtil {
         }
     }
 
+    public static void checkTypeOneOf(ObjectName objectName, String ... types) {
+        for(String type: types) {
+            if (type.equals(objectName.getKeyProperty(TYPE_KEY))) {
+                return;
+            }
+        }
+        throw new IllegalArgumentException("Wrong type, expected one of " + Arrays.asList(types)
+                + ", got " + objectName);
+    }
+
     public static ObjectName createModulePattern(String moduleName,
-            String instanceName) {
+                                                 String instanceName) {
         if (moduleName == null)
             moduleName = "*";
         if (instanceName == null)
@@ -235,7 +320,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createModulePattern(String ifcName,
-            String instanceName, String transactionName) {
+                                                 String instanceName, String transactionName) {
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
                 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
                 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
@@ -244,7 +329,7 @@ public class ObjectNameUtil {
     }
 
     public static ObjectName createRuntimeBeanPattern(String moduleName,
-            String instanceName) {
+                                                      String instanceName) {
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "="
                 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
@@ -255,7 +340,7 @@ public class ObjectNameUtil {
     }
 
     public static ModuleIdentifier fromON(ObjectName objectName,
-            String expectedType) {
+                                          String expectedType) {
         checkType(objectName, expectedType);
         String factoryName = getFactoryName(objectName);
         if (factoryName == null)
@@ -268,4 +353,7 @@ public class ObjectNameUtil {
         return new ModuleIdentifier(factoryName, instanceName);
     }
 
+    public static boolean isServiceReference(ObjectName objectName) {
+        return TYPE_SERVICE_REFERENCE.equals(objectName.getKeyProperty(TYPE_KEY));
+    }
 }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java
new file mode 100644 (file)
index 0000000..8c32507
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl;
+
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+
+public interface CloseableServiceReferenceReadableRegistry  extends AutoCloseable, ServiceReferenceReadableRegistry {
+
+
+    void close();
+
+}
index e3311c7..1923170 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.controller.config.manager.impl;
 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.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -104,7 +103,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     private List<ModuleFactory> lastListOfFactories = Collections.emptyList();
 
     @GuardedBy("this") // switched in every 2ndPC
-    private ServiceReferenceReadableRegistry readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
+    private CloseableServiceReferenceReadableRegistry  readableSRRegistry = ServiceReferenceRegistryImpl.createInitialSRLookupRegistry();
 
     // constructor
     public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
@@ -298,8 +297,7 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
             OsgiRegistration osgiRegistration = null;
             if (entry.hasOldModule()) {
                 ModuleInternalInfo oldInternalInfo = entry.getOldInternalInfo();
-                DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo
-                        .getReadableModule();
+                DynamicReadableWrapper oldReadableConfigBean = oldInternalInfo.getReadableModule();
                 currentConfig.remove(entry.getIdentifier());
 
                 // test if old instance == new instance
@@ -368,7 +366,9 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         version = configTransactionController.getVersion();
 
         // switch readable Service Reference Registry
-        this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(configTransactionController.getWritableRegistry(), this);
+        this.readableSRRegistry.close();
+        this.readableSRRegistry = ServiceReferenceRegistryImpl.createSRReadableRegistry(
+                configTransactionController.getWritableRegistry(), this, baseJMXRegistrator);
 
         return new CommitStatus(newInstances, reusedInstances,
                 recreatedInstances);
@@ -525,8 +525,8 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
 
     // service reference functionality:
     @Override
-    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return readableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -535,8 +535,8 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
     }
 
     @Override
-    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -549,11 +549,28 @@ public class ConfigRegistryImpl implements AutoCloseable, ConfigRegistryImplMXBe
         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 +
+                '}';
+    }
 }
 
 /**
@@ -579,12 +596,12 @@ class ConfigHolder {
     }
 
     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);
         }
     }
 
index 17ce078..e0d1a42 100644 (file)
@@ -95,7 +95,7 @@ class ConfigTransactionControllerImpl implements
         this.currentlyRegisteredFactories = currentlyRegisteredFactories;
         this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
         this.transactionStatus = new TransactionStatus();
-        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus);
+        this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry);
         this.transactionsMBeanServer = transactionsMBeanServer;
         this.configMBeanServer = configMBeanServer;
         this.blankTransaction = blankTransaction;
@@ -165,15 +165,14 @@ class ConfigTransactionControllerImpl implements
             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(
@@ -412,7 +411,7 @@ class ConfigTransactionControllerImpl implements
         close();
     }
 
-    private void close() {
+    public void close() {
         //FIXME: should not close object that was retrieved in constructor, a wrapper object should do that perhaps
         txLookupRegistry.close();
     }
@@ -523,8 +522,8 @@ class ConfigTransactionControllerImpl implements
 
 
     @Override
-    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return writableSRRegistry.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -533,8 +532,8 @@ class ConfigTransactionControllerImpl implements
     }
 
     @Override
-    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public synchronized Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -548,13 +547,13 @@ class ConfigTransactionControllerImpl implements
     }
 
     @Override
-    public synchronized void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
-        writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, objectName);
+    public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
+        return writableSRRegistry.saveServiceReference(serviceInterfaceName, refName, moduleON);
     }
 
     @Override
-    public synchronized boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        return writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
+    public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException {
+        writableSRRegistry.removeServiceReference(serviceInterfaceName, refName);
     }
 
     @Override
@@ -581,4 +580,13 @@ class ConfigTransactionControllerImpl implements
         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);
+    }
 }
index 12db6c8..a7d426e 100644 (file)
@@ -117,6 +117,13 @@ class ConfigTransactionLookupRegistry  implements LookupRegistry, Closeable {
         return ModuleQNameUtil.getQNames(allCurrentFactories);
     }
 
+
+    @Override
+    public String toString() {
+        return "ConfigTransactionLookupRegistry{" +
+                "transactionIdentifier=" + transactionIdentifier +
+                '}';
+    }
 }
 
 interface TransactionJMXRegistratorFactory {
index 14a706d..941aec1 100644 (file)
@@ -90,11 +90,6 @@ public class ModuleInternalInfo implements Comparable<ModuleInternalInfo>,
         return osgiRegistration;
     }
 
-    @Deprecated
-    public ModuleIdentifier getName() {
-        return name;
-    }
-
     /**
      * Get index representing dependency ordering within a transaction.
      */
@@ -111,7 +106,7 @@ public class ModuleInternalInfo implements Comparable<ModuleInternalInfo>,
     }
 
     public DestroyedModule toDestroyedModule() {
-        return new DestroyedModule(getName(),
+        return new DestroyedModule(getIdentifier(),
                 getReadableModule().getInstance(), getModuleJMXRegistrator(),
                 getOsgiRegistration(), getOrderingIdx());
     }
index 7fedcdf..0faa32b 100644 (file)
@@ -13,42 +13,52 @@ import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.ServiceReferenceWritableRegistry;
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReference;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBeanImpl;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceJMXRegistration;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactory;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceRegistrator.ServiceReferenceTransactionRegistratorFactoryImpl;
 import org.opendaylight.controller.config.manager.impl.util.InterfacesHelper;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
-public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
+public class ServiceReferenceRegistryImpl implements CloseableServiceReferenceReadableRegistry, ServiceReferenceWritableRegistry {
     private static final Logger logger = LoggerFactory.getLogger(ServiceReferenceRegistryImpl.class);
 
     private final Map<String, ModuleFactory> factories;
     private final Map<String, Set<String>> factoryNamesToQNames;
     // validator of incoming ObjectNames - throws InstanceNotFoundException if not found either in registry or transaction
     private final LookupRegistry lookupRegistry;
+    private final ServiceReferenceRegistrator serviceReferenceRegistrator;
     // helper method for getting QName of SI from namespace + local name
     private final Map<String /* namespace */, Map<String /* local name */, ServiceInterfaceAnnotation>> namespacesToAnnotations;
     // all Service Interface qNames for sanity checking
     private final Set<String /* qName */> allQNames;
 
     // actual reference database
-    private final Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNames;
+    private final Map<ServiceReference, ModuleIdentifier> refNames = new HashMap<>();
+    private final boolean writable;
+    private final Map<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> mBeans = new HashMap<>();
 
     /**
      * Static constructor for config registry. Since only transaction can write to this registry, it will
      * return blank state.
      */
-    public static ServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
+    public static CloseableServiceReferenceReadableRegistry createInitialSRLookupRegistry() {
         // since this is initial state, just throw exception:
         LookupRegistry lookupRegistry = new LookupRegistry() {
             @Override
@@ -73,36 +83,99 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
 
             @Override
             public void checkConfigBeanExists(ObjectName objectName) throws InstanceNotFoundException {
-                throw new InstanceNotFoundException("Cannot find " + objectName);
+                throw new InstanceNotFoundException("Cannot find " + objectName + " - Tried to use mocking registry");
             }
 
             @Override
             public Set<String> getAvailableModuleFactoryQNames() {
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public String toString() {
+                return "initial";
+            }
+        };
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactory(){
+            @Override
+            public ServiceReferenceRegistrator create() {
+                return new ServiceReferenceRegistrator() {
+                    @Override
+                    public String getNullableTransactionName() {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object, ObjectName on) throws InstanceAlreadyExistsException {
+                        throw new UnsupportedOperationException();
+                    }
+
+                    @Override
+                    public void close() {
+
+                    }
+                };
+            }
         };
         return new ServiceReferenceRegistryImpl(Collections.<String, ModuleFactory>emptyMap(), lookupRegistry,
-                Collections.<String /* qName */, Map<String /* refName */, ModuleIdentifier>>emptyMap());
+                serviceReferenceRegistratorFactory, false);
     }
 
     /**
      * Static constructor for transaction controller. Take current state as seen by config registry, allow writing new data.
      */
     public static ServiceReferenceWritableRegistry createSRWritableRegistry(ServiceReferenceReadableRegistry oldReadableRegistry,
-            LookupRegistry lookupRegistry, Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
+                                                    ConfigTransactionLookupRegistry txLookupRegistry,
+                                                    Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
 
+        if (txLookupRegistry == null) {
+            throw new IllegalArgumentException("txLookupRegistry is null");
+        }
         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry;
         Map<String, ModuleFactory> factories = extractFactoriesMap(currentlyRegisteredFactories);
-        return new ServiceReferenceRegistryImpl(factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(
+                txLookupRegistry.getTxModuleJMXRegistrator(), txLookupRegistry.getTxModuleJMXRegistrator().getTransactionName());
+        ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(factories, txLookupRegistry,
+                serviceReferenceRegistratorFactory, true);
+        copy(old, newRegistry, txLookupRegistry.getTransactionIdentifier().getName());
+        return newRegistry;
     }
 
     /**
      * Copy back state to config registry after commit.
      */
-    public static ServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry, LookupRegistry lookupRegistry) {
+    public static CloseableServiceReferenceReadableRegistry createSRReadableRegistry(ServiceReferenceWritableRegistry oldWritableRegistry,
+                                                                            LookupRegistry lookupRegistry, BaseJMXRegistrator baseJMXRegistrator) {
         ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldWritableRegistry;
+
         // even if factories do change, nothing in the mapping can change between transactions
-        return new ServiceReferenceRegistryImpl(old.factories, lookupRegistry, Collections.unmodifiableMap(old.refNames));
+        ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory = new ServiceReferenceTransactionRegistratorFactoryImpl(baseJMXRegistrator);
+        ServiceReferenceRegistryImpl newRegistry = new ServiceReferenceRegistryImpl(old.factories, lookupRegistry,
+                serviceReferenceRegistratorFactory, false);
+        copy(old, newRegistry, null);
+        return newRegistry;
+    }
+
+    /**
+     * Fill refNames and mBeans maps from old instance
+     */
+    private static void copy(ServiceReferenceRegistryImpl old, ServiceReferenceRegistryImpl newRegistry, String nullableDstTransactionName) {
+        for (Entry<ServiceReference, Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>> refNameEntry : old.mBeans.entrySet()) {
+            ObjectName currentImplementation;
+            ObjectName currentImplementationSrc = refNameEntry.getValue().getKey().getCurrentImplementation();
+            if (nullableDstTransactionName != null) {
+                currentImplementation = ObjectNameUtil.withTransactionName(currentImplementationSrc, nullableDstTransactionName);
+            } else {
+                currentImplementation = ObjectNameUtil.withoutTransactionName(currentImplementationSrc);
+            }
+            try {
+                boolean skipChecks = true;
+                newRegistry.saveServiceReference(refNameEntry.getKey(), currentImplementation, skipChecks);
+            } catch (InstanceNotFoundException e) {
+                logger.error("Cannot save service reference({}, {})", refNameEntry.getKey(), currentImplementation);
+                throw new IllegalStateException("Possible code error", e);
+            }
+        }
     }
 
     private static Map<String, ModuleFactory> extractFactoriesMap(Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories) {
@@ -114,9 +187,14 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     private ServiceReferenceRegistryImpl(Map<String, ModuleFactory> factories, LookupRegistry lookupRegistry,
-                                         Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> refNamesToCopy) {
+                                         ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory,
+                                         boolean writable) {
         this.factories = factories;
+        this.writable = writable;
         this.lookupRegistry = lookupRegistry;
+
+        this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create();
+
         Map<String, Set<String /* QName */>> factoryNamesToQNames = new HashMap<>();
         Set<ServiceInterfaceAnnotation> allAnnotations = new HashSet<>();
         Set<String /* qName */> allQNames = new HashSet<>();
@@ -154,22 +232,12 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
         }
         this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations);
         // copy refNames
-        Map<String /* qName */, Map<String /* refName */, ModuleIdentifier>> deepCopy = new HashMap<>();
-        for (Entry<String, Map<String, ModuleIdentifier>> outerROEntry: refNamesToCopy.entrySet()) {
-            Map<String /* refName */, ModuleIdentifier> innerWritableMap = new HashMap<>();
-            deepCopy.put(outerROEntry.getKey(), innerWritableMap);
-            for (Entry<String, ModuleIdentifier> innerROEntry:  outerROEntry.getValue().entrySet()) {
-                innerWritableMap.put(innerROEntry.getKey(), innerROEntry.getValue());
-            }
-        }
-        this.refNames = deepCopy;
         logger.trace("factoryNamesToQNames:{}", this.factoryNamesToQNames);
-        logger.trace("refNames:{}", refNames);
     }
 
 
     @Override
-    public Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
+    public synchronized Set<String> lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException {
         lookupRegistry.checkConfigBeanExists(objectName);
 
         String factoryName = ObjectNameUtil.getFactoryName(objectName);
@@ -183,7 +251,7 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     @Override
-    public String getServiceInterfaceName(String namespace, String localName) {
+    public synchronized String getServiceInterfaceName(String namespace, String localName) {
         Map<String /* localName */, ServiceInterfaceAnnotation> ofNamespace = namespacesToAnnotations.get(namespace);
         if (ofNamespace == null) {
             logger.error("Cannot find namespace {} in {}", namespace, namespacesToAnnotations);
@@ -197,23 +265,19 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
         return sia.value();
     }
 
-
-
     // reading:
 
     @Override
-    public Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
+    public synchronized Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> getServiceMapping() {
         Map<String /* serviceInterfaceName */, Map<String/* refName */, ObjectName>> result = new HashMap<>();
-        for (Entry<String /* qName */, Map<String, ModuleIdentifier>> outerEntry: refNames.entrySet()) {
-            String qName = outerEntry.getKey();
-            Map<String /* refName */, ObjectName> innerMap = new HashMap<>();
-            result.put(qName, innerMap);
-            for (Entry<String /* refName */, ModuleIdentifier> innerEntry: outerEntry.getValue().entrySet()) {
-                ModuleIdentifier moduleIdentifier = innerEntry.getValue();
-                ObjectName on;
-                on = getObjectName(moduleIdentifier);
-                innerMap.put(innerEntry.getKey(), on);
+        for (Entry<ServiceReference, ModuleIdentifier> entry: refNames.entrySet()) {
+            String qName = entry.getKey().getServiceInterfaceName();
+            Map<String /* refName */, ObjectName> innerMap = result.get(qName);
+            if (innerMap == null) {
+                innerMap = new HashMap<>();
+                result.put(qName, innerMap);
             }
+            innerMap.put(entry.getKey().getRefName(), getObjectName(entry.getValue()));
         }
         return result;
     }
@@ -230,116 +294,227 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
-        if (innerMap == null) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refName);
-            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
-        }
-        ModuleIdentifier moduleIdentifier = innerMap.get(refName);
+    public synchronized ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
+        ModuleIdentifier moduleIdentifier = refNames.get(serviceReference);
         if (moduleIdentifier == null) {
-            logger.error("Cannot find refName {} in {}, using qname {}", refName, innerMap, serviceInterfaceName);
-            throw new IllegalArgumentException("Cannot find module based on service reference " + refName);
+            logger.error("Cannot find qname {} and refName {} in {}", serviceInterfaceQName, refName, refName);
+            throw new IllegalArgumentException("Cannot find " + serviceReference);
         }
         return getObjectName(moduleIdentifier);
     }
 
     @Override
-    public  Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        Map<String, ModuleIdentifier> innerMap = refNames.get(serviceInterfaceName);
+    public synchronized Map<String /* refName */, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        Map<String, Map<String, ObjectName>> serviceMapping = getServiceMapping();
+        Map<String, ObjectName> innerMap = serviceMapping.get(serviceInterfaceQName);
         if (innerMap == null) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, refNames);
-            throw new IllegalArgumentException("Cannot find " + serviceInterfaceName);
+            logger.error("Cannot find qname {} in {}", serviceInterfaceQName, refNames);
+            throw new IllegalArgumentException("Cannot find " + serviceInterfaceQName);
         }
-        Map<String /* refName */, ObjectName> result = new HashMap<>();
-        for (Entry<String/* refName */, ModuleIdentifier> entry: innerMap.entrySet()) {
-            ObjectName on = getObjectName(entry.getValue());
-            result.put(entry.getKey(), on);
+        return innerMap;
+    }
+
+    @Override
+    public synchronized ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceQName, refName);
+        if (mBeans.containsKey(serviceReference) == false) {
+            throw new InstanceNotFoundException("Cannot find " + serviceReference);
+        }
+        return getServiceON(serviceReference);
+    }
+
+    @Override
+    public synchronized void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        String actualTransactionName = ObjectNameUtil.getTransactionName(objectName);
+        String expectedTransactionName = serviceReferenceRegistrator.getNullableTransactionName();
+        if (writable & actualTransactionName == null || (writable && actualTransactionName.equals(expectedTransactionName) == false)) {
+            throw new IllegalArgumentException("Mismatched transaction name in " + objectName);
+        }
+        String serviceQName = ObjectNameUtil.getServiceQName(objectName);
+        String referenceName = ObjectNameUtil.getReferenceName(objectName);
+        ServiceReference serviceReference = new ServiceReference(serviceQName, referenceName);
+        if (refNames.containsKey(serviceReference) == false) {
+            logger.warn("Cannot find {} in {}", serviceReference, refNames);
+            throw new InstanceNotFoundException("Service reference not found:" + objectName);
         }
-        return result;
     }
 
     // writing:
 
+    private void assertWritable() {
+        if (writable == false) {
+            throw new IllegalStateException("Cannot write to readable registry");
+        }
+    }
+
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName)  throws InstanceNotFoundException {
+    public synchronized ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON)  throws InstanceNotFoundException {
+        assertWritable();
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
+        return saveServiceReference(serviceReference, moduleON);
+    }
+
+    private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON)
+            throws InstanceNotFoundException{
+        return saveServiceReference(serviceReference, moduleON, false);
+    }
+
+    private synchronized ObjectName saveServiceReference(ServiceReference serviceReference, ObjectName moduleON,
+                                                         boolean skipChecks) throws InstanceNotFoundException {
+
         // make sure it is found
-        lookupRegistry.checkConfigBeanExists(objectName);
-        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+        if (skipChecks == false) {
+            lookupRegistry.checkConfigBeanExists(moduleON);
+        }
+        String factoryName = ObjectNameUtil.getFactoryName(moduleON);
+        String instanceName = ObjectNameUtil.getInstanceName(moduleON);
+        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
+
         // check that service interface name exist
-        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
+        Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(moduleIdentifier.getFactoryName());
         if (serviceInterfaceQNames == null) {
-            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
-            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
+            logger.error("Possible error in code: cannot find factoryName {} in {}, {}", moduleIdentifier.getFactoryName(),
+                    factoryNamesToQNames, moduleIdentifier);
+            throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + moduleIdentifier.getFactoryName());
         }
         // supplied serviceInterfaceName must exist in this collection
-        if (serviceInterfaceQNames.contains(serviceInterfaceName) == false) {
-            logger.error("Cannot find qname {} with factory name {}, found {}", serviceInterfaceName, factoryName, serviceInterfaceQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName + " within factory " + factoryName );
+        if (serviceInterfaceQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
+            logger.error("Cannot find qName {} with factory name {}, found {}", serviceReference.getServiceInterfaceName(), moduleIdentifier.getFactoryName(), serviceInterfaceQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName() + " within factory " + moduleIdentifier.getFactoryName());
         }
-        String instanceName = ObjectNameUtil.getInstanceName(objectName);
-        ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
-        Map<String /* refName */, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
-        // might be null
-        if (ofQName == null) {
-            ofQName = new HashMap<>();
-            refNames.put(serviceInterfaceName, ofQName);
+
+
+        // create service reference object name, put to mBeans
+        ObjectName result = getServiceON(serviceReference);
+        Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> mxBeanEntry = mBeans.get(serviceReference);
+        if (mxBeanEntry == null) {
+            // create dummy mx bean
+            ServiceReferenceMXBeanImpl dummyMXBean = new ServiceReferenceMXBeanImpl(moduleON);
+            ServiceReferenceJMXRegistration dummyMXBeanRegistration;
+            try {
+                dummyMXBeanRegistration = serviceReferenceRegistrator.registerMBean(dummyMXBean, result);
+            } catch (InstanceAlreadyExistsException e) {
+                throw new IllegalStateException("Possible error in code. Cannot register " + result, e);
+            }
+            mBeans.put(serviceReference, createMXBeanEntry(dummyMXBean, dummyMXBeanRegistration));
+        } else {
+            // update
+            mxBeanEntry.getKey().setCurrentImplementation(moduleON);
+        }
+        // save to refNames
+        refNames.put(serviceReference, moduleIdentifier);
+        return result;
+    }
+
+    private Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> createMXBeanEntry(
+            final ServiceReferenceMXBeanImpl mxBean, final ServiceReferenceJMXRegistration registration) {
+        return new Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration>() {
+            @Override
+            public ServiceReferenceMXBeanImpl getKey() {
+                return mxBean;
+            }
+
+            @Override
+            public ServiceReferenceJMXRegistration getValue() {
+                return registration;
+            }
+
+            @Override
+            public ServiceReferenceJMXRegistration setValue(ServiceReferenceJMXRegistration value) {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    private ObjectName getServiceON(ServiceReference serviceReference) {
+        if (writable) {
+            return ObjectNameUtil.createTransactionServiceON(serviceReferenceRegistrator.getNullableTransactionName(),
+                    serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
+        } else {
+            return ObjectNameUtil.createReadOnlyServiceON(serviceReference.getServiceInterfaceName(), serviceReference.getRefName());
         }
-        ofQName.put(refName, moduleIdentifier);
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        // is the qname known?
-        if (allQNames.contains(serviceInterfaceName) == false) {
-            logger.error("Cannot find qname {} in {}", serviceInterfaceName, allQNames);
-            throw new IllegalArgumentException("Cannot find service interface " + serviceInterfaceName);
+    public synchronized void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException{
+        ServiceReference serviceReference = new ServiceReference(serviceInterfaceName, refName);
+        removeServiceReference(serviceReference);
+    }
+
+    private synchronized void removeServiceReference(ServiceReference serviceReference) throws InstanceNotFoundException {
+        logger.debug("Removing service reference {} from {}", serviceReference, this);
+        assertWritable();
+        // is the qName known?
+        if (allQNames.contains(serviceReference.getServiceInterfaceName()) == false) {
+            logger.error("Cannot find qname {} in {}", serviceReference.getServiceInterfaceName(), allQNames);
+            throw new IllegalArgumentException("Cannot find service interface " + serviceReference.getServiceInterfaceName());
+        }
+        ModuleIdentifier removed = refNames.remove(serviceReference);
+        if (removed == null){
+            throw new InstanceNotFoundException("Cannot find " + serviceReference.getServiceInterfaceName());
         }
-        Map<String, ModuleIdentifier> ofQName = refNames.get(serviceInterfaceName);
-        if (ofQName == null) {
-            return false;
+        Entry<ServiceReferenceMXBeanImpl, ServiceReferenceJMXRegistration> entry = mBeans.remove(serviceReference);
+        if (entry == null) {
+            throw new IllegalStateException("Possible code error: cannot remove from mBeans: " + serviceReference);
         }
-        return ofQName.remove(refName) != null;
+        entry.getValue().close();
     }
 
     @Override
-    public void removeAllServiceReferences() {
-        refNames.clear();
+    public synchronized void removeAllServiceReferences() {
+        assertWritable();
+        for (ServiceReference serviceReference: mBeans.keySet()) {
+            try {
+                removeServiceReference(serviceReference);
+            } catch (InstanceNotFoundException e) {
+                throw new IllegalStateException("Possible error in code", e);
+            }
+        }
     }
 
     @Override
-    public boolean removeServiceReferences(ObjectName objectName) throws InstanceNotFoundException {
-        lookupRegistry.checkConfigBeanExists(objectName);
-        String factoryName = ObjectNameUtil.getFactoryName(objectName);
+    public synchronized boolean removeServiceReferences(ObjectName moduleObjectName) throws InstanceNotFoundException {
+        assertWritable();
+        Set<ServiceReference> serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName);
+        for (ServiceReference sr : serviceReferencesLinkingTo) {
+            removeServiceReference(sr);
+        }
+        return serviceReferencesLinkingTo.isEmpty() == false;
+    }
+
+    private synchronized Set<ServiceReference> findServiceReferencesLinkingTo(ObjectName moduleObjectName)  throws InstanceNotFoundException {
+        lookupRegistry.checkConfigBeanExists(moduleObjectName);
+        String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName);
         // check that service interface name exist
         Set<String> serviceInterfaceQNames = factoryNamesToQNames.get(factoryName);
         if (serviceInterfaceQNames == null) {
-            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, objectName);
+            logger.error("Possible error in code: cannot find factoryName {} in {}, object name {}", factoryName, factoryNamesToQNames, moduleObjectName);
             throw new IllegalStateException("Possible error in code: cannot find annotations of existing factory " + factoryName);
         }
-        String instanceName = ObjectNameUtil.getInstanceName(objectName);
+        String instanceName = ObjectNameUtil.getInstanceName(moduleObjectName);
         ModuleIdentifier moduleIdentifier = new ModuleIdentifier(factoryName, instanceName);
-        boolean found = false;
-        for(String qName: serviceInterfaceQNames){
-            Map<String, ModuleIdentifier> ofQName = refNames.get(qName);
-            if (ofQName != null) {
-                for(Iterator<Entry<String, ModuleIdentifier>> it = ofQName.entrySet ().iterator(); it.hasNext();){
-                    Entry<String, ModuleIdentifier> next = it.next();
-                    if (next.getValue().equals(moduleIdentifier)) {
-                        found = true;
-                        it.remove();
-                    }
-                }
+        Set<ServiceReference> result = new HashSet<>();
+        for (Entry<ServiceReference, ModuleIdentifier> entry : refNames.entrySet()) {
+            if (entry.getValue().equals(moduleIdentifier)) {
+                result.add(entry.getKey());
             }
         }
-        return found;
+        return result;
     }
 
+
     @Override
     public String toString() {
         return "ServiceReferenceRegistryImpl{" +
+                "lookupRegistry=" + lookupRegistry +
                 "refNames=" + refNames +
                 ", factoryNamesToQNames=" + factoryNamesToQNames +
                 '}';
     }
+
+    @Override
+    public void close() {
+        serviceReferenceRegistrator.close();
+    }
 }
index 760fe50..925a57b 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -37,12 +38,16 @@ final class DependencyResolverImpl implements DependencyResolver,
     private final TransactionStatus transactionStatus;
     @GuardedBy("this")
     private final Set<ModuleIdentifier> dependencies = new HashSet<>();
+    private final ServiceReferenceReadableRegistry readableRegistry;
 
     DependencyResolverImpl(ModuleIdentifier currentModule,
-            TransactionStatus transactionStatus, ModulesHolder modulesHolder) {
+            TransactionStatus transactionStatus, ModulesHolder modulesHolder,
+            ServiceReferenceReadableRegistry readableRegistry) {
+
         this.name = currentModule;
         this.transactionStatus = transactionStatus;
         this.modulesHolder = modulesHolder;
+        this.readableRegistry = readableRegistry;
     }
 
     /**
@@ -52,7 +57,7 @@ final class DependencyResolverImpl implements DependencyResolver,
     @Override
     public void validateDependency(
             Class<? extends AbstractServiceInterface> expectedServiceInterface,
-            ObjectName dependentModuleReadOnlyON, JmxAttribute jmxAttribute) {
+            ObjectName dependentReadOnlyON, JmxAttribute jmxAttribute) {
 
         transactionStatus.checkNotCommitted();
         if (expectedServiceInterface == null) {
@@ -62,22 +67,26 @@ final class DependencyResolverImpl implements DependencyResolver,
         if (jmxAttribute == null)
             throw new NullPointerException("Parameter 'jmxAttribute' is null");
 
-        JmxAttributeValidationException.checkNotNull(dependentModuleReadOnlyON,
+        JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
                 "is null, " + "expected dependency implementing "
                         + expectedServiceInterface, jmxAttribute);
 
+
+
         // check that objectName belongs to this transaction - this should be
         // stripped
         // in DynamicWritableWrapper
         boolean hasTransaction = ObjectNameUtil
-                .getTransactionName(dependentModuleReadOnlyON) != null;
+                .getTransactionName(dependentReadOnlyON) != null;
         JmxAttributeValidationException.checkCondition(
                 hasTransaction == false,
                 format("ObjectName should not contain "
                         + "transaction name. %s set to %s. ", jmxAttribute,
-                        dependentModuleReadOnlyON), jmxAttribute);
+                        dependentReadOnlyON), jmxAttribute);
+
+        dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
 
-        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(dependentModuleReadOnlyON, ObjectNameUtil
+        ModuleIdentifier moduleIdentifier = ObjectNameUtil.fromON(dependentReadOnlyON, ObjectNameUtil
                 .TYPE_MODULE);
 
         ModuleFactory foundFactory = modulesHolder.findModuleFactory(moduleIdentifier, jmxAttribute);
@@ -90,7 +99,7 @@ final class DependencyResolverImpl implements DependencyResolver,
                             + "Module name is %s : %s, expected service interface %s, dependent module ON %s , "
                             + "attribute %s",
                     foundFactory.getImplementationName(), foundFactory,
-                    expectedServiceInterface, dependentModuleReadOnlyON,
+                    expectedServiceInterface, dependentReadOnlyON,
                     jmxAttribute);
             throw new JmxAttributeValidationException(message, jmxAttribute);
         }
@@ -99,24 +108,35 @@ final class DependencyResolverImpl implements DependencyResolver,
         }
     }
 
+    // transalate from serviceref to module ON
+    private ObjectName translateServiceRefIfPossible(ObjectName dependentReadOnlyON) {
+        if (ObjectNameUtil.isServiceReference(dependentReadOnlyON)) {
+            String serviceQName = ObjectNameUtil.getServiceQName(dependentReadOnlyON);
+            String refName = ObjectNameUtil.getReferenceName(dependentReadOnlyON);
+            dependentReadOnlyON = ObjectNameUtil.withoutTransactionName( // strip again of transaction name
+                    readableRegistry.lookupConfigBeanByServiceInterfaceName(serviceQName, refName));
+        }
+        return dependentReadOnlyON;
+    }
+
     /**
      * {@inheritDoc}
      */
     //TODO: check for cycles
     @Override
-    public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentON,
+    public <T> T resolveInstance(Class<T> expectedType, ObjectName dependentReadOnlyON,
             JmxAttribute jmxAttribute) {
-        if (expectedType == null || dependentON == null || jmxAttribute == null) {
+        if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
             throw new IllegalArgumentException(format(
                     "Null parameters not allowed, got {} {} {}", expectedType,
-                    dependentON, jmxAttribute));
+                    dependentReadOnlyON, jmxAttribute));
         }
-
+        dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
         transactionStatus.checkCommitStarted();
         transactionStatus.checkNotCommitted();
 
         ModuleIdentifier dependentModuleIdentifier = ObjectNameUtil.fromON(
-                dependentON, ObjectNameUtil.TYPE_MODULE);
+                dependentReadOnlyON, ObjectNameUtil.TYPE_MODULE);
         Module module = modulesHolder.findModule(dependentModuleIdentifier,
                 jmxAttribute);
         synchronized (this) {
index 645aab3..afd865c 100644 (file)
@@ -11,6 +11,7 @@ import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.DependencyResolverFactory;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.manager.impl.CommitInfo;
 import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -35,11 +36,13 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
     private final Map<ModuleIdentifier, DependencyResolverImpl> moduleIdentifiersToDependencyResolverMap = new HashMap<>();
     private final ModulesHolder modulesHolder;
     private final TransactionStatus transactionStatus;
+    private final ServiceReferenceReadableRegistry readableRegistry;
 
     public DependencyResolverManager(String transactionName,
-            TransactionStatus transactionStatus) {
+            TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry) {
         this.modulesHolder = new ModulesHolder(transactionName);
         this.transactionStatus = transactionStatus;
+        this.readableRegistry = readableRegistry;
     }
 
     @Override
@@ -48,14 +51,11 @@ public class DependencyResolverManager implements TransactionHolder, DependencyR
     }
 
     public synchronized DependencyResolverImpl getOrCreate(ModuleIdentifier name) {
-        DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap
-                .get(name);
+        DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
         if (dependencyResolver == null) {
             transactionStatus.checkNotCommitted();
-            dependencyResolver = new DependencyResolverImpl(name,
-                    transactionStatus, modulesHolder);
-            moduleIdentifiersToDependencyResolverMap.put(name,
-                    dependencyResolver);
+            dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry);
+            moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
         }
         return dependencyResolver;
     }
index 09bc1f8..d09fc75 100644 (file)
@@ -14,7 +14,7 @@ import javax.management.ObjectName;
 import javax.management.QueryExp;
 import java.util.Set;
 
-public class BaseJMXRegistrator implements AutoCloseable {
+public class BaseJMXRegistrator implements AutoCloseable, NestableJMXRegistrator {
 
     private final InternalJMXRegistrator internalJMXRegistrator;
 
@@ -50,6 +50,11 @@ public class BaseJMXRegistrator implements AutoCloseable {
         return internalJMXRegistrator.getRegisteredObjectNames();
     }
 
+    @Override
+    public InternalJMXRegistrator createChild() {
+        return internalJMXRegistrator.createChild();
+    }
+
     @Override
     public void close() {
         internalJMXRegistrator.close();
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java
new file mode 100644 (file)
index 0000000..ff78e02
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl.jmx;
+
+public interface NestableJMXRegistrator {
+
+    InternalJMXRegistrator createChild();
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java
new file mode 100644 (file)
index 0000000..849f752
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl.jmx;
+
+public class ServiceReference {
+    private final String serviceInterfaceName, refName;
+
+    public ServiceReference(String serviceInterfaceName, String refName) {
+        this.serviceInterfaceName = serviceInterfaceName;
+        this.refName = refName;
+    }
+
+    public String getServiceInterfaceName() {
+        return serviceInterfaceName;
+    }
+
+    public String getRefName() {
+        return refName;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ServiceReference that = (ServiceReference) o;
+
+        if (!refName.equals(that.refName)) return false;
+        if (!serviceInterfaceName.equals(that.serviceInterfaceName)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = serviceInterfaceName.hashCode();
+        result = 31 * result + refName.hashCode();
+        return result;
+    }
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java
new file mode 100644 (file)
index 0000000..759541d
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl.jmx;
+
+import javax.management.ObjectName;
+
+public interface ServiceReferenceMXBean {
+
+    ObjectName getCurrentImplementation();
+
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java
new file mode 100644 (file)
index 0000000..dedeeed
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl.jmx;
+
+import javax.management.ObjectName;
+
+public class ServiceReferenceMXBeanImpl implements ServiceReferenceMXBean {
+    private ObjectName currentImplementation;
+
+    public ServiceReferenceMXBeanImpl(ObjectName currentImplementation) {
+        this.currentImplementation = currentImplementation;
+    }
+
+    @Override
+    public ObjectName getCurrentImplementation() {
+        return currentImplementation;
+    }
+
+    public void setCurrentImplementation(ObjectName currentImplementation) {
+        this.currentImplementation = currentImplementation;
+    }
+}
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java
new file mode 100644 (file)
index 0000000..160ee18
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl.jmx;
+
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+public interface ServiceReferenceRegistrator extends AutoCloseable {
+
+    public String getNullableTransactionName();
+
+    ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object,
+                                                          ObjectName on) throws InstanceAlreadyExistsException;
+
+    @Override
+    void close();
+
+    public static class ServiceReferenceJMXRegistration implements AutoCloseable {
+        private final InternalJMXRegistration registration;
+
+        ServiceReferenceJMXRegistration(InternalJMXRegistration registration) {
+            this.registration = registration;
+        }
+
+        @Override
+        public void close() {
+            registration.close();
+        }
+    }
+
+    public static interface ServiceReferenceTransactionRegistratorFactory {
+        public ServiceReferenceRegistrator create();
+    }
+
+    public static class ServiceReferenceRegistratorImpl implements ServiceReferenceRegistrator {
+        private final InternalJMXRegistrator currentJMXRegistrator;
+        private final String nullableTransactionName;
+
+        public ServiceReferenceRegistratorImpl(NestableJMXRegistrator parentRegistrator, String nullableTransactionName){
+            currentJMXRegistrator = parentRegistrator.createChild();
+            this.nullableTransactionName = nullableTransactionName;
+        }
+
+        public String getNullableTransactionName() {
+            return nullableTransactionName;
+        }
+
+
+        public ServiceReferenceJMXRegistration registerMBean(ServiceReferenceMXBeanImpl object,
+                                                             ObjectName on) throws InstanceAlreadyExistsException {
+            String actualTransactionName = ObjectNameUtil.getTransactionName(on);
+            boolean broken = false;
+            broken |= (nullableTransactionName == null) != (actualTransactionName == null);
+            broken |= (nullableTransactionName != null) && nullableTransactionName.equals(actualTransactionName) == false;
+            if (broken) {
+                throw new IllegalArgumentException("Transaction name mismatch between expected "
+                        + nullableTransactionName + ", got " + actualTransactionName + " in " + on);
+            }
+            if (ObjectNameUtil.isServiceReference(on) == false) {
+                throw new IllegalArgumentException("Invalid type of " + on);
+            }
+            return new ServiceReferenceJMXRegistration(currentJMXRegistrator.registerMBean(object, on));
+        }
+
+
+        @Override
+        public void close() {
+            currentJMXRegistrator.close();
+        }
+        public static interface ServiceReferenceTransactionRegistratorFactory {
+            public ServiceReferenceRegistrator create();
+        }
+    }
+
+
+    public static class ServiceReferenceTransactionRegistratorFactoryImpl implements ServiceReferenceTransactionRegistratorFactory {
+        private final NestableJMXRegistrator parentRegistrator;
+        private final String nullableTransactionName;
+
+        public ServiceReferenceTransactionRegistratorFactoryImpl(TransactionModuleJMXRegistrator parentRegistrator,
+                                                             String nullableTransactionName) {
+            this.parentRegistrator = parentRegistrator;
+            this.nullableTransactionName = nullableTransactionName;
+        }
+
+        public ServiceReferenceTransactionRegistratorFactoryImpl(BaseJMXRegistrator baseJMXRegistrator) {
+            this.parentRegistrator = baseJMXRegistrator;
+            this.nullableTransactionName = null;
+        }
+
+        public ServiceReferenceRegistrator create() {
+            return new ServiceReferenceRegistratorImpl(parentRegistrator, nullableTransactionName);
+        }
+    }
+}
index 546adb0..238fd24 100644 (file)
@@ -17,14 +17,14 @@ import javax.management.QueryExp;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator.InternalJMXRegistration;
 
-public class TransactionModuleJMXRegistrator implements Closeable {
-    private final InternalJMXRegistrator childJMXRegistrator;
+public class TransactionModuleJMXRegistrator implements Closeable, NestableJMXRegistrator {
+    private final InternalJMXRegistrator currentJMXRegistrator;
     private final String transactionName;
 
     public TransactionModuleJMXRegistrator(
             InternalJMXRegistrator internalJMXRegistrator,
             String transactionName) {
-        this.childJMXRegistrator = internalJMXRegistrator.createChild();
+        this.currentJMXRegistrator = internalJMXRegistrator.createChild();
         this.transactionName = transactionName;
     }
 
@@ -44,21 +44,29 @@ public class TransactionModuleJMXRegistrator implements Closeable {
 
     public TransactionModuleJMXRegistration registerMBean(Object object,
             ObjectName on) throws InstanceAlreadyExistsException {
-        if (!transactionName.equals(ObjectNameUtil.getTransactionName(on)))
-            throw new IllegalArgumentException(
-                    "Transaction name mismatch between expected "
+        if (transactionName.equals(ObjectNameUtil.getTransactionName(on)) == false) {
+            throw new IllegalArgumentException("Transaction name mismatch between expected "
                             + transactionName + " " + "and " + on);
-        ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+        }
+        ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_MODULE);
         return new TransactionModuleJMXRegistration(
-                childJMXRegistrator.registerMBean(object, on));
+                currentJMXRegistrator.registerMBean(object, on));
     }
 
     public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
-        return childJMXRegistrator.queryNames(name, query);
+        return currentJMXRegistrator.queryNames(name, query);
     }
 
     @Override
     public void close() {
-        childJMXRegistrator.close();
+        currentJMXRegistrator.close();
+    }
+
+    public String getTransactionName() {
+        return transactionName;
+    }
+
+    public InternalJMXRegistrator createChild() {
+        return currentJMXRegistrator.createChild();
     }
 }
index a7e3fa6..b0588a0 100644 (file)
@@ -14,6 +14,8 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleF
 import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
 import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
@@ -84,6 +86,8 @@ public abstract class AbstractConfigTest extends
     public final void cleanUpConfigTransactionManagerImpl() {
         configRegistryJMXRegistrator.close();
         configRegistry.close();
+        TestingFixedThreadPool.cleanUp();
+        TestingScheduledThreadPoolImpl.cleanUp();
     }
 
     /**
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java
new file mode 100644 (file)
index 0000000..6d0b340
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.manager.impl;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.manager.impl.jmx.ServiceReferenceMXBean;
+import org.opendaylight.controller.config.manager.testingservices.parallelapsp.TestingParallelAPSPModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.parallelapsp.test.AbstractParallelAPSPTest;
+import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolModuleFactory;
+import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
+import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+import javax.management.Attribute;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMX;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.controller.config.api.jmx.ObjectNameUtil.withoutTransactionName;
+
+public class ServiceReferenceRegistryImplTest extends AbstractParallelAPSPTest {
+
+
+    @Before
+    public void setUp() {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
+                new TestingFixedThreadPoolModuleFactory(),
+                new TestingParallelAPSPModuleFactory(),
+                new TestingScheduledThreadPoolModuleFactory()));
+    }
+
+    @Override
+    protected String getThreadPoolImplementationName() {
+        return TestingFixedThreadPoolModuleFactory.NAME;
+    }
+
+    @Test
+    public void test() throws Exception {
+        ConfigTransactionJMXClient transaction1 = configRegistryClient.createTransaction();
+        // create fixed1
+        int fixedNrOfThreads = 20, scheduledNrOfThreads = 30;
+
+        ObjectName fixedTPTransactionON = transaction1.createModule(getThreadPoolImplementationName(), fixed1);
+        platformMBeanServer.setAttribute(fixedTPTransactionON, new Attribute("ThreadCount", fixedNrOfThreads));
+
+        ObjectName scheduledTPTransactionON = transaction1.createModule(
+                TestingScheduledThreadPoolModuleFactory.NAME, "scheduled1");
+        platformMBeanServer.setAttribute(scheduledTPTransactionON, new Attribute("ThreadCount",
+                scheduledNrOfThreads));
+
+        String refName = "ref";
+        ObjectName serviceReference = transaction1.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+                fixedTPTransactionON);
+        // create apsp-parallel
+        createParallelAPSP(transaction1, serviceReference);
+        transaction1.commit();
+        // check fixed1 is used
+        ServiceReferenceMXBean serviceReferenceMXBean = JMX.newMXBeanProxy(platformMBeanServer,
+                withoutTransactionName(serviceReference), ServiceReferenceMXBean.class);
+        assertEquals(withoutTransactionName(fixedTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
+        checkApspThreadCount(fixedNrOfThreads);
+
+        // switch reference to scheduled
+        ConfigTransactionJMXClient transaction2 = configRegistryClient.createTransaction();
+        transaction2.saveServiceReference(TestingThreadPoolServiceInterface.QNAME, refName,
+                ObjectNameUtil.withTransactionName(scheduledTPTransactionON, transaction2.getTransactionName()));
+        transaction2.commit();
+        // check scheduled is used
+        checkApspThreadCount(scheduledNrOfThreads);
+        // check that dummy MXBean points to scheduled
+        assertEquals(withoutTransactionName(scheduledTPTransactionON), serviceReferenceMXBean.getCurrentImplementation());
+
+        // empty transaction
+        configRegistryClient.createTransaction().commit();
+
+        // get service mapping
+        Map<String,Map<String,ObjectName>> serviceMapping = configRegistryClient.getServiceMapping();
+        Map<String,Map<String,ObjectName>> expectedMapping = ImmutableMap.of(TestingThreadPoolServiceInterface.QNAME,
+                (Map<String, ObjectName>)ImmutableMap.of(refName, withoutTransactionName(scheduledTPTransactionON)));
+        assertEquals(expectedMapping, serviceMapping);
+
+        // destroy all
+        ConfigTransactionJMXClient transaction4 = configRegistryClient.createTransaction();
+        Set<ObjectName> objectNames = transaction4.lookupConfigBeans();
+        for(ObjectName on: objectNames) {
+            transaction4.destroyModule(on);
+        }
+        transaction4.commit();
+
+        serviceMapping = configRegistryClient.getServiceMapping();
+        assertTrue(serviceMapping.isEmpty());
+    }
+
+    private void checkApspThreadCount(int fixedNrOfThreads) throws MBeanException, AttributeNotFoundException,
+            InstanceNotFoundException, ReflectionException {
+        ObjectName apspON = ObjectNameUtil.createReadOnlyModuleON(TestingParallelAPSPModuleFactory.NAME, apsp1);
+        assertEquals(fixedNrOfThreads, platformMBeanServer.getAttribute(apspON, "MaxNumberOfThreads"));
+    }
+}
index 65b0105..31e70bd 100644 (file)
@@ -20,6 +20,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.JmxAttribute;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.ModuleInternalTransactionalInfo;
 import org.opendaylight.controller.config.manager.impl.TransactionStatus;
@@ -40,7 +41,8 @@ public class DependencyResolverManagerTest {
     @Before
     public void setUp() {
         transactionStatus = mock(TransactionStatus.class);
-        tested = new DependencyResolverManager("txName", transactionStatus);
+        ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
+        tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry);
         doNothing().when(transactionStatus).checkCommitStarted();
         doNothing().when(transactionStatus).checkNotCommitted();
     }
index 0338039..fe32289 100644 (file)
@@ -7,16 +7,19 @@
  */
 package org.opendaylight.controller.config.manager.impl.util;
 
-import java.util.Set;
-
-import javax.management.ObjectName;
-
+import com.google.common.base.Throwables;
+import com.google.common.collect.Sets;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
 
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
+import javax.management.ObjectName;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 
 public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
     private Set<ObjectName> unregisterONs;
@@ -37,7 +40,26 @@ public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
             }
         }
         if (lastException != null) {
-            Throwables.propagate(lastException);
+            throw Throwables.propagate(lastException);
         }
     }
+
+    @Test
+    public void testQuotation() throws Exception {
+        String serviceQName = "(namespace?revision=r)qname";
+        String refName = "refName";
+        String transaction = "transaction";
+        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+
+        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+
+    }
 }
index 3c55f4d..f4ba5ef 100644 (file)
@@ -114,8 +114,7 @@ public class TestingParallelAPSPModule implements Module,
 
             if (oldInstance != null) {
                 // changing thread pool is not supported
-                boolean reuse = threadPoolInstance.equals(oldInstance
-                        .getThreadPool());
+                boolean reuse = threadPoolInstance == oldInstance.getThreadPool();
                 if (reuse) {
                     logger.debug("Reusing old instance");
                     instance = oldInstance;
index 3d9d524..f979a45 100644 (file)
@@ -16,11 +16,11 @@ import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.ObjectName;
 
-abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
+public abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
     protected final String fixed1 = "fixed1";
     protected final String apsp1 = "apsp-parallel";
 
-    abstract String getThreadPoolImplementationName();
+    protected abstract String getThreadPoolImplementationName();
 
     protected ObjectName createParallelAPSP(
             ConfigTransactionJMXClient transaction, ObjectName threadPoolON)
@@ -36,6 +36,7 @@ abstract class AbstractParallelAPSPTest extends AbstractConfigTest {
 
     protected ObjectName createFixed1(ConfigTransactionJMXClient transaction,
             int numberOfThreads) throws InstanceAlreadyExistsException {
+
         ObjectName name = transaction.createModule(
                 getThreadPoolImplementationName(), fixed1);
 
index 77d1f8b..2b9760c 100644 (file)
@@ -36,7 +36,7 @@ public class TestingScheduledThreadPoolModule implements Module,
     @Nullable
     private final TestingScheduledThreadPoolImpl oldInstance;
 
-    private final int threadCount = 10;
+    private int threadCount = 10;
     private TestingScheduledThreadPoolImpl instance;
     private RootRuntimeBeanRegistrator runtimeBeanRegistrator;
     private boolean recreate;
@@ -68,6 +68,11 @@ public class TestingScheduledThreadPoolModule implements Module,
         return threadCount;
     }
 
+    @Override
+    public void setThreadCount(int threadCount) {
+        this.threadCount = threadCount;
+    }
+
     @Override
     public Closeable getInstance() {
         assertNotNull(runtimeBeanRegistrator);
index 91a4cff..0a886e5 100644 (file)
@@ -11,8 +11,9 @@ import org.opendaylight.controller.config.api.annotations.AbstractServiceInterfa
 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingThreadPoolIfc;
 
-@ServiceInterfaceAnnotation(value = "testing-threadpool", osgiRegistrationType = TestingThreadPoolIfc.class,
-    namespace = "ns", revision = "foo", localName = "bar")
+@ServiceInterfaceAnnotation(value = TestingThreadPoolServiceInterface.QNAME, osgiRegistrationType = TestingThreadPoolIfc.class,
+    namespace = "ns", revision = "foo", localName = "testing-threadpool")
 public interface TestingThreadPoolServiceInterface extends
         AbstractServiceInterface {
+    public static final String QNAME = "(ns?revision=foo)testing-threadpool";
 }
index 8badb75..549ff9f 100644 (file)
@@ -148,8 +148,8 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return configRegistryMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -158,8 +158,8 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -201,4 +201,15 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient {
     public Set<String> getAvailableModuleFactoryQNames() {
         return configRegistryMXBeanProxy.getAvailableModuleFactoryQNames();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return configRegistryMXBeanProxy.getServiceReference(serviceInterfaceQName, refName);
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        configRegistryMXBeanProxy.checkServiceReferenceExists(objectName);
+    }
+
 }
index 0db1e5b..e683d91 100644 (file)
@@ -164,13 +164,13 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
-        configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName,objectName);
+    public ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.saveServiceReference(serviceInterfaceName,refName, moduleON);
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
-        return configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName);
+    public void removeServiceReference(String serviceInterfaceName, String refName) throws InstanceNotFoundException{
+        configTransactionControllerMXBeanProxy.removeServiceReference(serviceInterfaceName, refName);
     }
 
     @Override
@@ -179,8 +179,8 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
-        return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceName, refName);
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
+        return configTransactionControllerMXBeanProxy.lookupConfigBeanByServiceInterfaceName(serviceInterfaceQName, refName);
     }
 
     @Override
@@ -189,8 +189,8 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
-        return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName);
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
+        return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName);
     }
 
     @Override
@@ -208,6 +208,16 @@ public class ConfigTransactionJMXClient implements ConfigTransactionClient {
         return configTransactionControllerMXBeanProxy.removeServiceReferences(objectName);
     }
 
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        return configTransactionControllerMXBeanProxy.getServiceReference(serviceInterfaceQName, refName);
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        configTransactionControllerMXBeanProxy.checkServiceReferenceExists(objectName);
+    }
+
     @Override
     public void validateBean(ObjectName configBeanON)
             throws ValidationException {
index 6534171..e0d4c85 100644 (file)
@@ -150,7 +150,7 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -160,7 +160,7 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
         throw new UnsupportedOperationException();
     }
 
@@ -178,4 +178,14 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean {
     public Set<String> getAvailableModuleFactoryQNames() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index 44eb73a..4d16f51 100644 (file)
@@ -117,12 +117,12 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public void saveServiceReference(String serviceInterfaceName, String refName, ObjectName objectName) throws InstanceNotFoundException {
+    public ObjectName saveServiceReference(String serviceInterfaceName, String refName, ObjectName moduleON) throws InstanceNotFoundException {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public boolean removeServiceReference(String serviceInterfaceName, String refName) {
+    public void removeServiceReference(String serviceInterfaceName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -132,7 +132,7 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceName, String refName) {
+    public ObjectName lookupConfigBeanByServiceInterfaceName(String serviceInterfaceQName, String refName) {
         throw new UnsupportedOperationException();
     }
 
@@ -142,7 +142,7 @@ public class TestingConfigTransactionController implements
     }
 
     @Override
-    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) {
+    public Map<String, ObjectName> lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) {
         throw new UnsupportedOperationException();
     }
 
@@ -165,4 +165,14 @@ public class TestingConfigTransactionController implements
     public Set<String> getAvailableModuleFactoryQNames() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public ObjectName getServiceReference(String serviceInterfaceQName, String refName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void checkServiceReferenceExists(ObjectName objectName) throws InstanceNotFoundException {
+        throw new UnsupportedOperationException();
+    }
 }
index f7197d1..b32e8bc 100644 (file)
@@ -150,10 +150,7 @@ package ${packageName};
         }
         <#list moduleFields as field>
         <#if field.dependent==true>
-        if (${field.name}Dependency == null) {
-            if (other.${field.name}Dependency != null)
-                return false;
-        } else if (!${field.name}Dependency.equals(other.${field.name}Dependency)) {
+        if (${field.name}Dependency != other.${field.name}Dependency) { // reference to dependency must be same
             return false;
         }
         <#else>

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.