Modify config Module impls to co-exist with blueprint 14/36714/26
authorTom Pantelis <tpanteli@brocade.com>
Mon, 28 Mar 2016 17:44:11 +0000 (13:44 -0400)
committerAnil Vishnoi <vishnoianil@gmail.com>
Fri, 22 Apr 2016 17:51:30 +0000 (17:51 +0000)
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 <tpanteli@brocade.com>
55 files changed:
features/mdsal/pom.xml
features/mdsal/src/main/features/features.xml
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/GlobalEventExecutorUtil.java [deleted file]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyModuleTest.java [deleted file]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyModuleTest.java [deleted file]
opendaylight/commons/protocol-framework/src/test/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyModuleTest.java [deleted file]
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/ServiceNotFoundException.java [new file with mode: 0644]
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/osgi/WaitingServiceTracker.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/AutoCloseableEventExecutor.java
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java
opendaylight/config/netty-threadgroup-config/pom.xml
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleFactory.java
opendaylight/config/netty-threadgroup-config/src/test/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModuleTest.java
opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModule.java
opendaylight/config/netty-timer-config/src/main/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleFactory.java
opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/binding/impl/RuntimeMappingModule.java
opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-binding-broker-impl.yang
opendaylight/md-sal/sal-binding-config/src/main/yang/opendaylight-md-sal-binding.yang
opendaylight/md-sal/sal-clustering-commons/src/main/yang/actor-system-provider-service.yang
opendaylight/md-sal/sal-common-api/src/main/yang/opendaylight-entity-ownership-service.yang
opendaylight/md-sal/sal-common-util/src/main/java/org/opendaylight/controller/sal/common/util/NoopAutoCloseable.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStore.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreInterface.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/admin/ClusterAdminRpcService.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/actor_system_provider/impl/ActorSystemProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/cluster_admin_provider/ClusterAdminProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/concurrent_data_broker/DomConcurrentDataBrokerModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/concurrent_data_broker/DomConcurrentDataBrokerModuleFactory.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedConfigDataStoreProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/DistributedOperationalDataStoreProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/ForwardingDistributedDataStore.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_entity_ownership_service/DistributedEntityOwnershipServiceProviderModule.java
opendaylight/md-sal/sal-distributed-datastore/src/main/resources/org/opendaylight/blueprint/clustered-datastore.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/yang/distributed-datastore-provider.yang
opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModule.java
opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/DomBrokerImplModuleFactory.java
opendaylight/md-sal/sal-dom-broker-config/src/main/java/org/opendaylight/controller/config/yang/md/sal/dom/impl/SchemaServiceImplSingletonModule.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMNotificationRouter.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.java
opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-config-dom-datastore.yang
opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-md-sal-dom.yang
opendaylight/md-sal/sal-dom-config/src/main/yang/opendaylight-operational-dom-datastore.yang
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModule.java
opendaylight/md-sal/sal-remoterpc-connector/src/main/java/org/opendaylight/controller/config/yang/config/remote_rpc_connector/RemoteRPCBrokerModuleFactory.java
opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/config/yang/config/clustering_it_provider/ClusteringItProviderModule.java
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModule.java
opendaylight/md-sal/samples/toaster-consumer/src/main/java/org/opendaylight/controller/config/yang/config/kitchen_service/impl/KitchenServiceModuleFactory.java
opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java
opendaylight/md-sal/samples/toaster-provider/src/main/java/org/opendaylight/controller/config/yang/config/toaster_provider/impl/ToasterProviderModule.java

index abb74a5..f12e9e1 100644 (file)
@@ -15,6 +15,7 @@
   <packaging>jar</packaging>
 
   <properties>
+    <blueprint.version>0.5.0-SNAPSHOT</blueprint.version>
     <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
     <mdsal.version>2.1.0-SNAPSHOT</mdsal.version>
     <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
       <artifactId>stax-utils</artifactId>
     </dependency>
 
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>blueprint</artifactId>
+      <version>${blueprint.version}</version>
+    </dependency>
+
     <!-- Required features repositories -->
     <dependency>
       <groupId>org.opendaylight.odlparent</groupId>
       <type>xml</type>
     </dependency>
 
-
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>md-sal-config</artifactId>
index b7283d0..897ec4f 100644 (file)
@@ -51,6 +51,7 @@
         <bundle>mvn:org.opendaylight.controller/sal-binding-config/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-inmemory-datastore/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.controller/sal-dom-broker-config/{{VERSION}}</bundle>
