From dceb9db7853dabfbd4abdfb3d886a79871097831 Mon Sep 17 00:00:00 2001 From: Tom Pantelis Date: Mon, 28 Mar 2016 13:44:11 -0400 Subject: [PATCH] Modify config Module impls to co-exist with blueprint Modified various config system Module implementation classes which have corresponding instances created and advertised via blueprint to obtain the instance in createInstance from the OSGi registry. The instance may not be available yet so it will wait. I added a WaitingServiceTracker class to encapsulate this logic using a ServiceTracker. For those modules that don't advertise services, createInstance simply returns a noop AutoCloseable since the components are created via blueprint. I also added the new disable-osgi-service-registration flag to the corresponding service yang identities to prevent the CSS from duplicating the service registrations. This patch also adds the blueprint bundle to the mdsal features and "turns on" blueprint. Change-Id: I60099c82a2a248fc233ad930c4808d6ab19ea881 Signed-off-by: Tom Pantelis --- features/mdsal/pom.xml | 8 +- features/mdsal/src/main/features/features.xml | 1 + .../framework/GlobalEventExecutorUtil.java | 37 ---- .../NeverReconnectStrategyModuleTest.java | 108 ------------ ...econnectImmediatelyStrategyModuleTest.java | 107 ------------ .../TimedReconnectStrategyModuleTest.java | 164 ------------------ .../api/osgi/ServiceNotFoundException.java | 25 +++ .../api/osgi/WaitingServiceTracker.java | 102 +++++++++++ .../AutoCloseableEventExecutor.java | 26 ++- .../GlobalEventExecutorModule.java | 17 +- .../GlobalEventExecutorModuleFactory.java | 10 +- .../GlobalEventExecutorModuleTest.java | 22 ++- .../config/netty-threadgroup-config/pom.xml | 1 - .../threadgroup/NettyThreadgroupModule.java | 35 +++- .../NettyThreadgroupModuleFactory.java | 22 ++- .../NettyThreadgroupModuleTest.java | 21 ++- .../netty/timer/HashedWheelTimerModule.java | 33 +++- .../timer/HashedWheelTimerModuleFactory.java | 24 ++- .../timer/HashedWheelTimerModuleTest.java | 22 ++- .../binding/test/util/BindingTestContext.java | 32 +--- .../binding/impl/RuntimeMappingModule.java | 45 +++-- .../opendaylight-binding-broker-impl.yang | 5 +- .../yang/opendaylight-md-sal-binding.yang | 6 + .../yang/actor-system-provider-service.yang | 1 + ...opendaylight-entity-ownership-service.yang | 1 + .../sal/common/util/NoopAutoCloseable.java | 24 +++ .../md-sal/sal-distributed-datastore/pom.xml | 10 +- .../datastore/DistributedDataStore.java | 4 +- .../DistributedDataStoreInterface.java | 21 +++ .../admin/ClusterAdminRpcService.java | 9 +- .../impl/ActorSystemProviderModule.java | 52 +++++- .../ClusterAdminProviderModule.java | 17 +- .../DomConcurrentDataBrokerModule.java | 96 ++++------ .../DomConcurrentDataBrokerModuleFactory.java | 20 +++ ...tributedConfigDataStoreProviderModule.java | 17 +- ...tedOperationalDataStoreProviderModule.java | 15 +- .../ForwardingDistributedDataStore.java | 77 ++++++++ ...dEntityOwnershipServiceProviderModule.java | 77 ++++++-- .../blueprint/clustered-datastore.xml | 15 +- .../yang/distributed-datastore-provider.yang | 8 +- .../md/sal/dom/impl/DomBrokerImplModule.java | 77 ++++++-- .../dom/impl/DomBrokerImplModuleFactory.java | 24 ++- .../SchemaServiceImplSingletonModule.java | 28 +-- .../broker/impl/DOMNotificationRouter.java | 2 + .../controller/sal/dom/broker/BrokerImpl.java | 39 ++--- .../opendaylight-config-dom-datastore.yang | 6 +- .../main/yang/opendaylight-md-sal-dom.yang | 3 + ...pendaylight-operational-dom-datastore.yang | 6 +- .../RemoteRPCBrokerModule.java | 30 +--- .../RemoteRPCBrokerModuleFactory.java | 23 +-- .../ClusteringItProviderModule.java | 64 +------ .../impl/KitchenServiceModule.java | 51 +++--- .../impl/KitchenServiceModuleFactory.java | 21 ++- .../sample/toaster/it/ToasterTest.java | 2 +- .../impl/ToasterProviderModule.java | 47 +---- 55 files changed, 897 insertions(+), 863 deletions(-) delete mode 100644 opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java delete mode 100644 opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java delete mode 100644 opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java delete mode 100644 opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java create mode 100644 opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/ServiceNotFoundException.java create mode 100644 opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/WaitingServiceTracker.java create mode 100644 opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/NoopAutoCloseable.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreInterface.java create mode 100644 opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/ForwardingDistributedDataStore.java diff --git a/features/mdsal/pom.xml b/features/mdsal/pom.xml index abb74a54db..f12e9e1358 100644 --- a/features/mdsal/pom.xml +++ b/features/mdsal/pom.xml @@ -15,6 +15,7 @@ jar + 0.5.0-SNAPSHOT 1.0.0-SNAPSHOT 2.1.0-SNAPSHOT 0.9.0-SNAPSHOT @@ -79,6 +80,12 @@ stax-utils + + org.opendaylight.controller + blueprint + ${blueprint.version} + + org.opendaylight.odlparent @@ -131,7 +138,6 @@ xml - org.opendaylight.controller md-sal-config diff --git a/features/mdsal/src/main/features/features.xml b/features/mdsal/src/main/features/features.xml index b7283d0e54..897ec4ff18 100644 --- a/features/mdsal/src/main/features/features.xml +++ b/features/mdsal/src/main/features/features.xml @@ -51,6 +51,7 @@ mvn:org.opendaylight.controller/sal-binding-config/{{VERSION}} mvn:org.opendaylight.controller/sal-inmemory-datastore/{{VERSION}} mvn:org.opendaylight.controller/sal-dom-broker-config/{{VERSION}} + mvn:org.opendaylight.controller/blueprint/{{VERSION}} mvn:org.opendaylight.controller/md-sal-config/{{VERSION}}/xml/config diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java deleted file mode 100644 index 695e36cbef..0000000000 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.yang.protocol.framework; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; - -import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; - -final class GlobalEventExecutorUtil { - - private GlobalEventExecutorUtil() { - throw new UnsupportedOperationException(); - } - - public static ObjectName create(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException { - try { - return transaction.lookupConfigBean(GlobalEventExecutorModuleFactory.NAME, - GlobalEventExecutorModuleFactory.SINGLETON_NAME); - } catch (InstanceNotFoundException e) { - try { - return transaction.createModule(GlobalEventExecutorModuleFactory.NAME, - GlobalEventExecutorModuleFactory.SINGLETON_NAME); - } catch (InstanceAlreadyExistsException e1) { - throw new IllegalStateException(e1); - } - } - } - -} diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java deleted file mode 100644 index 77589ed81d..0000000000 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.yang.protocol.framework; - -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.api.ValidationException; -import org.opendaylight.controller.config.api.jmx.CommitStatus; -import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; -import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -public class NeverReconnectStrategyModuleTest extends AbstractConfigTest { - - private static final String INSTANCE_NAME = "never-reconect-strategy-factory-impl"; - private static final String FACTORY_NAME = NeverReconnectStrategyFactoryModuleFactory.NAME; - - @Before - public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, - new NeverReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); - } - - @Test - public void testValidationExceptionTimeoutNotSet() throws Exception { - try { - createInstance(null); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("Timeout value is not set.")); - } - } - - @Test - public void testValidationExceptionTimeoutMinValue() throws Exception { - try { - createInstance(-1); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("is less than 0")); - } - } - - @Test - public void testCreateBean() throws Exception { - final CommitStatus status = createInstance(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 2, 0, 0); - } - - @Test - public void testReusingOldInstance() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 0, 2); - } - - @Test - public void testReconfigure() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy( - transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), NeverReconnectStrategyFactoryModuleMXBean.class); - mxBean.setTimeout(200); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 1, 1); - } - - private CommitStatus createInstance() throws Exception { - return createInstance(500); - } - - private CommitStatus createInstance(final Integer timeout) throws InstanceAlreadyExistsException, - ConflictingVersionException, ValidationException { - final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction(); - createInstance(transaction, timeout); - return transaction.commit(); - } - - private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout) - throws InstanceAlreadyExistsException { - final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME); - final NeverReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, - NeverReconnectStrategyFactoryModuleMXBean.class); - mxBean.setTimeout(timeout); - mxBean.setExecutor(GlobalEventExecutorUtil.create(transaction)); - return nameCreated; - } - -} diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java deleted file mode 100644 index 7e3ed5b2de..0000000000 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.yang.protocol.framework; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; - -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.config.api.ValidationException; -import org.opendaylight.controller.config.api.jmx.CommitStatus; -import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; -import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; - -public class ReconnectImmediatelyStrategyModuleTest extends AbstractConfigTest { - - private static final String INSTANCE_NAME = "reconnect-immediately-strategy-factory-impl"; - private static final String FACTORY_NAME = ReconnectImmediatelyStrategyFactoryModuleFactory.NAME; - - @Before - public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, - new ReconnectImmediatelyStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); - } - - @Test - public void testValidationExceptionTimeoutNotSet() throws Exception { - try { - createInstance(null); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("Timeout value is not set.")); - } - } - - @Test - public void testValidationExceptionTimeoutMinValue() throws Exception { - try { - createInstance(-1); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("is less than 0")); - } - } - - @Test - public void testCreateBean() throws Exception { - final CommitStatus status = createInstance(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 2, 0, 0); - } - - @Test - public void testReusingOldInstance() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 0, 2); - } - - @Test - public void testReconfigure() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy( - transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), - ReconnectImmediatelyStrategyFactoryModuleMXBean.class); - mxBean.setReconnectTimeout(200); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 1, 1); - } - - private CommitStatus createInstance() throws Exception { - return createInstance(500); - } - - private CommitStatus createInstance(final Integer timeout) throws Exception { - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - createInstance(transaction, timeout); - return transaction.commit(); - } - - private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final Integer timeout) - throws InstanceAlreadyExistsException { - final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, INSTANCE_NAME); - final ReconnectImmediatelyStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, - ReconnectImmediatelyStrategyFactoryModuleMXBean.class); - mxBean.setReconnectTimeout(timeout); - mxBean.setReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); - return nameCreated; - } - -} diff --git a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java b/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java deleted file mode 100644 index ec8a9d6f29..0000000000 --- a/opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.yang.protocol.framework; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.math.BigDecimal; -import javax.management.InstanceAlreadyExistsException; -import javax.management.ObjectName; -import org.junit.Before; -import org.junit.Test; -import org.opendaylight.controller.config.api.ConflictingVersionException; -import org.opendaylight.controller.config.api.ValidationException; -import org.opendaylight.controller.config.api.jmx.CommitStatus; -import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; -import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; -import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; -import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory; - -public class TimedReconnectStrategyModuleTest extends AbstractConfigTest { - - private static final String INSTANCE_NAME = "timed-reconect-stategy-facotry-impl"; - private static final String FACTORY_NAME = TimedReconnectStrategyFactoryModuleFactory.NAME; - - @Before - public void setUp() throws Exception { - super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, - new TimedReconnectStrategyFactoryModuleFactory(), new GlobalEventExecutorModuleFactory())); - } - - @Test - public void testValidationExceptionSleepFactorNotSet() throws Exception { - try { - createInstance(500, 100L, null, 500L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("SleepFactor value is not set.")); - } - } - - @Test - public void testValidationExceptionSleepFactorMinValue() throws Exception { - try { - createInstance(500, 100L, new BigDecimal(0.5), 500L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("is less than 1")); - } - } - - @Test - public void testValidationExceptionConnectTimeNotSet() throws Exception { - try { - createInstance(null, 100L, new BigDecimal(1.0), 500L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("ConnectTime value is not set.")); - } - } - - @Test - public void testValidationExceptionConnectTimeMinValue() throws Exception { - try { - createInstance(-1, 100L, new BigDecimal(1.0), 500L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("is less than 0")); - } - } - - @Test - public void testValidationExceptionMinSleepNotSet() throws Exception { - try { - createInstance(100, null, new BigDecimal(1.0), 100L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("MinSleep value is not set.")); - } - } - - @Test - public void testValidationExceptionMaxSleep() throws Exception { - try { - createInstance(100, 300L, new BigDecimal(1.0), 100L, 10L, 10000L); - fail(); - } catch (ValidationException e) { - assertTrue(e.getMessage().contains("is greter than MaxSleep")); - } - } - - @Test - public void testCreateBean() throws Exception { - final CommitStatus status = createInstance(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 2, 0, 0); - } - - @Test - public void testReusingOldInstance() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 0, 2); - } - - @Test - public void testReconfigure() throws Exception { - createInstance(); - final ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - assertBeanCount(1, FACTORY_NAME); - final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy( - transaction.lookupConfigBean(FACTORY_NAME, INSTANCE_NAME), TimedReconnectStrategyFactoryModuleMXBean.class); - assertEquals(mxBean.getMinSleep(), new Long(100)); - mxBean.setMinSleep(200L); - assertEquals(mxBean.getMinSleep(), new Long(200)); - final CommitStatus status = transaction.commit(); - assertBeanCount(1, FACTORY_NAME); - assertStatus(status, 0, 1, 1); - - } - - private CommitStatus createInstance() throws Exception { - return createInstance(500, 100L, new BigDecimal(1.0), 500L, 10L, 10000L); - } - - private CommitStatus createInstance(final Integer connectTime, final Long minSleep, final BigDecimal sleepFactor, - final Long maxSleep, final Long maxAttempts, final Long deadline) throws ConflictingVersionException, - ValidationException, InstanceAlreadyExistsException { - ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction(); - createInstance(transaction, INSTANCE_NAME, connectTime, minSleep, sleepFactor, maxSleep, maxAttempts, deadline); - return transaction.commit(); - } - - public static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final String InstanceName) - throws Exception { - return createInstance(transaction, InstanceName, 500, 100L, new BigDecimal(1.0), 500L, 10L, 10000L); - } - - private static ObjectName createInstance(final ConfigTransactionJMXClient transaction, final String instanceName, - final Integer connectTime, final Long minSleep, final BigDecimal sleepFactor, final Long maxSleep, - final Long maxAttempts, final Long deadline) throws InstanceAlreadyExistsException { - final ObjectName nameCreated = transaction.createModule(FACTORY_NAME, instanceName); - final TimedReconnectStrategyFactoryModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, - TimedReconnectStrategyFactoryModuleMXBean.class); - mxBean.setConnectTime(connectTime); - mxBean.setDeadline(deadline); - mxBean.setMaxAttempts(maxAttempts); - mxBean.setMaxSleep(maxSleep); - mxBean.setMinSleep(minSleep); - mxBean.setSleepFactor(sleepFactor); - mxBean.setTimedReconnectExecutor(GlobalEventExecutorUtil.create(transaction)); - return nameCreated; - } - -} diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/ServiceNotFoundException.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/ServiceNotFoundException.java new file mode 100644 index 0000000000..0d9e7f0a34 --- /dev/null +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/ServiceNotFoundException.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 Brocade Communications 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.api.osgi; + +/** + * RuntimeException thrown when an OSGi service lookup fails. + * + * @author Thomas Pantelis + */ +public class ServiceNotFoundException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public ServiceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ServiceNotFoundException(String message) { + super(message); + } +} diff --git a/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/WaitingServiceTracker.java b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/WaitingServiceTracker.java new file mode 100644 index 0000000000..1549e6b26a --- /dev/null +++ b/opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/WaitingServiceTracker.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016 Brocade Communications 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.api.osgi; + +import java.util.concurrent.TimeUnit; +import javax.annotation.Nonnull; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.util.tracker.ServiceTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Tracker that waits for an OSGi service. + * + * @author Thomas Pantelis + */ +public final class WaitingServiceTracker implements AutoCloseable { + private static final Logger LOG = LoggerFactory.getLogger(WaitingServiceTracker.class); + public static final long FIVE_MINUTES = TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES); + + private final ServiceTracker tracker; + private final Class serviceInterface; + + private WaitingServiceTracker(Class serviceInterface, ServiceTracker tracker) { + this.tracker = tracker; + this.serviceInterface = serviceInterface; + } + + /** + * Waits for an OSGi services. + * + * @param timeoutInMillis the timeout in millis + * @return the service instance + * @throws ServiceNotFoundException if it times out or is interrupted + */ + @SuppressWarnings("unchecked") + public T waitForService(long timeoutInMillis) throws ServiceNotFoundException { + try { + T service = (T) tracker.waitForService(timeoutInMillis); + if(service == null) { + throw new ServiceNotFoundException(String.format("OSGi Service %s was not found after %d ms", + serviceInterface, timeoutInMillis)); + } + + return service; + } catch(InterruptedException e) { + throw new ServiceNotFoundException(String.format("Wait for OSGi service %s was interrrupted", + serviceInterface)); + } + } + + /** + * Creates an instance. + * + * @param serviceInterface the service interface + * @param context the BundleContext + * @return new WaitingServiceTracker instance + */ + public static WaitingServiceTracker create(@Nonnull Class serviceInterface, @Nonnull BundleContext context) { + ServiceTracker tracker = new ServiceTracker<>(context, serviceInterface, null); + tracker.open(); + return new WaitingServiceTracker(serviceInterface, tracker); + } + + /** + * Creates an instance. + * + * @param serviceInterface the service interface + * @param context the BundleContext + * @param filter the OSGi service filter + * @return new WaitingServiceTracker instance + */ + public static WaitingServiceTracker create(@Nonnull Class serviceInterface, @Nonnull BundleContext context, + @Nonnull String filter) { + String newFilter = String.format("(&(%s=%s)%s)", Constants.OBJECTCLASS, serviceInterface.getName(), filter); + try { + ServiceTracker tracker = new ServiceTracker<>(context, context.createFilter(newFilter), null); + tracker.open(); + return new WaitingServiceTracker(serviceInterface, tracker); + } catch(InvalidSyntaxException e) { + throw new IllegalArgumentException(String.format("Invalid OSGi filter %s", newFilter), e); + } + } + + @Override + public void close() { + try { + tracker.close(); + } catch(RuntimeException e) { + // The ServiceTracker could throw IllegalStateException if the BundleContext is already closed. + // This is benign so ignore it. + LOG.debug("Error closing ServiceTracker", e); + } + } +} diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/AutoCloseableEventExecutor.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/AutoCloseableEventExecutor.java index cb721db67d..99d94d08e3 100644 --- a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/AutoCloseableEventExecutor.java +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/AutoCloseableEventExecutor.java @@ -27,33 +27,43 @@ public interface AutoCloseableEventExecutor extends EventExecutor, AutoCloseable } @Override - public void close() { + public void close() throws Exception { eventExecutor.shutdownGracefully(0, DEFAULT_SHUTDOWN_SECONDS, TimeUnit.SECONDS); } - private static AutoCloseableEventExecutor createCloseableProxy(final EventExecutor eventExecutor) { - final CloseableEventExecutorMixin closeableGlobalEventExecutorMixin = - new CloseableEventExecutorMixin(eventExecutor); + private static AutoCloseableEventExecutor createCloseableProxy( + final CloseableEventExecutorMixin closeableEventExecutorMixin) { return Reflection.newProxy(AutoCloseableEventExecutor.class, new AbstractInvocationHandler() { @Override protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("close")) { - closeableGlobalEventExecutorMixin.close(); + closeableEventExecutorMixin.close(); return null; } else { - return method.invoke(eventExecutor, args); + return method.invoke(closeableEventExecutorMixin.eventExecutor, args); } } }); } public static AutoCloseableEventExecutor globalEventExecutor() { - return createCloseableProxy(GlobalEventExecutor.INSTANCE); + return createCloseableProxy(new CloseableEventExecutorMixin(GlobalEventExecutor.INSTANCE)); } public static AutoCloseableEventExecutor immediateEventExecutor() { - return createCloseableProxy(ImmediateEventExecutor.INSTANCE); + return createCloseableProxy(new CloseableEventExecutorMixin(ImmediateEventExecutor.INSTANCE)); + } + + public static AutoCloseableEventExecutor forwardingEventExecutor(final EventExecutor eventExecutor, + final AutoCloseable closeable) { + return createCloseableProxy(new CloseableEventExecutorMixin(eventExecutor) { + @Override + public void close() throws Exception { + // Intentional no-op. + closeable.close(); + } + }); } } } \ No newline at end of file diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java index caca6b1b64..da0639187d 100644 --- a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java @@ -17,10 +17,14 @@ */ package org.opendaylight.controller.config.yang.netty.eventexecutor; +import io.netty.util.concurrent.EventExecutor; +import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker; import org.opendaylight.controller.config.yang.netty.eventexecutor.AutoCloseableEventExecutor.CloseableEventExecutorMixin; +import org.osgi.framework.BundleContext; public final class GlobalEventExecutorModule extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule { + private BundleContext bundleContext; public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -39,10 +43,15 @@ public final class GlobalEventExecutorModule extends } @Override - public java.lang.AutoCloseable createInstance() { - return CloseableEventExecutorMixin.globalEventExecutor(); + public AutoCloseable createInstance() { + // The service is provided via blueprint so wait for and return it here for backwards compatibility. + final WaitingServiceTracker tracker = WaitingServiceTracker.create( + EventExecutor.class, bundleContext, "(type=global-event-executor)"); + EventExecutor eventExecutor = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES); + return CloseableEventExecutorMixin.forwardingEventExecutor(eventExecutor, tracker); } - - + public void setBundleContext(final BundleContext bundleContext) { + this.bundleContext = bundleContext; + } } diff --git a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java index 1ca57c637f..467f0689e9 100644 --- a/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java +++ b/opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java @@ -18,7 +18,6 @@ package org.opendaylight.controller.config.yang.netty.eventexecutor; import static com.google.common.base.Preconditions.checkArgument; - import org.opendaylight.controller.config.api.DependencyResolver; import org.osgi.framework.BundleContext; @@ -29,12 +28,17 @@ public class GlobalEventExecutorModuleFactory extends org.opendaylight.controlle @Override public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, GlobalEventExecutorModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) { checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME); - return super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext); + GlobalEventExecutorModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, + oldInstance, bundleContext); + module.setBundleContext(bundleContext); + return module; } @Override public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) { checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME); - return super.instantiateModule(instanceName, dependencyResolver, bundleContext); + GlobalEventExecutorModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; } } diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java index 8fe3d7c24c..7d763699ff 100644 --- a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java +++ b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java @@ -10,7 +10,12 @@ package org.opendaylight.controller.config.yang.netty.eventexecutor; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import io.netty.util.concurrent.EventExecutor; import javax.management.InstanceAlreadyExistsException; import javax.management.ObjectName; import org.junit.Before; @@ -21,16 +26,29 @@ import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; +import org.osgi.framework.Filter; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; public class GlobalEventExecutorModuleTest extends AbstractConfigTest { private GlobalEventExecutorModuleFactory factory; private final String instanceName = GlobalEventExecutorModuleFactory.SINGLETON_NAME; + @SuppressWarnings({ "rawtypes", "unchecked" }) @Before - public void setUp() { + public void setUp() throws Exception { factory = new GlobalEventExecutorModuleFactory(); super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); + + Filter mockFilter = mock(Filter.class); + doReturn("mock").when(mockFilter).toString(); + doReturn(mockFilter).when(mockedContext).createFilter(anyString()); + doNothing().when(mockedContext).addServiceListener(any(ServiceListener.class), anyString()); + ServiceReference mockServiceRef = mock(ServiceReference.class); + doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext). + getServiceReferences(anyString(), anyString()); + doReturn(mock(EventExecutor.class)).when(mockedContext).getService(mockServiceRef); } @Test diff --git a/opendaylight/config/netty-threadgroup-config/pom.xml b/opendaylight/config/netty-threadgroup-config/pom.xml index 223eca1d38..5a0e483727 100644 --- a/opendaylight/config/netty-threadgroup-config/pom.xml +++ b/opendaylight/config/netty-threadgroup-config/pom.xml @@ -68,7 +68,6 @@ ${project.groupId}.${project.artifactId} org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.threadgroup.rev131107.*, - *,io.netty.channel diff --git a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java index 54266f4e84..09ea672001 100644 --- a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java +++ b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java @@ -17,13 +17,21 @@ */ package org.opendaylight.controller.config.yang.netty.threadgroup; +import com.google.common.reflect.AbstractInvocationHandler; +import com.google.common.reflect.Reflection; +import io.netty.channel.EventLoopGroup; +import java.lang.reflect.Method; import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker; +import org.osgi.framework.BundleContext; /** * */ public final class NettyThreadgroupModule extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModule { + private BundleContext bundleContext; + public NettyThreadgroupModule(org.opendaylight.controller.config.api.ModuleIdentifier name, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(name, dependencyResolver); } @@ -41,7 +49,30 @@ public final class NettyThreadgroupModule extends org.opendaylight.controller.co } @Override - public java.lang.AutoCloseable createInstance() { - return NioEventLoopGroupCloseable.newInstance(getThreadCount()); + public AutoCloseable createInstance() { + // The service is provided via blueprint so wait for and return it here for backwards compatibility. + String typeFilter = String.format("(type=%s)", getIdentifier().getInstanceName()); + final WaitingServiceTracker tracker = WaitingServiceTracker.create( + EventLoopGroup.class, bundleContext, typeFilter); + final EventLoopGroup group = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES); + + return Reflection.newProxy(AutoCloseableEventLoopGroupInterface.class, new AbstractInvocationHandler() { + @Override + protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().equals("close")) { + tracker.close(); + return null; + } else { + return method.invoke(group, args); + } + } + }); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + private static interface AutoCloseableEventLoopGroupInterface extends EventLoopGroup, AutoCloseable { } } diff --git a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java index c97bd566b0..b509932568 100644 --- a/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java +++ b/opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java @@ -17,11 +17,23 @@ */ package org.opendaylight.controller.config.yang.netty.threadgroup; -/** -* -*/ -public class NettyThreadgroupModuleFactory extends org.opendaylight.controller.config.yang.netty.threadgroup.AbstractNettyThreadgroupModuleFactory -{ +import org.opendaylight.controller.config.api.DependencyResolver; +import org.osgi.framework.BundleContext; +public class NettyThreadgroupModuleFactory extends AbstractNettyThreadgroupModuleFactory { + @Override + public NettyThreadgroupModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + NettyThreadgroupModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) { + NettyThreadgroupModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + @Override + public NettyThreadgroupModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + BundleContext bundleContext) { + NettyThreadgroupModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; + } } diff --git a/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java b/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java index ceefcda6de..81f85845fb 100644 --- a/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java +++ b/opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java @@ -7,6 +7,12 @@ */ package org.opendaylight.controller.config.yang.netty.threadgroup; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import io.netty.channel.EventLoopGroup; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.ObjectName; @@ -18,16 +24,29 @@ import org.opendaylight.controller.config.api.jmx.CommitStatus; import org.opendaylight.controller.config.manager.impl.AbstractConfigTest; import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver; import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; +import org.osgi.framework.Filter; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; public class NettyThreadgroupModuleTest extends AbstractConfigTest { private NettyThreadgroupModuleFactory factory; private final String instanceName = "netty1"; + @SuppressWarnings({ "rawtypes", "unchecked" }) @Before - public void setUp() { + public void setUp() throws Exception { factory = new NettyThreadgroupModuleFactory(); super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory)); + + Filter mockFilter = mock(Filter.class); + doReturn("mock").when(mockFilter).toString(); + doReturn(mockFilter).when(mockedContext).createFilter(anyString()); + doNothing().when(mockedContext).addServiceListener(any(ServiceListener.class), anyString()); + ServiceReference mockServiceRef = mock(ServiceReference.class); + doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext). + getServiceReferences(anyString(), anyString()); + doReturn(mock(EventLoopGroup.class)).when(mockedContext).getService(mockServiceRef); } @Test diff --git a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java index 7114ed6025..76d75e8372 100644 --- a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java +++ b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java @@ -17,13 +17,20 @@ */ package org.opendaylight.controller.config.yang.netty.timer; +import com.google.common.reflect.AbstractInvocationHandler; +import com.google.common.reflect.Reflection; +import io.netty.util.Timer; +import java.lang.reflect.Method; import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker; +import org.osgi.framework.BundleContext; /** * */ public final class HashedWheelTimerModule extends org.opendaylight.controller.config.yang.netty.timer.AbstractHashedWheelTimerModule { + private BundleContext bundleContext; public HashedWheelTimerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -50,7 +57,29 @@ public final class HashedWheelTimerModule extends } @Override - public java.lang.AutoCloseable createInstance() { - return HashedWheelTimerCloseable.newInstance(getThreadFactoryDependency(), getTickDuration(), getTicksPerWheel()); + public AutoCloseable createInstance() { + // The service is provided via blueprint so wait for and return it here for backwards compatibility. + final WaitingServiceTracker tracker = WaitingServiceTracker.create( + Timer.class, bundleContext, "(type=global-timer)"); + final Timer timer = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES); + + return Reflection.newProxy(AutoCloseableTimerInterface.class, new AbstractInvocationHandler() { + @Override + protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().equals("close")) { + tracker.close(); + return null; + } else { + return method.invoke(timer, args); + } + } + }); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + private static interface AutoCloseableTimerInterface extends Timer, AutoCloseable { } } diff --git a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java index c869413a5e..d8ec0fcf90 100644 --- a/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java +++ b/opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java @@ -17,10 +17,24 @@ */ package org.opendaylight.controller.config.yang.netty.timer; -/** -* -*/ -public class HashedWheelTimerModuleFactory extends - org.opendaylight.controller.config.yang.netty.timer.AbstractHashedWheelTimerModuleFactory { +import org.opendaylight.controller.config.api.DependencyResolver; +import org.osgi.framework.BundleContext; + +public class HashedWheelTimerModuleFactory extends AbstractHashedWheelTimerModuleFactory { + @Override + public HashedWheelTimerModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + HashedWheelTimerModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) { + HashedWheelTimerModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, + oldInstance, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + @Override + public HashedWheelTimerModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + BundleContext bundleContext) { + HashedWheelTimerModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; + } } diff --git a/opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java b/opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java index 6ffeb0490d..9936823973 100644 --- a/opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java +++ b/opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java @@ -9,7 +9,12 @@ package org.opendaylight.controller.config.yang.netty.timer; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import io.netty.util.Timer; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.ObjectName; @@ -23,6 +28,9 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.Hardcod import org.opendaylight.controller.config.util.ConfigTransactionJMXClient; import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleFactory; import org.opendaylight.controller.config.yang.threadpool.impl.NamingThreadFactoryModuleMXBean; +import org.osgi.framework.Filter; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; public class HashedWheelTimerModuleTest extends AbstractConfigTest { @@ -30,11 +38,21 @@ public class HashedWheelTimerModuleTest extends AbstractConfigTest { private NamingThreadFactoryModuleFactory threadFactory; private final String instanceName = "hashed-wheel-timer1"; + @SuppressWarnings({ "rawtypes", "unchecked" }) @Before - public void setUp() { + public void setUp() throws Exception { factory = new HashedWheelTimerModuleFactory(); threadFactory = new NamingThreadFactoryModuleFactory(); super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, threadFactory)); + + Filter mockFilter = mock(Filter.class); + doReturn("mock").when(mockFilter).toString(); + doReturn(mockFilter).when(mockedContext).createFilter(anyString()); + doNothing().when(mockedContext).addServiceListener(any(ServiceListener.class), anyString()); + ServiceReference mockServiceRef = mock(ServiceReference.class); + doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext). + getServiceReferences(anyString(), anyString()); + doReturn(mock(Timer.class)).when(mockedContext).getService(mockServiceRef); } public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException { diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java index 5ca041a3e6..526f4005f5 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java @@ -8,16 +8,13 @@ package org.opendaylight.controller.sal.binding.test.util; import static com.google.common.base.Preconditions.checkState; - import com.google.common.annotations.Beta; import com.google.common.collect.ClassToInstanceMap; -import com.google.common.collect.ImmutableClassToInstanceMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.MutableClassToInstanceMap; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; -import javassist.ClassPool; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.MountPointService; import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; @@ -50,7 +47,6 @@ import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.api.mount.MountProviderService; import org.opendaylight.controller.sal.binding.impl.RootBindingAwareBroker; -import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.BrokerService; import org.opendaylight.controller.sal.core.spi.data.DOMStore; import org.opendaylight.controller.sal.dom.broker.BrokerImpl; @@ -63,6 +59,7 @@ import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils; import org.opendaylight.yangtools.yang.binding.YangModuleInfo; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import javassist.ClassPool; @Beta public class BindingTestContext implements AutoCloseable { @@ -175,33 +172,6 @@ public class BindingTestContext implements AutoCloseable { } - private ProviderSession createMockContext() { - - final ClassToInstanceMap domBrokerServices = ImmutableClassToInstanceMap - . builder() - // - .put(DOMRpcRouter.class, biBrokerImpl.getRouter()) // - .put(DOMMountPointService.class, biMountImpl) - .build(); - - return new ProviderSession() { - - @Override - public T getService(final Class service) { - return domBrokerServices.getInstance(service); - } - - @Override - public boolean isClosed() { - return false; - } - - @Override - public void close() { - } - }; - } - public void startBindingToDomMappingService() { checkState(classPool != null, "ClassPool needs to be present"); diff --git a/opendaylight/md-sal/sal-binding-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java b/opendaylight/md-sal/sal-binding-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java index e2d942e9cd..f6b86ebcd1 100644 --- a/opendaylight/md-sal/sal-binding-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java +++ b/opendaylight/md-sal/sal-binding-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java @@ -8,20 +8,18 @@ package org.opendaylight.controller.config.yang.md.sal.binding.impl; import com.google.common.base.Preconditions; -import java.util.Hashtable; +import com.google.common.base.Stopwatch; +import com.google.common.util.concurrent.Uninterruptibles; +import java.util.concurrent.TimeUnit; import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec; -import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder; -import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator; -import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; -import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; -import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; /** * **/ public final class RuntimeMappingModule extends AbstractRuntimeMappingModule { + private static final long WAIT_IN_MINUTES = 5; private BundleContext bundleContext; @@ -50,16 +48,31 @@ public final class RuntimeMappingModule extends AbstractRuntimeMappingModule { @Override public java.lang.AutoCloseable createInstance() { - final ClassLoadingStrategy classLoading = getGlobalClassLoadingStrategy(); - final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(SingletonHolder.JAVASSIST)); - final BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, codecRegistry,getWaitForSchema()); - bundleContext.registerService(SchemaContextListener.class, instance, new Hashtable()); - return instance; - } + // This is kind of ugly - you might cringe (you've been warned). The BindingToNormalizedNodeCodec + // instance is advertised via blueprint so ideally we'd obtain it from the OSGi service registry. + // The config yang service identity declares the concrete BindingToNormalizedNodeCodec class + // and not an interface as the java-class so we must return a BindingToNormalizedNodeCodec instance. + // However we can't cast the instance obtained from the service registry to + // BindingToNormalizedNodeCodec b/c Aries may register a proxy if there are interceptors defined. + // By default karaf ships with the org.apache.aries.quiesce.api bundle which automatically adds + // an interceptor that adds stat tracking for service method calls. While this can be disabled, we + // shouldn't rely on it. + // + // Therefore we store a static instance in the BindingToNormalizedNodeCodecFactory which is created + // by blueprint via newInstance. We obtain the static instance here and busy wait if not yet available. + + Stopwatch sw = Stopwatch.createStarted(); + while(sw.elapsed(TimeUnit.MINUTES) <= WAIT_IN_MINUTES) { + BindingToNormalizedNodeCodec instance = BindingToNormalizedNodeCodecFactory.getInstance(); + if(instance != null) { + return instance; + } + + Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS); + } - private ClassLoadingStrategy getGlobalClassLoadingStrategy() { - final ServiceReference ref = bundleContext.getServiceReference(ClassLoadingStrategy.class); - return bundleContext.getService(ref); + throw new IllegalStateException("Could not obtain the BindingToNormalizedNodeCodec instance after " + + WAIT_IN_MINUTES + " minutes."); } public void setBundleContext(final BundleContext bundleContext) { diff --git a/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-binding-broker-impl.yang b/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-binding-broker-impl.yang index 3244b5a4ee..a56e2f9e32 100644 --- a/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-binding-broker-impl.yang +++ b/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-binding-broker-impl.yang @@ -19,18 +19,21 @@ module opendaylight-sal-binding-broker-impl { identity binding-dom-mapping-service { base config:service-type; config:java-class "org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec"; + config:disable-osgi-service-registration; } /* FIXME: move to opendaylight-md-sal-binding (cannot be there due to Class name confict with old implementation)*/ identity binding-new-notification-service { base config:service-type; config:java-class "org.opendaylight.controller.md.sal.binding.api.NotificationService"; + config:disable-osgi-service-registration; } /* TODO: move to opendaylight-md-sal-binding (cannot be there due to Class name confict with old implementation)*/ identity binding-new-notification-publish-service { base config:service-type; config:java-class "org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"; + config:disable-osgi-service-registration; } identity binding-broker-impl { @@ -134,7 +137,7 @@ module opendaylight-sal-binding-broker-impl { container notification-service { uses config:service-ref { refine type { - mandatory true; + mandatory false; config:required-identity sal:binding-notification-service; } } diff --git a/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang b/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang index 18a94dfacd..f1f19b4c1e 100644 --- a/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang +++ b/opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang @@ -26,6 +26,7 @@ module opendaylight-md-sal-binding { identity binding-async-data-broker { base "config:service-type"; config:java-class "org.opendaylight.controller.md.sal.binding.api.DataBroker"; + config:disable-osgi-service-registration; } identity binding-data-consumer-broker { @@ -36,26 +37,31 @@ module opendaylight-md-sal-binding { identity binding-rpc-registry { base "config:service-type"; config:java-class "org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"; + config:disable-osgi-service-registration; } identity binding-notification-service { base "config:service-type"; config:java-class "org.opendaylight.controller.sal.binding.api.NotificationProviderService"; + config:disable-osgi-service-registration; } identity binding-codec-tree-factory { base "config:service-type"; config:java-class "org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory"; + config:disable-osgi-service-registration; } identity binding-normalized-node-serializer { base "config:service-type"; config:java-class "org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer"; + config:disable-osgi-service-registration; } identity binding-notification-subscription-service { base "config:service-type"; config:java-class "org.opendaylight.controller.sal.binding.api.NotificationService"; + config:disable-osgi-service-registration; } } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/yang/actor-system-provider-service.yang b/opendaylight/md-sal/sal-clustering-commons/src/main/yang/actor-system-provider-service.yang index f284851cd9..4f97c3ae52 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/yang/actor-system-provider-service.yang +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/yang/actor-system-provider-service.yang @@ -14,5 +14,6 @@ module actor-system-provider-service { identity actor-system-provider-service { base "config:service-type"; config:java-class "org.opendaylight.controller.cluster.ActorSystemProvider"; + config:disable-osgi-service-registration; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-common-api/src/main/yang/opendaylight-entity-ownership-service.yang b/opendaylight/md-sal/sal-common-api/src/main/yang/opendaylight-entity-ownership-service.yang index f16f7c4430..28aee9fd4c 100644 --- a/opendaylight/md-sal/sal-common-api/src/main/yang/opendaylight-entity-ownership-service.yang +++ b/opendaylight/md-sal/sal-common-api/src/main/yang/opendaylight-entity-ownership-service.yang @@ -14,5 +14,6 @@ module opendaylight-entity-ownership-service { identity entity-ownership-service { base "config:service-type"; config:java-class "org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService"; + config:disable-osgi-service-registration; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/NoopAutoCloseable.java b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/NoopAutoCloseable.java new file mode 100644 index 0000000000..7f95f9632c --- /dev/null +++ b/opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/NoopAutoCloseable.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 Brocade Communications 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.sal.common.util; + +/** + * An AutoCloseable that does nothing. + * + * @author Thomas Pantelis + */ +public final class NoopAutoCloseable implements AutoCloseable { + public static final NoopAutoCloseable INSTANCE = new NoopAutoCloseable(); + + private NoopAutoCloseable() { + } + + @Override + public void close() { + } +} diff --git a/opendaylight/md-sal/sal-distributed-datastore/pom.xml b/opendaylight/md-sal/sal-distributed-datastore/pom.xml index 935af23cae..d545cf49ec 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/pom.xml +++ b/opendaylight/md-sal/sal-distributed-datastore/pom.xml @@ -176,7 +176,15 @@ ${project.groupId}.${project.artifactId} org.opendaylight.controller.cluster.datastore.osgi.Activator - !*snappy;!org.jboss.*;!com.jcraft.*;!*jetty*;!sun.security.*;* + + !*snappy; + !org.jboss.*; + !com.jcraft.*; + !*jetty*; + !sun.security.*; + *; + org.opendaylight.controller.md.sal.dom.broker.impl.jmx + + + + org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface + + + - @@ -112,5 +124,4 @@ - \ No newline at end of file diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang b/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang index d40a3aafad..8174c77863 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang @@ -242,7 +242,7 @@ module distributed-datastore-provider { container config-schema-service { uses config:service-ref { refine type { - mandatory true; + mandatory false; config:required-identity sal:schema-service; } } @@ -251,7 +251,7 @@ module distributed-datastore-provider { container config-actor-system-provider { uses config:service-ref { refine type { - mandatory true; + mandatory false; config:required-identity actor-system:actor-system-provider-service; } } @@ -270,7 +270,7 @@ module distributed-datastore-provider { container operational-schema-service { uses config:service-ref { refine type { - mandatory true; + mandatory false; config:required-identity sal:schema-service; } } @@ -279,7 +279,7 @@ module distributed-datastore-provider { container operational-actor-system-provider { uses config:service-ref { refine type { - mandatory true; + mandatory false; config:required-identity actor-system:actor-system-provider-service; } } diff --git a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java index 61385ded68..895d3d2e29 100644 --- a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java +++ b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java @@ -10,23 +10,27 @@ package org.opendaylight.controller.config.yang.md.sal.dom.impl; import com.google.common.base.Preconditions; import com.google.common.collect.ClassToInstanceMap; import com.google.common.collect.MutableClassToInstanceMap; -import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.List; +import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker; import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService; import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService; import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter; -import org.opendaylight.controller.md.sal.dom.broker.impl.DOMRpcRouter; -import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl; import org.opendaylight.controller.sal.core.api.BrokerService; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.dom.broker.BrokerImpl; import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl; +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -public final class DomBrokerImplModule extends org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomBrokerImplModule -{ +public final class DomBrokerImplModule extends org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomBrokerImplModule{ + private static final Logger LOG = LoggerFactory.getLogger(DomBrokerImplModule.class); + + private BundleContext bundleContext; public DomBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); @@ -45,28 +49,63 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi @Override public java.lang.AutoCloseable createInstance() { - final DOMDataBroker asyncBroker= getAsyncDataBrokerDependency(); + // The services are provided via blueprint so retrieve then from the OSGi service registry for + // backwards compatibility. + + final List closeables = new ArrayList<>(); + DOMNotificationService domNotificationService = newTracker( + DOMNotificationService.class, closeables).waitForService(WaitingServiceTracker.FIVE_MINUTES); + + DOMNotificationPublishService domNotificationPublishService = newTracker( + DOMNotificationPublishService.class, closeables).waitForService(WaitingServiceTracker.FIVE_MINUTES); + + DOMRpcService domRpcService = newTracker( + DOMRpcService.class, closeables).waitForService(WaitingServiceTracker.FIVE_MINUTES); + + DOMRpcProviderService domRpcProvider = newTracker( + DOMRpcProviderService.class, closeables).waitForService(WaitingServiceTracker.FIVE_MINUTES); + + DOMMountPointService mountService = newTracker(DOMMountPointService.class, closeables). + waitForService(WaitingServiceTracker.FIVE_MINUTES); + + final DOMDataBroker dataBroker = getAsyncDataBrokerDependency(); final ClassToInstanceMap services = MutableClassToInstanceMap.create(); - final DOMNotificationRouter domNotificationRouter = DOMNotificationRouter.create(getNotificationQueueDepth().getValue().intValue(), - getNotificationQueueSpin().longValue(), getNotificationQueuePark().longValue(), TimeUnit.MILLISECONDS); - services.putInstance(DOMNotificationService.class, domNotificationRouter); - services.putInstance(DOMNotificationPublishService.class, domNotificationRouter); + services.putInstance(DOMNotificationService.class, domNotificationService); + services.putInstance(DOMNotificationPublishService.class, domNotificationPublishService); final SchemaService schemaService = getSchemaServiceImpl(); services.putInstance(SchemaService.class, schemaService); - services.putInstance(DOMDataBroker.class, asyncBroker); + services.putInstance(DOMDataBroker.class, dataBroker); - final DOMRpcRouter rpcRouter = DOMRpcRouter.newInstance(schemaService); - services.putInstance(DOMRpcService.class, rpcRouter); - services.putInstance(DOMRpcProviderService.class, rpcRouter); + services.putInstance(DOMRpcService.class, domRpcService); + services.putInstance(DOMRpcProviderService.class, domRpcProvider); - final DOMMountPointService mountService = new DOMMountPointServiceImpl(); services.putInstance(DOMMountPointService.class, mountService); - return new BrokerImpl(rpcRouter, services); + BrokerImpl broker = new BrokerImpl(domRpcService, domRpcProvider, services); + broker.setDeactivator(new AutoCloseable() { + @Override + public void close() { + for(AutoCloseable ac: closeables) { + try { + ac.close(); + } catch(Exception e) { + LOG.warn("Exception while closing {}", ac, e); + } + } + } + }); + + return broker; + } + + private WaitingServiceTracker newTracker(Class serviceInterface, List closeables) { + WaitingServiceTracker tracker = WaitingServiceTracker.create(serviceInterface, bundleContext); + closeables.add(tracker); + return tracker; } private SchemaService getSchemaServiceImpl() { @@ -78,4 +117,8 @@ public final class DomBrokerImplModule extends org.opendaylight.controller.confi } return schemaService; } + + public void setBundleContext(final BundleContext bundleContext) { + this.bundleContext = bundleContext; + } } diff --git a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java index f1fcb495aa..52230180eb 100644 --- a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java +++ b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java @@ -7,11 +7,29 @@ */ package org.opendaylight.controller.config.yang.md.sal.dom.impl; +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.spi.Module; +import org.osgi.framework.BundleContext; -/** -* -*/ public class DomBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractDomBrokerImplModuleFactory { + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, + BundleContext bundleContext) { + DomBrokerImplModule module = (DomBrokerImplModule)super.createModule(instanceName, dependencyResolver, + bundleContext); + module.setBundleContext(bundleContext); + return module; + } + + @Override + public Module createModule(String instanceName, DependencyResolver dependencyResolver, DynamicMBeanWithInstance old, + BundleContext bundleContext) throws Exception { + DomBrokerImplModule module = (DomBrokerImplModule)super.createModule(instanceName, dependencyResolver, + old, bundleContext); + module.setBundleContext(bundleContext); + return module; + } } diff --git a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java index 62b026430a..dae7f05cc6 100644 --- a/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java +++ b/opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java @@ -7,13 +7,18 @@ */ package org.opendaylight.controller.config.yang.md.sal.dom.impl; +import com.google.common.util.concurrent.CheckedFuture; import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.controller.sal.core.api.model.YangTextSourceProvider; import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl; import org.opendaylight.yangtools.concepts.Delegator; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,22 +61,20 @@ org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImp @Override public java.lang.AutoCloseable createInstance() { - return GlobalBundleScanningSchemaServiceImpl.getInstance(); + return new GlobalSchemaServiceProxy(GlobalBundleScanningSchemaServiceImpl.getInstance()); } - public class GlobalSchemaServiceProxy implements AutoCloseable, SchemaService, Delegator { + private static class GlobalSchemaServiceProxy implements AutoCloseable, SchemaService, YangTextSourceProvider, + Delegator { + private final GlobalBundleScanningSchemaServiceImpl delegate; - private SchemaService delegate; - - public GlobalSchemaServiceProxy() { - this.delegate = GlobalBundleScanningSchemaServiceImpl.getInstance(); + public GlobalSchemaServiceProxy(GlobalBundleScanningSchemaServiceImpl service) { + this.delegate = service; } @Override - public void close() throws Exception { - if (delegate != null) { - delegate = null; - } + public void close() { + // Intentional noop as the life-cycle is controlled via blueprint. } @Override @@ -104,5 +107,10 @@ org.opendaylight.controller.config.yang.md.sal.dom.impl.AbstractSchemaServiceImp return delegate; } + @Override + public CheckedFuture getSource( + SourceIdentifier sourceIdentifier) { + return delegate.getSource(sourceIdentifier); + } } } diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java index 138de6b770..64c6b9e1fd 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java @@ -98,6 +98,8 @@ public final class DOMNotificationRouter implements AutoCloseable, DOMNotificati } public static DOMNotificationRouter create(final int queueDepth, final long spinTime, final long parkTime, final TimeUnit unit) { + Preconditions.checkArgument(Long.lowestOneBit(queueDepth) == Long.highestOneBit(queueDepth), + "Queue depth %s is not power-of-two", queueDepth); final ExecutorService executor = Executors.newCachedThreadPool(); final WaitStrategy strategy = PhasedBackoffWaitStrategy.withLock(spinTime, parkTime, unit); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java index 03fbb18cae..6cd0ebc5f8 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java @@ -46,17 +46,23 @@ public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService, private final Set providerSessions = Collections .synchronizedSet(new HashSet()); - private AutoCloseable deactivator = null; + private AutoCloseable deactivator; - private DOMRpcRouter router = null; + private final DOMRpcService rpcService; + private final DOMRpcProviderService rpcProvider; private final ClassToInstanceMap services; - public BrokerImpl(final DOMRpcRouter router,final ClassToInstanceMap services) { - this.router = Preconditions.checkNotNull(router, "RPC Router must not be null"); - this.services = ImmutableClassToInstanceMap.copyOf(services); + public BrokerImpl(final DOMRpcRouter router,final ClassToInstanceMap services) { + this(router, router, services); } + public BrokerImpl(final DOMRpcService rpcService, final DOMRpcProviderService rpcProvider, + final ClassToInstanceMap services) { + this.rpcService = Preconditions.checkNotNull(rpcService, "DOMRpcService must not be null"); + this.rpcProvider = Preconditions.checkNotNull(rpcProvider, "DOMRpcProviderService must not be null"); + this.services = ImmutableClassToInstanceMap.copyOf(services); + } @Override public ConsumerSession registerConsumer(final Consumer consumer, @@ -130,21 +136,6 @@ public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService, this.deactivator = deactivator; } - /** - * @return the router - */ - public DOMRpcRouter getRouter() { - return router; - } - - /** - * @param router - * the router to set - */ - public void setRouter(final DOMRpcRouter router) { - this.router = router; - } - protected Optional getGlobalService(final Class service) { return Optional.fromNullable(services.getInstance(service)); } @@ -174,24 +165,24 @@ public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService, @Nonnull @Override public DOMRpcImplementationRegistration registerRpcImplementation(@Nonnull final T implementation, @Nonnull final DOMRpcIdentifier... rpcs) { - return router.registerRpcImplementation(implementation, rpcs); + return rpcProvider.registerRpcImplementation(implementation, rpcs); } @Nonnull @Override public DOMRpcImplementationRegistration registerRpcImplementation(@Nonnull final T implementation, @Nonnull final Set rpcs) { - return router.registerRpcImplementation(implementation, rpcs); + return rpcProvider.registerRpcImplementation(implementation, rpcs); } @Nonnull @Override public CheckedFuture invokeRpc(@Nonnull final SchemaPath type, @Nullable final NormalizedNode input) { - return router.invokeRpc(type, input); + return rpcService.invokeRpc(type, input); } @Nonnull @Override public ListenerRegistration registerRpcListener(@Nonnull final T listener) { - return router.registerRpcListener(listener); + return rpcService.registerRpcListener(listener); } } diff --git a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-config-dom-datastore.yang b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-config-dom-datastore.yang index 9a3ab181e0..4d9c7df5ab 100644 --- a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-config-dom-datastore.yang +++ b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-config-dom-datastore.yang @@ -14,9 +14,9 @@ module opendaylight-config-dom-datastore { } identity config-dom-datastore { - base "config:service-type"; - config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore"; - + base "config:service-type"; + config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore"; + config:disable-osgi-service-registration; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-md-sal-dom.yang b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-md-sal-dom.yang index db62d04eaa..cf21279ff1 100644 --- a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-md-sal-dom.yang +++ b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-md-sal-dom.yang @@ -21,15 +21,18 @@ module opendaylight-md-sal-dom { identity dom-async-data-broker { base "config:service-type"; config:java-class "org.opendaylight.controller.md.sal.dom.api.DOMDataBroker"; + config:disable-osgi-service-registration; } identity schema-service { base "config:service-type"; config:java-class "org.opendaylight.controller.sal.core.api.model.SchemaService"; + config:disable-osgi-service-registration; } identity yang-text-source-provider { base "config:service-type"; config:java-class "org.opendaylight.controller.sal.core.api.model.YangTextSourceProvider"; + config:disable-osgi-service-registration; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-operational-dom-datastore.yang b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-operational-dom-datastore.yang index fd408840bb..008010b7d4 100644 --- a/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-operational-dom-datastore.yang +++ b/opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-operational-dom-datastore.yang @@ -14,9 +14,9 @@ module opendaylight-operational-dom-datastore { } identity operational-dom-datastore { - base "config:service-type"; - config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore"; - + base "config:service-type"; + config:java-class "org.opendaylight.controller.sal.core.spi.data.DOMStore"; + config:disable-osgi-service-registration; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java index 4ada10a887..e4631f965d 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java @@ -8,16 +8,9 @@ package org.opendaylight.controller.config.yang.config.remote_rpc_connector; -import akka.actor.ActorSystem; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService; -import org.opendaylight.controller.remote.rpc.RemoteRpcProvider; -import org.opendaylight.controller.remote.rpc.RemoteRpcProviderConfig; -import org.opendaylight.controller.remote.rpc.RemoteRpcProviderFactory; -import org.opendaylight.controller.sal.core.api.Broker; -import org.osgi.framework.BundleContext; +import org.opendaylight.controller.sal.common.util.NoopAutoCloseable; public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModule { - private BundleContext bundleContext; public RemoteRPCBrokerModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } @@ -37,22 +30,9 @@ public class RemoteRPCBrokerModule extends org.opendaylight.controller.config.ya } @Override - public java.lang.AutoCloseable createInstance() { - Broker broker = getDomBrokerDependency(); - - ActorSystem actorSystem = getActorSystemProviderDependency().getActorSystem(); - RemoteRpcProviderConfig config = new RemoteRpcProviderConfig.Builder(actorSystem.name()) - .metricCaptureEnabled(getEnableMetricCapture()) - .mailboxCapacity(getBoundedMailboxCapacity()) - .build(); - - RemoteRpcProvider rpcProvider = RemoteRpcProviderFactory.createInstance((DOMRpcProviderService)broker, - actorSystem, config); - broker.registerProvider(rpcProvider); - return rpcProvider; - } - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; + public AutoCloseable createInstance() { + // The RemoteRpcProvider is created via blueprint and doesn't advertise any services so return a + // no-op here for backwards compatibility. + return NoopAutoCloseable.INSTANCE; } } diff --git a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java index 4d75ebb443..dec35597fe 100644 --- a/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java +++ b/opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java @@ -17,26 +17,5 @@ */ package org.opendaylight.controller.config.yang.config.remote_rpc_connector; - -import org.opendaylight.controller.config.api.DependencyResolver; -import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; -import org.opendaylight.controller.config.spi.Module; -import org.osgi.framework.BundleContext; - -public class RemoteRPCBrokerModuleFactory extends org.opendaylight.controller.config.yang.config.remote_rpc_connector.AbstractRemoteRPCBrokerModuleFactory { - @Override - public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) { - RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName,dependencyResolver,bundleContext); - module.setBundleContext(bundleContext); - return module; - } - - @Override - public Module createModule(String instanceName, DependencyResolver dependencyResolver, - DynamicMBeanWithInstance old, BundleContext bundleContext) throws Exception { - RemoteRPCBrokerModule module = (RemoteRPCBrokerModule)super.createModule(instanceName, dependencyResolver, - old, bundleContext); - module.setBundleContext(bundleContext); - return module; - } +public class RemoteRPCBrokerModuleFactory extends AbstractRemoteRPCBrokerModuleFactory { } diff --git a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/config/yang/config/clustering_it_provider/ClusteringItProviderModule.java b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/config/yang/config/clustering_it_provider/ClusteringItProviderModule.java index 45b4afaa6e..926054d325 100644 --- a/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/config/yang/config/clustering_it_provider/ClusteringItProviderModule.java +++ b/opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/config/yang/config/clustering_it_provider/ClusteringItProviderModule.java @@ -9,18 +9,7 @@ package org.opendaylight.controller.config.yang.config.clustering_it_provider; -import org.opendaylight.controller.clustering.it.listener.PeopleCarListener; -import org.opendaylight.controller.clustering.it.provider.CarProvider; -import org.opendaylight.controller.clustering.it.provider.PeopleProvider; -import org.opendaylight.controller.clustering.it.provider.PurchaseCarProvider; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; -import org.opendaylight.controller.sal.binding.api.NotificationProviderService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.sal.clustering.it.car.purchase.rev140818.CarPurchaseService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.sal.clustering.it.car.rev140818.CarService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.sal.clustering.it.people.rev140818.PeopleService; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.opendaylight.controller.sal.common.util.NoopAutoCloseable; public class ClusteringItProviderModule extends org.opendaylight.controller.config.yang.config.clustering_it_provider.AbstractClusteringItProviderModule { public ClusteringItProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -37,53 +26,8 @@ public class ClusteringItProviderModule extends org.opendaylight.controller.conf } @Override - public java.lang.AutoCloseable createInstance() { - DataBroker dataBrokerService = getDataBrokerDependency(); - NotificationProviderService notificationProvider = getNotificationServiceDependency(); - - // Add routed RPC registration for car purchase - final PurchaseCarProvider purchaseCar = new PurchaseCarProvider(); - purchaseCar.setNotificationProvider(notificationProvider); - - final BindingAwareBroker.RoutedRpcRegistration purchaseCarRpc = getRpcRegistryDependency() - .addRoutedRpcImplementation(CarPurchaseService.class, purchaseCar); - - // Add people provider registration - final PeopleProvider people = new PeopleProvider(); - people.setDataProvider(dataBrokerService); - - people.setRpcRegistration(purchaseCarRpc); - - CarProvider carProvider = new CarProvider(dataBrokerService, getOwnershipServiceDependency()); - getRpcRegistryDependency().addRpcImplementation(CarService.class, carProvider); - - final BindingAwareBroker.RpcRegistration peopleRpcReg = getRpcRegistryDependency() - .addRpcImplementation(PeopleService.class, people); - - - - final PeopleCarListener peopleCarListener = new PeopleCarListener(); - peopleCarListener.setDataProvider(dataBrokerService); - - final ListenerRegistration listenerReg = - getNotificationServiceDependency().registerNotificationListener( peopleCarListener ); - - // Wrap toaster as AutoCloseable and close registrations to md-sal at - // close() - final class AutoCloseableToaster implements AutoCloseable { - - @Override - public void close() throws Exception { - peopleRpcReg.close(); - purchaseCarRpc.close(); - people.close(); - purchaseCar.close(); - listenerReg.close(); - } - } - - AutoCloseable ret = new AutoCloseableToaster(); - return ret; + public AutoCloseable createInstance() { + // The components are created and wired via blueprint so return an empty AutoCloseable. + return NoopAutoCloseable.INSTANCE; } - } diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java index 75432769f2..65fba77fb6 100644 --- a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java +++ b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java @@ -18,15 +18,12 @@ package org.opendaylight.controller.config.yang.config.kitchen_service.impl; import java.util.concurrent.Future; - +import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker; import org.opendaylight.controller.sample.kitchen.api.EggsType; import org.opendaylight.controller.sample.kitchen.api.KitchenService; -import org.opendaylight.controller.sample.kitchen.impl.KitchenServiceImpl; import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToastType; -import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService; -import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.NotificationListener; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +33,8 @@ import org.slf4j.LoggerFactory; public final class KitchenServiceModule extends AbstractKitchenServiceModule { private static final Logger log = LoggerFactory.getLogger(KitchenServiceModule.class); + private BundleContext bundleContext; + public KitchenServiceModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); } @@ -53,36 +52,34 @@ public final class KitchenServiceModule extends AbstractKitchenServiceModule { } @Override - public java.lang.AutoCloseable createInstance() { - ToasterService toasterService = getRpcRegistryDependency().getRpcService(ToasterService.class); - - final KitchenServiceImpl kitchenService = new KitchenServiceImpl(toasterService); - - final ListenerRegistration toasterListenerReg = - getNotificationServiceDependency().registerNotificationListener( kitchenService ); - - final KitchenServiceRuntimeRegistration runtimeReg = - getRootRuntimeBeanRegistratorWrapper().register( kitchenService ); + public AutoCloseable createInstance() { + // The KitchenServiceImpl instance is created and advertised with the OSGi registry via blueprint + // so obtain it here so we can return it to the config system. It's possible the blueprint container + // hasn't been created yet so we busy wait 5 min for the service. + final WaitingServiceTracker tracker = WaitingServiceTracker.create( + KitchenService.class, bundleContext); + final KitchenService kitchenService = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES); final class AutoCloseableKitchenService implements KitchenService, AutoCloseable { - @Override - public void close() throws Exception { - toasterListenerReg.close(); - runtimeReg.close(); - log.info("Toaster consumer (instance {}) torn down.", this); + public void close() { + // We need to close the ServiceTracker however we don't want to close the actual + // KitchenService instance because its life-cycle is controlled via blueprint. + tracker.close(); + log.info("KitchenService (instance {}) closed.", kitchenService); } @Override - public Future> makeBreakfast( final EggsType eggs, - final Class toast, - final int toastDoneness ) { - return kitchenService.makeBreakfast( eggs, toast, toastDoneness ); + public Future> makeBreakfast(final EggsType eggs, final Class toast, + final int toastDoneness) { + return kitchenService.makeBreakfast(eggs, toast, toastDoneness); } } - AutoCloseable ret = new AutoCloseableKitchenService(); - log.info("KitchenService (instance {}) initialized.", ret ); - return ret; + return new AutoCloseableKitchenService(); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; } } diff --git a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java index 4b02ceca29..e57bc187f2 100644 --- a/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java +++ b/opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java @@ -17,9 +17,24 @@ */ package org.opendaylight.controller.config.yang.config.kitchen_service.impl; -/** - * - */ +import org.opendaylight.controller.config.api.DependencyResolver; +import org.osgi.framework.BundleContext; + public class KitchenServiceModuleFactory extends AbstractKitchenServiceModuleFactory { + @Override + public KitchenServiceModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + KitchenServiceModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) { + KitchenServiceModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, + oldInstance, bundleContext); + module.setBundleContext(bundleContext); + return module; + } + @Override + public KitchenServiceModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, + BundleContext bundleContext) { + KitchenServiceModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext); + module.setBundleContext(bundleContext); + return module; + } } diff --git a/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java b/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java index b255ad318f..c115fc9114 100644 --- a/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java +++ b/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java @@ -55,7 +55,7 @@ public class ToasterTest extends AbstractMdsalTestBase { @Test public void testToaster() throws Exception { MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer(); - ObjectName providerOn = new ObjectName("org.opendaylight.controller:instanceName=toaster-provider-impl,type=RuntimeBean,moduleFactoryName=toaster-provider-impl"); + ObjectName providerOn = new ObjectName("org.opendaylight.controller:name=OpendaylightToaster,type=toaster-provider"); long toastsMade = (long) platformMBeanServer.getAttribute(providerOn, "ToastsMade"); assertEquals(0, toastsMade); diff --git a/opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java b/opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java index 47c5692564..73438eb878 100644 --- a/opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java +++ b/opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java @@ -17,10 +17,7 @@ */ package org.opendaylight.controller.config.yang.config.toaster_provider.impl; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; -import org.opendaylight.controller.sample.toaster.provider.OpendaylightToaster; -import org.opendaylight.yang.gen.v1.http.netconfcentral.org.ns.toaster.rev091120.ToasterService; +import org.opendaylight.controller.sal.common.util.NoopAutoCloseable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,44 +49,8 @@ public final class ToasterProviderModule extends @Override public java.lang.AutoCloseable createInstance() { - final OpendaylightToaster opendaylightToaster = new OpendaylightToaster(); - - // Register to md-sal - opendaylightToaster.setNotificationProvider(getNotificationServiceDependency()); - - DataBroker dataBrokerService = getDataBrokerDependency(); - opendaylightToaster.setDataProvider(dataBrokerService); - - final BindingAwareBroker.RpcRegistration rpcRegistration = getRpcRegistryDependency() - .addRpcImplementation(ToasterService.class, opendaylightToaster); - - // Register runtimeBean for toaster statistics via JMX - final ToasterProviderRuntimeRegistration runtimeReg = getRootRuntimeBeanRegistratorWrapper().register( - opendaylightToaster); - - // Wrap toaster as AutoCloseable and close registrations to md-sal at - // close() - final class AutoCloseableToaster implements AutoCloseable { - - @Override - public void close() throws Exception { - rpcRegistration.close(); - runtimeReg.close(); - closeQuietly(opendaylightToaster); - log.info("Toaster provider (instance {}) torn down.", this); - } - - private void closeQuietly(final AutoCloseable resource) { - try { - resource.close(); - } catch (final Exception e) { - log.debug("Ignoring exception while closing {}", resource, e); - } - } - } - - AutoCloseable ret = new AutoCloseableToaster(); - log.info("Toaster provider (instance {}) initialized.", ret); - return ret; + // The components are created and wired via blueprint and, since this module doesn't advertise any + // services, return an empty AutoCloseable. The config module is kept for backwards compatibility. + return NoopAutoCloseable.INSTANCE; } } -- 2.36.6