From 81282cf3711693da7dde667c6bbf18cb40e81ad0 Mon Sep 17 00:00:00 2001 From: Tomas Olvecky Date: Mon, 16 Dec 2013 11:39:41 +0100 Subject: [PATCH] Persist service references as separate MBeans. 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 --- .../api/ConfigTransactionController.java | 2 +- .../controller/config/api/LookupRegistry.java | 3 +- .../api/ServiceReferenceReadableRegistry.java | 19 +- .../api/ServiceReferenceWritableRegistry.java | 5 +- .../config/api/jmx/ObjectNameUtil.java | 136 +++++-- ...eableServiceReferenceReadableRegistry.java | 17 + .../manager/impl/ConfigRegistryImpl.java | 39 +- .../impl/ConfigTransactionControllerImpl.java | 34 +- .../impl/ConfigTransactionLookupRegistry.java | 7 + .../manager/impl/ModuleInternalInfo.java | 7 +- .../impl/ServiceReferenceRegistryImpl.java | 371 +++++++++++++----- .../DependencyResolverImpl.java | 44 ++- .../DependencyResolverManager.java | 14 +- .../manager/impl/jmx/BaseJMXRegistrator.java | 7 +- .../impl/jmx/NestableJMXRegistrator.java | 13 + .../manager/impl/jmx/ServiceReference.java | 45 +++ .../impl/jmx/ServiceReferenceMXBean.java | 16 + .../impl/jmx/ServiceReferenceMXBeanImpl.java | 27 ++ .../impl/jmx/ServiceReferenceRegistrator.java | 103 +++++ .../jmx/TransactionModuleJMXRegistrator.java | 28 +- .../manager/impl/AbstractConfigTest.java | 4 + .../ServiceReferenceRegistryImplTest.java | 116 ++++++ .../DependencyResolverManagerTest.java | 4 +- .../manager/impl/util/ObjectNameUtilTest.java | 36 +- .../TestingParallelAPSPModule.java | 3 +- .../test/AbstractParallelAPSPTest.java | 5 +- .../test/DependentWiringTest.java | 2 +- .../test/MockedDependenciesTest.java | 2 +- ...ngScheduledThreadPoolConfigBeanMXBean.java | 3 + .../TestingScheduledThreadPoolModule.java | 7 +- .../TestingThreadPoolServiceInterface.java | 5 +- .../config/util/ConfigRegistryJMXClient.java | 19 +- .../util/ConfigTransactionJMXClient.java | 26 +- .../config/util/TestingConfigRegistry.java | 14 +- .../TestingConfigTransactionController.java | 18 +- .../freeMarker/module_abs_template_new.ftl | 5 +- 36 files changed, 976 insertions(+), 230 deletions(-) create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java create mode 100644 opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java create mode 100644 opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java index c257e55dc0..264751318c 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ConfigTransactionController.java @@ -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. diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java index 772617e97d..376ecdb52a 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/LookupRegistry.java @@ -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 getAvailableModuleFactoryQNames(); diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java index f84fcd48c9..d7e94e8a76 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceReadableRegistry.java @@ -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> getServiceMapping(); + Map> 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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName); + Map 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; + } diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java index f3d6d16d6c..fa2aa1f56e 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/ServiceReferenceWritableRegistry.java @@ -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. diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java index cc1d89761c..3baa1039e0 100644 --- a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java @@ -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 attribs) { + public static ObjectName createON(String domain, Map attribs) { Hashtable 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 onParams = createModuleON(moduleName, instanceName); + String moduleName, String instanceName) { + Map 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 onParams = createServiceMap(serviceQName, refName); + return createON(ON_DOMAIN, onParams); + } + + public static ObjectName createTransactionServiceON(String transactionName, String serviceQName, String refName) { + Map 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 createServiceON(String transactionName, String serviceQName, + String refName) { + Map result = new HashMap<>(createServiceMap(serviceQName, refName)); + result.put(TRANSACTION_NAME_KEY, transactionName); + return result; + } + + private static Map createServiceMap(String serviceQName, + String refName) { + Map 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 onParams = createModuleON(moduleName, instanceName); + String instanceName) { + Map onParams = createModuleMap(moduleName, instanceName); return createON(ON_DOMAIN, onParams); } - private static Map createModuleON(String moduleName, - String instanceName) { + private static Map createModuleMap(String moduleName, + String instanceName) { Map 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 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 allProperties = getAdditionalProperties(inputON); - Map outputProperties = new HashMap<>(createModuleON(moduleName, instanceName)); - - for(Entry entry: allProperties.entrySet()) { + for (Entry 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 additionalProperties = getAdditionalProperties(inputON); + additionalProperties.put(TRANSACTION_NAME_KEY, transactionName); + return createON(inputON.getDomain(), additionalProperties); + + } + private static void assertDoesNotContain( Map additionalProperties, String key) { if (additionalProperties.containsKey(key)) { @@ -165,7 +240,7 @@ public class ObjectNameUtil { } public static ObjectName createRuntimeBeanName(String moduleName, - String instanceName, Map additionalProperties) { + String instanceName, Map 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 index 0000000000..8c325079d3 --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/CloseableServiceReferenceReadableRegistry.java @@ -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(); + +} diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java index e3311c747f..19231705d1 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigRegistryImpl.java @@ -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 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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { - return readableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + public synchronized Map 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 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); } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java index 17ce078154..e0d1a42661 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionControllerImpl.java @@ -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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { - return writableSRRegistry.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + public synchronized Map 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); + } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java index 12db6c8f89..a7d426ebdd 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ConfigTransactionLookupRegistry.java @@ -117,6 +117,13 @@ class ConfigTransactionLookupRegistry implements LookupRegistry, Closeable { return ModuleQNameUtil.getQNames(allCurrentFactories); } + + @Override + public String toString() { + return "ConfigTransactionLookupRegistry{" + + "transactionIdentifier=" + transactionIdentifier + + '}'; + } } interface TransactionJMXRegistratorFactory { diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java index 14a706dd9b..941aec1096 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ModuleInternalInfo.java @@ -90,11 +90,6 @@ public class ModuleInternalInfo implements Comparable, 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, } public DestroyedModule toDestroyedModule() { - return new DestroyedModule(getName(), + return new DestroyedModule(getIdentifier(), getReadableModule().getInstance(), getModuleJMXRegistrator(), getOsgiRegistration(), getOrderingIdx()); } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java index 7fedcdf71c..0faa32b7dc 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImpl.java @@ -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 factories; private final Map> 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> namespacesToAnnotations; // all Service Interface qNames for sanity checking private final Set allQNames; // actual reference database - private final Map> refNames; + private final Map refNames = new HashMap<>(); + private final boolean writable; + private final Map> 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 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.emptyMap(), lookupRegistry, - Collections.>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> currentlyRegisteredFactories) { + ConfigTransactionLookupRegistry txLookupRegistry, + Map> currentlyRegisteredFactories) { + if (txLookupRegistry == null) { + throw new IllegalArgumentException("txLookupRegistry is null"); + } ServiceReferenceRegistryImpl old = (ServiceReferenceRegistryImpl) oldReadableRegistry; Map 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> 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 extractFactoriesMap(Map> currentlyRegisteredFactories) { @@ -114,9 +187,14 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg } private ServiceReferenceRegistryImpl(Map factories, LookupRegistry lookupRegistry, - Map> refNamesToCopy) { + ServiceReferenceTransactionRegistratorFactory serviceReferenceRegistratorFactory, + boolean writable) { this.factories = factories; + this.writable = writable; this.lookupRegistry = lookupRegistry; + + this.serviceReferenceRegistrator = serviceReferenceRegistratorFactory.create(); + Map> factoryNamesToQNames = new HashMap<>(); Set allAnnotations = new HashSet<>(); Set allQNames = new HashSet<>(); @@ -154,22 +232,12 @@ public class ServiceReferenceRegistryImpl implements ServiceReferenceReadableReg } this.namespacesToAnnotations = Collections.unmodifiableMap(namespacesToAnnotations); // copy refNames - Map> deepCopy = new HashMap<>(); - for (Entry> outerROEntry: refNamesToCopy.entrySet()) { - Map innerWritableMap = new HashMap<>(); - deepCopy.put(outerROEntry.getKey(), innerWritableMap); - for (Entry 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 lookupServiceInterfaceNames(ObjectName objectName) throws InstanceNotFoundException { + public synchronized Set 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 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> getServiceMapping() { + public synchronized Map> getServiceMapping() { Map> result = new HashMap<>(); - for (Entry> outerEntry: refNames.entrySet()) { - String qName = outerEntry.getKey(); - Map innerMap = new HashMap<>(); - result.put(qName, innerMap); - for (Entry innerEntry: outerEntry.getValue().entrySet()) { - ModuleIdentifier moduleIdentifier = innerEntry.getValue(); - ObjectName on; - on = getObjectName(moduleIdentifier); - innerMap.put(innerEntry.getKey(), on); + for (Entry entry: refNames.entrySet()) { + String qName = entry.getKey().getServiceInterfaceName(); + Map 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 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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { - Map innerMap = refNames.get(serviceInterfaceName); + public synchronized Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) { + Map> serviceMapping = getServiceMapping(); + Map 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 result = new HashMap<>(); - for (Entry 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 serviceInterfaceQNames = factoryNamesToQNames.get(factoryName); + Set 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 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 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 createMXBeanEntry( + final ServiceReferenceMXBeanImpl mxBean, final ServiceReferenceJMXRegistration registration) { + return new Entry() { + @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 ofQName = refNames.get(serviceInterfaceName); - if (ofQName == null) { - return false; + Entry 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 serviceReferencesLinkingTo = findServiceReferencesLinkingTo(moduleObjectName); + for (ServiceReference sr : serviceReferencesLinkingTo) { + removeServiceReference(sr); + } + return serviceReferencesLinkingTo.isEmpty() == false; + } + + private synchronized Set findServiceReferencesLinkingTo(ObjectName moduleObjectName) throws InstanceNotFoundException { + lookupRegistry.checkConfigBeanExists(moduleObjectName); + String factoryName = ObjectNameUtil.getFactoryName(moduleObjectName); // check that service interface name exist Set 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 ofQName = refNames.get(qName); - if (ofQName != null) { - for(Iterator> it = ofQName.entrySet ().iterator(); it.hasNext();){ - Entry next = it.next(); - if (next.getValue().equals(moduleIdentifier)) { - found = true; - it.remove(); - } - } + Set result = new HashSet<>(); + for (Entry 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(); + } } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java index 760fe50e28..925a57b044 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverImpl.java @@ -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 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 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 resolveInstance(Class expectedType, ObjectName dependentON, + public T resolveInstance(Class 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) { diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java index 645aab37ff..afd865c4fc 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManager.java @@ -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 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; } diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java index 09bc1f818f..d09fc75d73 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/BaseJMXRegistrator.java @@ -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 index 0000000000..ff78e0257b --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/NestableJMXRegistrator.java @@ -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 index 0000000000..849f75234f --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReference.java @@ -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 index 0000000000..759541dc26 --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBean.java @@ -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 index 0000000000..dedeeed789 --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceMXBeanImpl.java @@ -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 index 0000000000..160ee1888a --- /dev/null +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/ServiceReferenceRegistrator.java @@ -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); + } + } +} diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java index 546adb0d89..238fd2447e 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/jmx/TransactionModuleJMXRegistrator.java @@ -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 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(); } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java index a7e3fa6c6f..b0588a0903 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/AbstractConfigTest.java @@ -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 index 0000000000..6d0b340cd3 --- /dev/null +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/ServiceReferenceRegistryImplTest.java @@ -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> serviceMapping = configRegistryClient.getServiceMapping(); + Map> expectedMapping = ImmutableMap.of(TestingThreadPoolServiceInterface.QNAME, + (Map)ImmutableMap.of(refName, withoutTransactionName(scheduledTPTransactionON))); + assertEquals(expectedMapping, serviceMapping); + + // destroy all + ConfigTransactionJMXClient transaction4 = configRegistryClient.createTransaction(); + Set 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")); + } +} diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java index 65b010532b..31e70bd84e 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/dependencyresolver/DependencyResolverManagerTest.java @@ -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(); } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java index 03380392e8..fe322895ab 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java @@ -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 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)); + + } } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java index 3c55f4dcc0..f4ba5ef887 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/TestingParallelAPSPModule.java @@ -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; diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java index 3d9d5245ef..f979a45dd1 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/AbstractParallelAPSPTest.java @@ -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); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java index f9a11301e1..978d375cd2 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/DependentWiringTest.java @@ -48,7 +48,7 @@ public class DependentWiringTest extends AbstractParallelAPSPTest { } @Override - String getThreadPoolImplementationName() { + protected String getThreadPoolImplementationName() { return TestingFixedThreadPoolModuleFactory.NAME; } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java index e385136abf..642f526efd 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/parallelapsp/test/MockedDependenciesTest.java @@ -111,7 +111,7 @@ public class MockedDependenciesTest extends AbstractParallelAPSPTest { } @Override - String getThreadPoolImplementationName() { + protected String getThreadPoolImplementationName() { return threadPoolImplementationName; } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java index df86232906..6ccb2418f0 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolConfigBeanMXBean.java @@ -15,4 +15,7 @@ public interface TestingScheduledThreadPoolConfigBeanMXBean extends public boolean isRecreate(); public void setRecreate(boolean recreate); + + public void setThreadCount(int threadCount); + } diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java index 77d1f8bbdf..2b9760cfc4 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/scheduledthreadpool/TestingScheduledThreadPoolModule.java @@ -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); diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java index 91a4cff415..0a886e5fb0 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/seviceinterface/TestingThreadPoolServiceInterface.java @@ -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"; } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java index 8badb75f05..549ff9ffcf 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigRegistryJMXClient.java @@ -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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { - return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) { + return configRegistryMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceQName); } @Override @@ -201,4 +201,15 @@ public class ConfigRegistryJMXClient implements ConfigRegistryClient { public Set 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); + } + } diff --git a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java index 0db1e5b822..e683d915ba 100644 --- a/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java +++ b/opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/ConfigTransactionJMXClient.java @@ -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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { - return configTransactionControllerMXBeanProxy.lookupServiceReferencesByServiceInterfaceName(serviceInterfaceName); + public Map 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 { diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java index 65341714df..e0d4c85943 100644 --- a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java +++ b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigRegistry.java @@ -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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) { throw new UnsupportedOperationException(); } @@ -178,4 +178,14 @@ public class TestingConfigRegistry implements ConfigRegistryMXBean { public Set 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(); + } } diff --git a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java index 44eb73af79..4d16f51ae5 100644 --- a/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java +++ b/opendaylight/config/config-util/src/test/java/org/opendaylight/controller/config/util/TestingConfigTransactionController.java @@ -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 lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceName) { + public Map lookupServiceReferencesByServiceInterfaceName(String serviceInterfaceQName) { throw new UnsupportedOperationException(); } @@ -165,4 +165,14 @@ public class TestingConfigTransactionController implements public Set 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(); + } } diff --git a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl index f7197d1582..b32e8bc130 100644 --- a/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl +++ b/opendaylight/config/yang-jmx-generator-plugin/src/main/resources/freeMarker/module_abs_template_new.ftl @@ -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> -- 2.36.6