+        <bundle start-level="40">mvn:org.opendaylight.controller/blueprint/{{VERSION}}</bundle>
         <configfile finalname="${config.configfile.directory}/${config.mdsal.configfile}">mvn:org.opendaylight.controller/md-sal-config/{{VERSION}}/xml/config</configfile>
     </feature>
     <feature name='odl-toaster' version='${project.version}' description="OpenDaylight :: Toaster">
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 (file)
index 695e36c..0000000
+++ /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 (file)
index 77589ed..0000000
+++ /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 (file)
index 7e3ed5b..0000000
+++ /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 (file)
index ec8a9d6..0000000
+++ /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 (file)
index 0000000..0d9e7f0
--- /dev/null
@@ -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 (file)
index 0000000..1549e6b
--- /dev/null
@@ -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<T> 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<T, ?> tracker;
+    private final Class<T> serviceInterface;
+
+    private WaitingServiceTracker(Class<T> serviceInterface, ServiceTracker<T, ?> 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 <T> WaitingServiceTracker<T> create(@Nonnull Class<T> serviceInterface, @Nonnull BundleContext context) {
+        ServiceTracker<T, ?> tracker = new ServiceTracker<>(context, serviceInterface, null);
+        tracker.open();
+        return new WaitingServiceTracker<T>(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 <T> WaitingServiceTracker<T> create(@Nonnull Class<T> serviceInterface, @Nonnull BundleContext context,
+            @Nonnull String filter) {
+        String newFilter = String.format("(&(%s=%s)%s)", Constants.OBJECTCLASS, serviceInterface.getName(), filter);
+        try {
+            ServiceTracker<T, ?> tracker = new ServiceTracker<>(context, context.createFilter(newFilter), null);
+            tracker.open();
+            return new WaitingServiceTracker<T>(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);
+        }
+    }
+}
index cb721db..99d94d0 100644 (file)
@@ -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
index caca6b1..da06391 100644 (file)
  */
 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<EventExecutor> 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;
+    }
 }
index 1ca57c6..467f068 100644 (file)
@@ -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;
     }
 }
index 8fe3d7c..7d76369 100644 (file)
@@ -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
index 223eca1..5a0e483 100644 (file)
@@ -68,7 +68,6 @@
           <instructions>
             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
             <Export-Package>org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.netty.threadgroup.rev131107.*,</Export-Package>
-            <Import-Package>*,io.netty.channel</Import-Package>
           </instructions>
         </configuration>
       </plugin>
index 54266f4..09ea672 100644 (file)
 */
 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<EventLoopGroup> 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 {
     }
 }
index c97bd56..b509932 100644 (file)
 */
 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;
+    }
 }
index ceefcda..81f8584 100644 (file)
@@ -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
index 7114ed6..76d75e8 100644 (file)
  */
 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<Timer> 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 {
     }
 }
index c869413..d8ec0fc 100644 (file)
  */
 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;
+    }
 }
index 6ffeb04..9936823 100644 (file)
@@ -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 {
index 5ca041a..526f400 100644 (file)
@@ -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<BrokerService> domBrokerServices = ImmutableClassToInstanceMap
-                .<BrokerService> builder()
-                //
-                .put(DOMRpcRouter.class, biBrokerImpl.getRouter()) //
-                .put(DOMMountPointService.class, biMountImpl)
-                .build();
-
-        return new ProviderSession() {
-
-            @Override
-            public <T extends BrokerService> T getService(final Class<T> 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");
 
index e2d942e..f6b86eb 100644 (file)
@@ -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<String,String>());
-        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<ClassLoadingStrategy> 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) {
index 3244b5a..a56e2f9 100644 (file)
@@ -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;
                         }
                     }
index 18a94df..f1f19b4 100644 (file)
@@ -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;
     }
 
 }
index f284851..4f97c3a 100644 (file)
@@ -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
index f16f7c4..28aee9f 100644 (file)
@@ -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 (file)
index 0000000..7f95f96
--- /dev/null
@@ -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() {
+    }
+}
index 935af23..d545cf4 100644 (file)
             <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
             <Bundle-Activator>org.opendaylight.controller.cluster.datastore.osgi.Activator</Bundle-Activator>
             <Export-Package></Export-Package>
-            <Import-Package>!*snappy;!org.jboss.*;!com.jcraft.*;!*jetty*;!sun.security.*;*</Import-Package>
+            <Import-Package>
+                !*snappy;
+                !org.jboss.*;
+                !com.jcraft.*;
+                !*jetty*;
+                !sun.security.*;
+                *;
+                org.opendaylight.controller.md.sal.dom.broker.impl.jmx
+            </Import-Package>
             <!--
             <Embed-Dependency>
                 sal-clustering-commons;
