<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>
<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">
+++ /dev/null
-/*
- * 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);
- }
- }
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
}
@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
*/
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) {
}
@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;
+ }
}
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;
@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;
}
}
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;
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
<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>
*/
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);
}
}
@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 {
}
}
*/
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;
+ }
}
*/
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;
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
*/
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) {
}
@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 {
}
}
*/
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;
+ }
}
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;
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 {
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 {
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;
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;
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 {
}
- 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");
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;
@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) {
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 {
container notification-service {
uses config:service-ref {
refine type {
- mandatory true;
+ mandatory false;
config:required-identity sal:binding-notification-service;
}
}
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 {
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;
}
}
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
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
--- /dev/null
+/*
+ * 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() {
+ }
+}
<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;
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;
/**
*
*/
-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);
actorContext.shutdown();
}
+ @Override
public ActorContext getActorContext() {
return actorContext;
}
--- /dev/null
+/*
+ * 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
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;
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;
}
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 {
}
@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();
+ }
+ }
}
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;
@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
*/
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);
@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();
+ }
}
}
*/
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;
+ }
}
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;
}
@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() {
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;
@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() {
--- /dev/null
+/*
+ * 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;
+ }
+}
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,
@Override
public void customValidation() {
- strategyConfig = EntityOwnerSelectionStrategyConfigReader.loadStrategyWithConfig(bundleContext);
}
@Override
@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();
+ }
+ }
}
<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"
<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
container config-schema-service {
uses config:service-ref {
refine type {
- mandatory true;
+ mandatory false;
config:required-identity sal:schema-service;
}
}
container config-actor-system-provider {
uses config:service-ref {
refine type {
- mandatory true;
+ mandatory false;
config:required-identity actor-system:actor-system-provider-service;
}
}
container operational-schema-service {
uses config:service-ref {
refine type {
- mandatory true;
+ mandatory false;
config:required-identity sal:schema-service;
}
}
container operational-actor-system-provider {
uses config:service-ref {
refine type {
- mandatory true;
+ mandatory false;
config:required-identity actor-system:actor-system-provider-service;
}
}
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);
@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() {
}
return schemaService;
}
+
+ public void setBundleContext(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
}
*/
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;
+ }
}
*/
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;
@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
return delegate;
}
+ @Override
+ public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> getSource(
+ SourceIdentifier sourceIdentifier) {
+ return delegate.getSource(sourceIdentifier);
+ }
}
}
}
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);
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,
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));
}
@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);
}
}
}
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
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
}
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
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);
}
}
@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;
}
}
*/
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 {
}
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) {
}
@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;
}
-
}
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;
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);
}
}
@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;
}
}
*/
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;
+ }
}
@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);
*/
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;
@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;
}
}