index 198c3b2..579c897 100644 (file)
@@ -27,7 +27,6 @@ import org.opendaylight.controller.cluster.datastore.utils.PrimaryShardInfoFutur
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
-import org.opendaylight.controller.sal.core.spi.data.DOMStore;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
@@ -44,7 +43,7 @@ import org.slf4j.LoggerFactory;
 /**
  *
  */
-public class DistributedDataStore implements DOMStore, SchemaContextListener,
+public class DistributedDataStore implements DistributedDataStoreInterface, SchemaContextListener,
         DatastoreContextConfigAdminOverlay.Listener, DOMStoreTreeChangePublisher, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(DistributedDataStore.class);
@@ -215,6 +214,7 @@ public class DistributedDataStore implements DOMStore, SchemaContextListener,
         actorContext.shutdown();
     }
 
+    @Override
     public ActorContext getActorContext() {
         return actorContext;
     }
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreInterface.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/DistributedDataStoreInterface.java
new file mode 100644 (file)
index 0000000..b678d17
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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.cluster.datastore;
+
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+
+/**
+ * The public interface exposed vi a DistributedDataStore via the OSGi registry.
+ *
+ * @author Thomas Pantelis
+ */
+public interface DistributedDataStoreInterface extends DOMStore {
+
+    ActorContext getActorContext();
+}
\ No newline at end of file
index a67d3de..39aafca 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import org.apache.commons.lang3.SerializationUtils;
-import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
 import org.opendaylight.controller.cluster.datastore.messages.AddShardReplica;
 import org.opendaylight.controller.cluster.datastore.messages.DatastoreSnapshot;
 import org.opendaylight.controller.cluster.datastore.messages.DatastoreSnapshotList;
@@ -67,11 +67,12 @@ public class ClusterAdminRpcService implements ClusterAdminService, AutoCloseabl
 
     private static final Logger LOG = LoggerFactory.getLogger(ClusterAdminRpcService.class);
 
-    private final DistributedDataStore configDataStore;
-    private final DistributedDataStore operDataStore;
+    private final DistributedDataStoreInterface configDataStore;
+    private final DistributedDataStoreInterface operDataStore;
     private RpcRegistration<ClusterAdminService> rpcRegistration;
 
-    public ClusterAdminRpcService(DistributedDataStore configDataStore, DistributedDataStore operDataStore) {
+    public ClusterAdminRpcService(DistributedDataStoreInterface configDataStore,
+            DistributedDataStoreInterface operDataStore) {
         this.configDataStore = configDataStore;
         this.operDataStore = operDataStore;
     }
index 89f296d..8c2e8d0 100644 (file)
@@ -8,6 +8,12 @@
 
 package org.opendaylight.controller.config.yang.config.actor_system_provider.impl;
 
+import akka.actor.ActorSystem;
+import com.google.common.collect.ForwardingObject;
+import org.opendaylight.controller.cluster.ActorSystemProvider;
+import org.opendaylight.controller.cluster.ActorSystemProviderListener;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.osgi.framework.BundleContext;
 
 public class ActorSystemProviderModule extends AbstractActorSystemProviderModule {
@@ -27,11 +33,53 @@ public class ActorSystemProviderModule extends AbstractActorSystemProviderModule
     }
 
     @Override
-    public java.lang.AutoCloseable createInstance() {
-        return new ActorSystemProviderImpl(bundleContext);
+    public boolean canReuseInstance(AbstractActorSystemProviderModule oldModule) {
+        return true;
+    }
+
+    @Override
+    public AutoCloseable createInstance() {
+        // The service is provided via blueprint so wait for and return it here for backwards compatibility.
+        WaitingServiceTracker<ActorSystemProvider> tracker = WaitingServiceTracker.create(
+                ActorSystemProvider.class, bundleContext);
+        ActorSystemProvider delegate = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+        return new ForardingActorSystemProvider(delegate, tracker);
     }
 
     public void setBundleContext(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
+
+    private static class ForardingActorSystemProvider extends ForwardingObject
+            implements ActorSystemProvider, AutoCloseable {
+        private final ActorSystemProvider delegate;
+        private final AutoCloseable closeable;
+
+        ForardingActorSystemProvider(ActorSystemProvider delegate, AutoCloseable closeable) {
+            this.delegate = delegate;
+            this.closeable = closeable;
+        }
+
+        @Override
+        public ActorSystem getActorSystem() {
+            return delegate().getActorSystem();
+        }
+
+        @Override
+        public ListenerRegistration<ActorSystemProviderListener> registerActorSystemProviderListener(
+                ActorSystemProviderListener listener) {
+            return delegate().registerActorSystemProviderListener(listener);
+        }
+
+        @Override
+        protected ActorSystemProvider delegate() {
+            return delegate;
+        }
+
+        @Override
+        public void close() throws Exception {
+            // We don't close the delegate as the life-cycle is controlled via blueprint.
+            closeable.close();
+        }
+    }
 }
index 0d96368..facc07f 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.controller.config.yang.config.cluster_admin_provider;
 
 import com.google.common.base.Preconditions;
-import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
 import org.opendaylight.controller.cluster.datastore.admin.ClusterAdminRpcService;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
@@ -31,13 +31,14 @@ public class ClusterAdminProviderModule extends AbstractClusterAdminProviderModu
 
     @Override
     public AutoCloseable createInstance() {
-        Preconditions.checkArgument(getConfigDataStoreDependency() instanceof DistributedDataStore,
-                "Injected config DOMStore must be an instance of DistributedDataStore");
-        Preconditions.checkArgument(getOperDataStoreDependency() instanceof DistributedDataStore,
-                "Injected operational DOMStore must be an instance of DistributedDataStore");
-        ClusterAdminRpcService service = new ClusterAdminRpcService((DistributedDataStore)getConfigDataStoreDependency(),
-                (DistributedDataStore)getOperDataStoreDependency());
+        Preconditions.checkArgument(getConfigDataStoreDependency() instanceof DistributedDataStoreInterface,
+                "Injected config DOMStore must be an instance of DistributedDataStoreInterface");
+        Preconditions.checkArgument(getOperDataStoreDependency() instanceof DistributedDataStoreInterface,
+                "Injected operational DOMStore must be an instance of DistributedDataStoreInterface");
+        ClusterAdminRpcService service = new ClusterAdminRpcService(
+                (DistributedDataStoreInterface)getConfigDataStoreDependency(),
+                (DistributedDataStoreInterface)getOperDataStoreDependency());
         service.start(getRpcRegistryDependency());
         return service;
     }
-}
+}
\ No newline at end of file
index 262197f..5962293 100644 (file)
@@ -7,24 +7,14 @@
  */
 package org.opendaylight.controller.config.yang.config.concurrent_data_broker;
 
-import com.google.common.collect.Lists;
-import java.util.EnumMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker;
 import org.opendaylight.controller.config.api.DependencyResolver;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.util.jmx.AbstractMXBean;
-import org.opendaylight.controller.md.sal.common.util.jmx.ThreadExecutorStatsMXBeanImpl;
-import org.opendaylight.controller.md.sal.dom.broker.impl.jmx.CommitStatsMXBeanImpl;
-import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
-import org.opendaylight.controller.sal.core.spi.data.DOMStore;
-import org.opendaylight.yangtools.util.DurationStatisticsTracker;
-import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.spi.ForwardingDOMDataBroker;
+import org.osgi.framework.BundleContext;
 
 public class DomConcurrentDataBrokerModule extends AbstractDomConcurrentDataBrokerModule {
-    private static final String JMX_BEAN_TYPE = "DOMDataBroker";
+    private BundleContext bundleContext;
 
     public DomConcurrentDataBrokerModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
         super(identifier, dependencyResolver);
@@ -41,64 +31,36 @@ public class DomConcurrentDataBrokerModule extends AbstractDomConcurrentDataBrok
 
     @Override
     public AutoCloseable createInstance() {
-        //Initializing Operational DOM DataStore defaulting to InMemoryDOMDataStore if one is not configured
-        DOMStore operStore =  getOperationalDataStoreDependency();
-        if(operStore == null){
-           //we will default to InMemoryDOMDataStore creation
-          operStore = InMemoryDOMDataStoreFactory.create("DOM-OPER", getSchemaServiceDependency());
-        }
-
-        DOMStore configStore = getConfigDataStoreDependency();
-        if(configStore == null){
-           //we will default to InMemoryDOMDataStore creation
-           configStore = InMemoryDOMDataStoreFactory.create("DOM-CFG", getSchemaServiceDependency());
-        }
-
-        final Map<LogicalDatastoreType, DOMStore> datastores = new EnumMap<>(LogicalDatastoreType.class);
-        datastores.put(LogicalDatastoreType.OPERATIONAL, operStore);
-        datastores.put(LogicalDatastoreType.CONFIGURATION, configStore);
-
-        /*
-         * We use an executor for commit ListenableFuture callbacks that favors reusing available
-         * threads over creating new threads at the expense of execution time. The assumption is
-         * that most ListenableFuture callbacks won't execute a lot of business logic where we want
-         * it to run quicker - many callbacks will likely just handle error conditions and do
-         * nothing on success. The executor queue capacity is bounded and, if the capacity is
-         * reached, subsequent submitted tasks will block the caller.
-         */
-        ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
-                getMaxDataBrokerFutureCallbackPoolSize(), getMaxDataBrokerFutureCallbackQueueSize(),
-                "CommitFutures");
+        // The ConcurrentDOMDataBroker is provided via blueprint so wait for and return it here for
+        // backwards compatibility.
+        WaitingServiceTracker<DOMDataBroker> tracker = WaitingServiceTracker.create(
+                DOMDataBroker.class, bundleContext, "(type=default)");
+        DOMDataBroker delegate = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+        return new ForwardingConcurrentDOMBroker(delegate, tracker);
+    }
 
-        final List<AbstractMXBean> mBeans = Lists.newArrayList();
+    public void setBundleContext(final BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
 
-        final DurationStatisticsTracker commitStatsTracker;
-        final ConcurrentDOMDataBroker cdb = new ConcurrentDOMDataBroker(datastores, listenableFutureExecutor);
-        commitStatsTracker = cdb.getCommitStatsTracker();
+    private static class ForwardingConcurrentDOMBroker extends ForwardingDOMDataBroker implements AutoCloseable {
+        private final DOMDataBroker delegate;
+        private final AutoCloseable closeable;
 
-        if(commitStatsTracker != null) {
-            final CommitStatsMXBeanImpl commitStatsMXBean = new CommitStatsMXBeanImpl(
-                    commitStatsTracker, JMX_BEAN_TYPE);
-            commitStatsMXBean.registerMBean();
-            mBeans.add(commitStatsMXBean);
+        ForwardingConcurrentDOMBroker(DOMDataBroker delegate, AutoCloseable closeable) {
+            this.delegate = delegate;
+            this.closeable = closeable;
         }
 
-        final AbstractMXBean commitFutureStatsMXBean =
-                ThreadExecutorStatsMXBeanImpl.create(listenableFutureExecutor,
-                        "CommitFutureExecutorStats", JMX_BEAN_TYPE, null);
-        if(commitFutureStatsMXBean != null) {
-            mBeans.add(commitFutureStatsMXBean);
+        @Override
+        protected DOMDataBroker delegate() {
+            return delegate;
         }
 
-        cdb.setCloseable(new AutoCloseable() {
-            @Override
-            public void close() {
-                for(AbstractMXBean mBean: mBeans) {
-                    mBean.unregisterMBean();
-                }
-            }
-        });
-
-        return cdb;
+        @Override
+        public void close() throws Exception {
+            // We don't close the delegate as the life-cycle is controlled via blueprint.
+            closeable.close();
+        }
     }
 }
index d42c444..c6f5a9e 100644 (file)
@@ -7,6 +7,26 @@
  */
 package org.opendaylight.controller.config.yang.config.concurrent_data_broker;
 
+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 DomConcurrentDataBrokerModuleFactory extends AbstractDomConcurrentDataBrokerModuleFactory {
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        DomConcurrentDataBrokerModule module = (DomConcurrentDataBrokerModule)super.createModule(instanceName,
+                dependencyResolver, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
 
+    @Override
+    public Module createModule(String instanceName, DependencyResolver dependencyResolver, DynamicMBeanWithInstance old,
+            BundleContext bundleContext) throws Exception {
+        DomConcurrentDataBrokerModule module = (DomConcurrentDataBrokerModule)super.createModule(instanceName,
+                dependencyResolver, old, bundleContext);
+        module.setBundleContext(bundleContext);
+        return module;
+    }
 }
index daa4c14..3076323 100644 (file)
@@ -9,8 +9,8 @@
 package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
 
 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
-import org.opendaylight.controller.cluster.datastore.DatastoreSnapshotRestore;
-import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.osgi.framework.BundleContext;
 
@@ -43,12 +43,13 @@ public class DistributedConfigDataStoreProviderModule extends
     }
 
     @Override
-    public java.lang.AutoCloseable createInstance() {
-        DatastoreContext datastoreContext = newDatastoreContext(getConfigProperties());
-
-        return DistributedDataStoreFactory.createInstance(getConfigSchemaServiceDependency(),
-                datastoreContext, DatastoreSnapshotRestore.instance(),
-                getConfigActorSystemProviderDependency(), bundleContext);
+    public AutoCloseable createInstance() {
+        // The DistributedConfigDataStore is provided via blueprint so wait for and return it here for
+        // backwards compatibility.
+        WaitingServiceTracker<DistributedDataStoreInterface> tracker = WaitingServiceTracker.create(
+                DistributedDataStoreInterface.class, bundleContext, "(type=distributed-config)");
+        DistributedDataStoreInterface delegate = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+        return new ForwardingDistributedDataStore(delegate, tracker);
     }
 
     public static DatastoreContext newDatastoreContext() {
index 9bb6b82..e7589e0 100644 (file)
@@ -9,8 +9,8 @@
 package org.opendaylight.controller.config.yang.config.distributed_datastore_provider;
 
 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
-import org.opendaylight.controller.cluster.datastore.DatastoreSnapshotRestore;
-import org.opendaylight.controller.cluster.datastore.DistributedDataStoreFactory;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.osgi.framework.BundleContext;
 
@@ -44,11 +44,12 @@ public class DistributedOperationalDataStoreProviderModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        DatastoreContext datastoreContext = newDatastoreContext(getOperationalProperties());
-
-        return DistributedDataStoreFactory.createInstance(getOperationalSchemaServiceDependency(),
-                datastoreContext, DatastoreSnapshotRestore.instance(),
-                getOperationalActorSystemProviderDependency(), bundleContext);
+        // The DistributedOperDataStore is provided via blueprint so wait for and return it here for
+        // backwards compatibility
+        WaitingServiceTracker<DistributedDataStoreInterface> tracker = WaitingServiceTracker.create(
+                DistributedDataStoreInterface.class, bundleContext, "(type=distributed-operational)");
+        DistributedDataStoreInterface delegate = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+        return new ForwardingDistributedDataStore(delegate, tracker);
     }
 
     public static DatastoreContext newDatastoreContext() {
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/ForwardingDistributedDataStore.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/config/yang/config/distributed_datastore_provider/ForwardingDistributedDataStore.java
new file mode 100644 (file)
index 0000000..b04bf1b
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * 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.yang.config.distributed_datastore_provider;
+
+import com.google.common.collect.ForwardingObject;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
+import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * DOMStore implementation that forwards to a delegate.
+ *
+ * @author Thomas Pantelis
+ */
+class ForwardingDistributedDataStore extends ForwardingObject implements DistributedDataStoreInterface, AutoCloseable {
+    private final DistributedDataStoreInterface delegate;
+    private final AutoCloseable closeable;
+
+    ForwardingDistributedDataStore(DistributedDataStoreInterface delegate, AutoCloseable closeable) {
+        this.delegate = delegate;
+        this.closeable = closeable;
+    }
+
+    @Override
+    public DOMStoreReadTransaction newReadOnlyTransaction() {
+        return delegate().newReadOnlyTransaction();
+    }
+
+    @Override
+    public DOMStoreWriteTransaction newWriteOnlyTransaction() {
+        return delegate().newWriteOnlyTransaction();
+    }
+
+    @Override
+    public DOMStoreReadWriteTransaction newReadWriteTransaction() {
+        return delegate().newReadWriteTransaction();
+    }
+
+    @Override
+    public <L extends AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>>> ListenerRegistration<L> registerChangeListener(
+            YangInstanceIdentifier path, L listener, DataChangeScope scope) {
+        return delegate().registerChangeListener(path, listener, scope);
+    }
+
+    @Override
+    public DOMStoreTransactionChain createTransactionChain() {
+        return delegate().createTransactionChain();
+    }
+
+    @Override
+    public ActorContext getActorContext() {
+        return delegate().getActorContext();
+    }
+
+    @Override
+    public void close() throws Exception {
+        closeable.close();
+    }
+
+    @Override
+    protected DistributedDataStoreInterface delegate() {
+        return delegate;
+    }
+}
index c0a4585..a7ea21f 100644 (file)
@@ -8,19 +8,21 @@
 
 package org.opendaylight.controller.config.yang.config.distributed_entity_ownership_service;
 
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
-import org.opendaylight.controller.cluster.datastore.entityownership.DistributedEntityOwnershipService;
-import org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.EntityOwnerSelectionStrategyConfig;
-import org.opendaylight.controller.cluster.datastore.entityownership.selectionstrategy.EntityOwnerSelectionStrategyConfigReader;
-import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
+import com.google.common.base.Optional;
+import com.google.common.collect.ForwardingObject;
 import org.opendaylight.controller.config.api.DependencyResolver;
 import org.opendaylight.controller.config.api.ModuleIdentifier;
-import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
 import org.osgi.framework.BundleContext;
 
 public class DistributedEntityOwnershipServiceProviderModule extends AbstractDistributedEntityOwnershipServiceProviderModule {
-    private EntityOwnerSelectionStrategyConfig strategyConfig;
     private BundleContext bundleContext;
 
     public DistributedEntityOwnershipServiceProviderModule(final ModuleIdentifier identifier,
@@ -36,7 +38,6 @@ public class DistributedEntityOwnershipServiceProviderModule extends AbstractDis
 
     @Override
     public void customValidation() {
-        strategyConfig = EntityOwnerSelectionStrategyConfigReader.loadStrategyWithConfig(bundleContext);
     }
 
     @Override
@@ -46,17 +47,59 @@ public class DistributedEntityOwnershipServiceProviderModule extends AbstractDis
 
     @Override
     public AutoCloseable createInstance() {
-        // FIXME: EntityOwnership needs only the ActorContext, not the entire datastore
-        DOMStore dataStore = getDataStoreDependency();
-        Preconditions.checkArgument(dataStore instanceof DistributedDataStore,
-                "Injected DOMStore must be an instance of DistributedDataStore");
-
-        final ActorContext context = ((DistributedDataStore)dataStore).getActorContext();
-        return DistributedEntityOwnershipService.start(context, strategyConfig);
+        // The DistributedEntityOwnershipService is provided via blueprint so wait for and return it here for
+        // backwards compatibility.
+        WaitingServiceTracker<EntityOwnershipService> tracker = WaitingServiceTracker.create(
+                EntityOwnershipService.class, bundleContext);
+        EntityOwnershipService delegate = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
+        return new ForwardingEntityOwnershipService(delegate, tracker);
     }
 
     public void setBundleContext(final BundleContext bundleContext) {
-        // What do we need from the bundle context?
         this.bundleContext = bundleContext;
     }
+
+    private static class ForwardingEntityOwnershipService extends ForwardingObject
+            implements EntityOwnershipService, AutoCloseable {
+        private final EntityOwnershipService delegate;
+        private final AutoCloseable closeable;
+
+        public ForwardingEntityOwnershipService(EntityOwnershipService delegate, AutoCloseable closeable) {
+            this.delegate = delegate;
+            this.closeable = closeable;
+        }
+
+        @Override
+        public EntityOwnershipCandidateRegistration registerCandidate(Entity entity)
+                throws CandidateAlreadyRegisteredException {
+            return delegate().registerCandidate(entity);
+        }
+
+        @Override
+        public EntityOwnershipListenerRegistration registerListener(String entityType,
+                EntityOwnershipListener listener) {
+            return delegate().registerListener(entityType, listener);
+        }
+
+        @Override
+        public Optional<EntityOwnershipState> getOwnershipState(Entity forEntity) {
+            return delegate().getOwnershipState(forEntity);
+        }
+
+        @Override
+        public boolean isCandidateRegistered(Entity entity) {
+            return delegate().isCandidateRegistered(entity);
+        }
+
+        @Override
+        protected EntityOwnershipService delegate() {
+            return delegate;
+        }
+
+        @Override
+        public void close() throws Exception {
+            // We don't close the delegate as the life-cycle is controlled via blueprint.
+            closeable.close();
+        }
+    }
 }
index ac0f02f..cd2ee2d 100644 (file)
     <argument ref="blueprintBundleContext"/>
   </bean>
 
+  <service ref="configDatastore" odl:type="distributed-config">
+    <interfaces>
+      <value>org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface</value>
+    </interfaces>
+  </service>
+
   <!-- Distributed Operational Datastore -->
 
   <bean id="operDatastoreContext" class="org.opendaylight.controller.config.yang.config.distributed_datastore_provider.DistributedOperationalDataStoreProviderModule"
     <argument ref="blueprintBundleContext"/>
   </bean>
 
+  <service ref="operDatastore" odl:type="distributed-operational">
+    <interfaces>
+      <value>org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface</value>
+    </interfaces>
+  </service>
+
   <!-- Concurrent DOMDataBroker -->
 
   <bean id="listenableFutureExecutor" class="org.opendaylight.yangtools.util.concurrent.SpecialExecutors"
@@ -64,7 +76,7 @@
   <bean id="commitStatsTracker" class="org.opendaylight.yangtools.util.DurationStatisticsTracker"
           factory-method="createConcurrent"/>
 
-  <bean id="clusteredDOMDataBroker" class="org.opendaylight.controller.cluster.datastore.ConcurrentDOMDataBroker"
+  <bean id="clusteredDOMDataBroker" class="org.opendaylight.controller.cluster.databroker.ConcurrentDOMDataBroker"
           destroy-method="close">
     <argument>
       <map>
 
   <service ref="distributedEntityOwnershipService" interface="org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService"
         odl:type="default"/>
-
 </blueprint>
\ No newline at end of file
index d40a3aa..8174c77 100644 (file)
@@ -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;
                         }
                     }
index 61385de..895d3d2 100644 (file)
@@ -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<AutoCloseable> 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<BrokerService> 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 <T> WaitingServiceTracker<T> newTracker(Class<T> serviceInterface, List<AutoCloseable> closeables) {
+        WaitingServiceTracker<T> 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;
+    }
 }
index f1fcb49..5223018 100644 (file)
@@ -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;
+    }
 }
index 62b0264..dae7f05 100644 (file)
@@ -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<SchemaService> {
+    private static class GlobalSchemaServiceProxy implements AutoCloseable, SchemaService, YangTextSourceProvider,
+            Delegator<SchemaService> {
+        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<? extends YangTextSchemaSource, SchemaSourceException> getSource(
+                SourceIdentifier sourceIdentifier) {
+            return delegate.getSource(sourceIdentifier);
+        }
     }
 }
index 138de6b..64c6b9e 100644 (file)
@@ -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);
 
index 03fbb18..6cd0ebc 100644 (file)
@@ -46,17 +46,23 @@ public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService,
     private final Set<ProviderContextImpl> providerSessions = Collections
             .synchronizedSet(new HashSet<ProviderContextImpl>());
 
-    private AutoCloseable deactivator = null;
+    private AutoCloseable deactivator;
 
-    private DOMRpcRouter router = null;
+    private final DOMRpcService rpcService;
+    private final DOMRpcProviderService rpcProvider;
 
     private final ClassToInstanceMap<BrokerService> services;
 
-    public  BrokerImpl(final DOMRpcRouter router,final ClassToInstanceMap<BrokerService> services) {
-        this.router = Preconditions.checkNotNull(router, "RPC Router must not be null");
-        this.services = ImmutableClassToInstanceMap.copyOf(services);
+    public BrokerImpl(final DOMRpcRouter router,final ClassToInstanceMap<BrokerService> services) {
+        this(router, router, services);
     }
 
+    public BrokerImpl(final DOMRpcService rpcService, final DOMRpcProviderService rpcProvider,
+            final ClassToInstanceMap<BrokerService> 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 <T extends BrokerService> Optional<T> getGlobalService(final Class<T> service) {
         return Optional.fromNullable(services.getInstance(service));
     }
@@ -174,24 +165,24 @@ public class BrokerImpl implements Broker, DOMRpcProviderService, DOMRpcService,
     @Nonnull
     @Override
     public <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull final T implementation, @Nonnull final DOMRpcIdentifier... rpcs) {
-        return router.registerRpcImplementation(implementation, rpcs);
+        return rpcProvider.registerRpcImplementation(implementation, rpcs);
     }
 
     @Nonnull
     @Override
     public <T extends DOMRpcImplementation> DOMRpcImplementationRegistration<T> registerRpcImplementation(@Nonnull final T implementation, @Nonnull final Set<DOMRpcIdentifier> rpcs) {
-        return router.registerRpcImplementation(implementation, rpcs);
+        return rpcProvider.registerRpcImplementation(implementation, rpcs);
     }
 
     @Nonnull
     @Override
     public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull final SchemaPath type, @Nullable final NormalizedNode<?, ?> input) {
-        return router.invokeRpc(type, input);
+        return rpcService.invokeRpc(type, input);
     }
 
     @Nonnull
     @Override
     public <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(@Nonnull final T listener) {
-        return router.registerRpcListener(listener);
+        return rpcService.registerRpcListener(listener);
     }
 }
index 9a3ab18..4d9c7df 100644 (file)
@@ -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
index db62d04..cf21279 100644 (file)
@@ -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
index fd40884..008010b 100644 (file)
@@ -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
index 4ada10a..e4631f9 100644 (file)
@@ -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;
     }
 }
index 4d75ebb..dec3559 100644 (file)
 */
 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 {
 }
index 45b4afa..926054d 100644 (file)
@@ -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<CarPurchaseService> 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<PeopleService> peopleRpcReg = getRpcRegistryDependency()
-          .addRpcImplementation(PeopleService.class, people);
-
-
-
-      final PeopleCarListener peopleCarListener = new PeopleCarListener();
-      peopleCarListener.setDataProvider(dataBrokerService);
-
-      final ListenerRegistration<NotificationListener> 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;
     }
-
 }
index 7543276..65fba77 100644 (file)
 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<NotificationListener> 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<KitchenService> 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<RpcResult<Void>> makeBreakfast( final EggsType eggs,
-                                                          final Class<? extends ToastType> toast,
-                                                          final int toastDoneness ) {
-                return kitchenService.makeBreakfast( eggs, toast, toastDoneness );
+            public Future<RpcResult<Void>> makeBreakfast(final EggsType eggs, final Class<? extends ToastType> 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;
     }
 }
index 4b02cec..e57bc18 100644 (file)
  */
 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;
+    }
 }
index b255ad3..c115fc9 100644 (file)
@@ -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);
index 47c5692..73438eb 100644 (file)
 */
 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<ToasterService> 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;
     }
 }