<bundle start="true" start-level="35">mvn:org.javassist/javassist/${javassist.version}</bundle>
<bundle start="true" start-level="35">mvn:commons-io/commons-io/${commons.io.version}</bundle>
<bundle start="true" start-level="35">mvn:commons-codec/commons-codec/${commons.codec.version}</bundle>
- <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang.version}</bundle>
+ <bundle start="true" start-level="35">mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
<bundle start="true" start-level="35">mvn:commons-net/commons-net/${commons.net.version}</bundle>
</feature>
<feature name="base-eclipselink-persistence" description="EclipseLink Persistence API" version="2.0.4.v201112161009">
<appauth.version>0.4.2-SNAPSHOT</appauth.version>
<archetype-app-northbound>0.0.1-SNAPSHOT</archetype-app-northbound>
<aries.util.version>1.1.0</aries.util.version>
- <!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+ <!-- Controller Modules Versions -->
<arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
<asm.version>4.1</asm.version>
<!-- Plugin Versions -->
<commons.jasper>7.0.32.v201211201952</commons.jasper>
<commons.juli.version>7.0.32.v201211081135</commons.juli.version>
<commons.lang.version>3.1</commons.lang.version>
+ <commons.lang3.version>3.1</commons.lang3.version>
<commons.logback_settings.version>0.0.2-SNAPSHOT</commons.logback_settings.version>
<commons.net.version>3.0.1</commons.net.version>
<commons.opendaylight.commons.httpclient>0.1.2-SNAPSHOT</commons.opendaylight.commons.httpclient>
<artifactId>akka-remote_${scala.version}</artifactId>
<version>${akka.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-testkit_${scala.version}</artifactId>
+ <version>${akka.version}</version>
+ </dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
- <version>${commons.lang.version}</version>
+ <version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
OpenType<?> innerCompositeType;
if(isDerivedType(innerTypeBaseType, innerType)) {
- innerCompositeType = getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
+ innerCompositeType = baseInnerTypeDefinition instanceof UnionTypeDefinition ?
+ getCompositeTypeForUnion(baseInnerTypeDefinition) :
+ getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
} else {
innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
}
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
- <artifactId>features-file</artifactId>
+ <artifactId>features-yangtools</artifactId>
<version>${yangtools.version}</version>
<classifier>features</classifier>
<type>xml</type>
<name>runtime-mapping-singleton</name>
</binding-mapping-service>
</module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
+ <name>binding-async-data-broker</name>
+ <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <dom-async-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-async-broker>
+ <binding-mapping-service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+ <name>runtime-mapping-singleton</name>
+ </binding-mapping-service>
+ </binding-forwarded-data-broker>
+ </module>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
</instance>
</service>
+ <service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <instance>
+ <name>binding-data-broker</name>
+ <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
+ </instance>
+ </service>
+
<service>
<type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
<instance>
VlanIdBuilder vlanIDBuilder = new VlanIdBuilder();
vlanIDBuilder.setVlanId(new VlanId((NetUtils
.getUnsignedShort((short) vlan.getValue()))));
+ vlanIDBuilder.setVlanIdPresent(true);
vlanMatchBuild.setVlanId(vlanIDBuilder.build());
}
*/
package org.opendaylight.controller.md.inventory.manager;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FlowCapableInventoryProvider implements AutoCloseable {
+import com.google.common.base.Preconditions;
+
+class FlowCapableInventoryProvider implements AutoCloseable, Runnable {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
+ private static final int QUEUE_DEPTH = 500;
+ private static final int MAX_BATCH = 100;
+
+ private final BlockingQueue<InventoryOperation> queue = new LinkedBlockingDeque<>(QUEUE_DEPTH);
+ private final NotificationProviderService notificationService;
+ private final DataProviderService dataService;
+ private Registration<?> listenerRegistration;
+ private Thread thread;
- private final static Logger LOG = LoggerFactory.getLogger(FlowCapableInventoryProvider.class);
+ FlowCapableInventoryProvider(final DataProviderService dataService, final NotificationProviderService notificationService) {
+ this.dataService = Preconditions.checkNotNull(dataService);
+ this.notificationService = Preconditions.checkNotNull(notificationService);
+ }
+
+ void start() {
+ final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
+ this.listenerRegistration = this.notificationService.registerNotificationListener(changeCommiter);
- private DataProviderService dataService;
- private NotificationProviderService notificationService;
- private Registration<NotificationListener> listenerRegistration;
- private final NodeChangeCommiter changeCommiter = new NodeChangeCommiter(FlowCapableInventoryProvider.this);
+ thread = new Thread(this);
+ thread.setDaemon(true);
+ thread.setName("FlowCapableInventoryProvider");
+ thread.start();
- public void start() {
- this.listenerRegistration = this.notificationService.registerNotificationListener(this.changeCommiter);
LOG.info("Flow Capable Inventory Provider started.");
}
- protected DataModificationTransaction startChange() {
- DataProviderService _dataService = this.dataService;
- return _dataService.beginTransaction();
+ void enqueue(final InventoryOperation op) {
+ try {
+ queue.put(op);
+ } catch (InterruptedException e) {
+ LOG.warn("Failed to enqueue operation {}", op, e);
+ }
}
@Override
- public void close() {
- try {
- LOG.info("Flow Capable Inventory Provider stopped.");
- if (this.listenerRegistration != null) {
+ public void close() throws InterruptedException {
+ LOG.info("Flow Capable Inventory Provider stopped.");
+ if (this.listenerRegistration != null) {
+ try {
this.listenerRegistration.close();
+ } catch (Exception e) {
+ LOG.error("Failed to stop inventory provider", e);
}
- } catch (Exception e) {
- String errMsg = "Error by stop Flow Capable Inventory Provider.";
- LOG.error(errMsg, e);
- throw new RuntimeException(errMsg, e);
+ listenerRegistration = null;
}
- }
- public DataProviderService getDataService() {
- return this.dataService;
- }
+ if (thread != null) {
+ thread.interrupt();
+ thread.join();
+ thread = null;
+ }
- public void setDataService(final DataProviderService dataService) {
- this.dataService = dataService;
- }
- public NotificationProviderService getNotificationService() {
- return this.notificationService;
}
- public void setNotificationService(
- final NotificationProviderService notificationService) {
- this.notificationService = notificationService;
+ @Override
+ public void run() {
+ try {
+ for (;;) {
+ InventoryOperation op = queue.take();
+
+ final DataModificationTransaction tx = dataService.beginTransaction();
+ LOG.debug("New operations available, starting transaction {}", tx.getIdentifier());
+
+ int ops = 0;
+ do {
+ op.applyOperation(tx);
+
+ ops++;
+ if (ops < MAX_BATCH) {
+ op = queue.poll();
+ } else {
+ op = null;
+ }
+ } while (op != null);
+
+ LOG.debug("Processed {} operations, submitting transaction {}", ops, tx.getIdentifier());
+
+ try {
+ final RpcResult<TransactionStatus> result = tx.commit().get();
+ if(!result.isSuccessful()) {
+ LOG.error("Transaction {} failed", tx.getIdentifier());
+ }
+ } catch (ExecutionException e) {
+ LOG.warn("Failed to commit inventory change", e.getCause());
+ }
+ }
+ } catch (InterruptedException e) {
+ LOG.info("Processing interrupted, terminating", e);
+ }
+
+ // Drain all events, making sure any blocked threads are unblocked
+ while (!queue.isEmpty()) {
+ queue.poll();
+ }
}
}
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class InventoryActivator extends AbstractBindingAwareProvider {
-
- private static FlowCapableInventoryProvider provider = new FlowCapableInventoryProvider();
+ private static final Logger LOG = LoggerFactory.getLogger(InventoryActivator.class);
+ private FlowCapableInventoryProvider provider;
@Override
public void onSessionInitiated(final ProviderContext session) {
- DataProviderService salDataService = session.<DataProviderService> getSALService(DataProviderService.class);
+ DataProviderService salDataService = session.getSALService(DataProviderService.class);
NotificationProviderService salNotifiService =
- session.<NotificationProviderService> getSALService(NotificationProviderService.class);
- InventoryActivator.provider.setDataService(salDataService);
- InventoryActivator.provider.setNotificationService(salNotifiService);
- InventoryActivator.provider.start();
+ session.getSALService(NotificationProviderService.class);
+
+ provider = new FlowCapableInventoryProvider(salDataService, salNotifiService);
+ provider.start();
}
@Override
protected void stopImpl(final BundleContext context) {
- InventoryActivator.provider.close();
+ if (provider != null) {
+ try {
+ provider.close();
+ } catch (InterruptedException e) {
+ LOG.warn("Interrupted while waiting for shutdown", e);
+ }
+ provider = null;
+ }
}
}
--- /dev/null
+/**
+ * Copyright (c) 2014 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.md.inventory.manager;
+
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+
+interface InventoryOperation {
+
+ void applyOperation(DataModificationTransaction tx);
+
+}
*/
package org.opendaylight.controller.md.inventory.manager;
-import java.util.concurrent.Future;
-
-import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Objects;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-
-public class NodeChangeCommiter implements OpendaylightInventoryListener {
+import com.google.common.base.Preconditions;
- protected final static Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
+class NodeChangeCommiter implements OpendaylightInventoryListener {
+ private static final Logger LOG = LoggerFactory.getLogger(NodeChangeCommiter.class);
private final FlowCapableInventoryProvider manager;
public NodeChangeCommiter(final FlowCapableInventoryProvider manager) {
- this.manager = manager;
- }
-
- public FlowCapableInventoryProvider getManager() {
- return this.manager;
+ this.manager = Preconditions.checkNotNull(manager);
}
@Override
public synchronized void onNodeConnectorRemoved(final NodeConnectorRemoved connector) {
-
- final NodeConnectorRef ref = connector.getNodeConnectorRef();
- final DataModificationTransaction it = this.getManager().startChange();
- LOG.debug("removing node connector {} ", ref.getValue());
- it.removeOperationalData(ref.getValue());
- Future<RpcResult<TransactionStatus>> commitResult = it.commit();
- listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector removal", ref.getValue());
+ manager.enqueue(new InventoryOperation() {
+ @Override
+ public void applyOperation(final DataModificationTransaction tx) {
+ final NodeConnectorRef ref = connector.getNodeConnectorRef();
+ LOG.debug("removing node connector {} ", ref.getValue());
+ tx.removeOperationalData(ref.getValue());
+ }
+ });
}
@Override
public synchronized void onNodeConnectorUpdated(final NodeConnectorUpdated connector) {
-
- final NodeConnectorRef ref = connector.getNodeConnectorRef();
- final FlowCapableNodeConnectorUpdated flowConnector = connector
- .getAugmentation(FlowCapableNodeConnectorUpdated.class);
- final DataModificationTransaction it = this.manager.startChange();
- final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
- NodeConnectorId id = connector.getId();
- NodeConnectorKey nodeConnectorKey = new NodeConnectorKey(id);
- data.setKey(nodeConnectorKey);
- boolean notEquals = (!Objects.equal(flowConnector, null));
- if (notEquals) {
- final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
- data.addAugmentation(FlowCapableNodeConnector.class, augment);
- }
- InstanceIdentifier<? extends Object> value = ref.getValue();
- LOG.debug("updating node connector : {}.", value);
- NodeConnector build = data.build();
- it.putOperationalData((value), build);
- Future<RpcResult<TransactionStatus>> commitResult = it.commit();
- listenOnTransactionState(it.getIdentifier(), commitResult, "nodeConnector update", ref.getValue());
+ manager.enqueue(new InventoryOperation() {
+ @Override
+ public void applyOperation(final DataModificationTransaction tx) {
+ final NodeConnectorRef ref = connector.getNodeConnectorRef();
+ final NodeConnectorBuilder data = new NodeConnectorBuilder(connector);
+ data.setKey(new NodeConnectorKey(connector.getId()));
+
+ final FlowCapableNodeConnectorUpdated flowConnector = connector
+ .getAugmentation(FlowCapableNodeConnectorUpdated.class);
+ if (flowConnector != null) {
+ final FlowCapableNodeConnector augment = InventoryMapping.toInventoryAugment(flowConnector);
+ data.addAugmentation(FlowCapableNodeConnector.class, augment);
+ }
+ InstanceIdentifier<? extends Object> value = ref.getValue();
+ LOG.debug("updating node connector : {}.", value);
+ NodeConnector build = data.build();
+ tx.putOperationalData(value, build);
+ }
+ });
}
@Override
public synchronized void onNodeRemoved(final NodeRemoved node) {
-
- final NodeRef ref = node.getNodeRef();
- final DataModificationTransaction it = this.manager.startChange();
- LOG.debug("removing node : {}", ref.getValue());
- it.removeOperationalData((ref.getValue()));
- Future<RpcResult<TransactionStatus>> commitResult = it.commit();
- listenOnTransactionState(it.getIdentifier(), commitResult, "node removal", ref.getValue());
+ manager.enqueue(new InventoryOperation() {
+ @Override
+ public void applyOperation(final DataModificationTransaction tx) {
+ final NodeRef ref = node.getNodeRef();
+ LOG.debug("removing node : {}", ref.getValue());
+ tx.removeOperationalData((ref.getValue()));
+ }
+ });
}
@Override
public synchronized void onNodeUpdated(final NodeUpdated node) {
-
- final NodeRef ref = node.getNodeRef();
- final FlowCapableNodeUpdated flowNode = node
- .<FlowCapableNodeUpdated> getAugmentation(FlowCapableNodeUpdated.class);
- final DataModificationTransaction it = this.manager.startChange();
- final NodeBuilder nodeBuilder = new NodeBuilder(node);
- nodeBuilder.setKey(new NodeKey(node.getId()));
- boolean equals = Objects.equal(flowNode, null);
- if (equals) {
+ final FlowCapableNodeUpdated flowNode = node.getAugmentation(FlowCapableNodeUpdated.class);
+ if (flowNode == null) {
return;
}
- final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
- nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
- InstanceIdentifier<? extends Object> value = ref.getValue();
- InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) value).builder();
- InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder
- .<FlowCapableNode> augmentation(FlowCapableNode.class);
- final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
- LOG.debug("updating node :{} ", path);
- it.putOperationalData(path, augment);
-
- Future<RpcResult<TransactionStatus>> commitResult = it.commit();
- listenOnTransactionState(it.getIdentifier(), commitResult, "node update", ref.getValue());
- }
-
- /**
- * @param txId transaction identificator
- * @param future transaction result
- * @param action performed by transaction
- * @param nodeConnectorPath target value
- */
- private static void listenOnTransactionState(final Object txId, Future<RpcResult<TransactionStatus>> future,
- final String action, final InstanceIdentifier<?> nodeConnectorPath) {
- Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future),new FutureCallback<RpcResult<TransactionStatus>>() {
-
- @Override
- public void onFailure(Throwable t) {
- LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId, t);
-
- }
+ manager.enqueue(new InventoryOperation() {
@Override
- public void onSuccess(RpcResult<TransactionStatus> result) {
- if(!result.isSuccessful()) {
- LOG.error("Action {} [{}] failed for Tx:{}", action, nodeConnectorPath, txId);
- }
+ public void applyOperation(final DataModificationTransaction tx) {
+ final NodeRef ref = node.getNodeRef();
+ final NodeBuilder nodeBuilder = new NodeBuilder(node);
+ nodeBuilder.setKey(new NodeKey(node.getId()));
+
+ final FlowCapableNode augment = InventoryMapping.toInventoryAugment(flowNode);
+ nodeBuilder.addAugmentation(FlowCapableNode.class, augment);
+
+ @SuppressWarnings("unchecked")
+ InstanceIdentifierBuilder<Node> builder = ((InstanceIdentifier<Node>) ref.getValue()).builder();
+ InstanceIdentifierBuilder<FlowCapableNode> augmentation = builder.augmentation(FlowCapableNode.class);
+ final InstanceIdentifier<FlowCapableNode> path = augmentation.build();
+ LOG.debug("updating node :{} ", path);
+ tx.putOperationalData(path, augment);
}
});
}
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-public interface BindingDataBroker extends AsyncDataBroker<InstanceIdentifier<?>, DataObject, BindingDataChangeListener>{
+public interface BindingDataBroker extends AsyncDataBroker<InstanceIdentifier<?>, DataObject, BindingDataChangeListener>, BindingService {
@Override
BindingDataReadTransaction newReadOnlyTransaction();
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.sal.binding.api;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareService;
+
+/**
+ *
+ * Marker interface for MD-SAL services which are available for users of MD-SAL.
+ *
+ * BindingService is marker interface for infrastructure services provided by
+ * the SAL. These services may be session-specific, and wrapped by custom
+ * delegator patterns in order to introduce additional semantics / checks
+ * to the system.
+ *
+ * This interface extends {@link BindingAwareService}, order to be make
+ * new services available via
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext}
+ * and via
+ * {@link org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext}
+ *
+ */
+public interface BindingService extends BindingAwareService {
+
+}
org.opendaylight.controller.md.sal.binding.impl,
<!--org.opendaylight.controller.sal.binding.dom.*,-->
org.opendaylight.controller.sal.binding.osgi.*,
- org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.binding.impl.rev131028.*
</Private-Package>
</instructions>
</configuration>
--- /dev/null
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.Provider;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.osgi.framework.BundleContext;
+
+public class BindingAsyncDataBrokerImplModule extends
+ org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModule implements
+ Provider {
+ private BundleContext bundleContext;
+
+ public BindingAsyncDataBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public BindingAsyncDataBrokerImplModule(
+ final org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ final org.opendaylight.controller.config.yang.md.sal.binding.impl.BindingAsyncDataBrokerImplModule oldModule,
+ final java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ Broker domBroker = getDomAsyncBrokerDependency();
+ BindingIndependentMappingService mappingService = getBindingMappingServiceDependency();
+
+ // FIXME: Switch this to DOM Broker registration which would not require
+ // BundleContext when API are updated.
+ ProviderSession session = domBroker.registerProvider(this, getBundleContext());
+ DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+ SchemaService schemaService = session.getService(SchemaService.class);
+ return new ForwardedBindingDataBroker(domDataBroker, mappingService, schemaService);
+ }
+
+ // FIXME: Remove this when DOM Broker registration would not require
+ // BundleContext
+ @Deprecated
+ private BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ // FIXME: Remove this when DOM Broker registration would not require
+ // BundleContext
+ @Deprecated
+ void setBundleContext(final BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ @Override
+ public Collection<ProviderFunctionality> getProviderFunctionality() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public void onSessionInitiated(final ProviderSession arg0) {
+ // intentional NOOP
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: opendaylight-sal-binding-broker-impl yang module local name: binding-forwarded-data-broker
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri May 16 17:18:18 CEST 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.md.sal.binding.impl;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+public class BindingAsyncDataBrokerImplModuleFactory extends org.opendaylight.controller.config.yang.md.sal.binding.impl.AbstractBindingAsyncDataBrokerImplModuleFactory {
+
+
+
+
+ @Override
+ public BindingAsyncDataBrokerImplModule instantiateModule(final String instanceName,
+ final DependencyResolver dependencyResolver, final BindingAsyncDataBrokerImplModule oldModule,
+ final AutoCloseable oldInstance, final BundleContext bundleContext) {
+ BindingAsyncDataBrokerImplModule module = super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public BindingAsyncDataBrokerImplModule instantiateModule(final String instanceName,
+ final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+ // TODO Auto-generated method stub
+ BindingAsyncDataBrokerImplModule module = super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+}
\r
private BundleContext bundleContext;\r
\r
- public BindingBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {\r
+ public BindingBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {\r
super(identifier, dependencyResolver);\r
}\r
\r
- public BindingBrokerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
- org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,\r
- BindingBrokerImplModule oldModule, java.lang.AutoCloseable oldInstance) {\r
+ public BindingBrokerImplModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier,\r
+ final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,\r
+ final BindingBrokerImplModule oldModule, final java.lang.AutoCloseable oldInstance) {\r
super(identifier, dependencyResolver, oldModule, oldInstance);\r
}\r
\r
private RootBindingAwareBroker createStandaloneBroker() {\r
RootBindingAwareBroker broker = new RootBindingAwareBroker(getIdentifier().getInstanceName());\r
\r
- broker.setDataBroker(getDataBrokerDependency());\r
+ broker.setLegacyDataBroker(getDataBrokerDependency());\r
broker.setNotificationBroker(getNotificationServiceDependency());\r
broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));\r
+ // FIXME: Also set Async Data Broker\r
return broker;\r
}\r
\r
private RootBindingAwareBroker createForwardedBroker() {\r
DomForwardedBindingBrokerImpl broker = new DomForwardedBindingBrokerImpl(getIdentifier().getInstanceName());\r
\r
- broker.setDataBroker(getDataBrokerDependency());\r
+ broker.setLegacyDataBroker(getDataBrokerDependency());\r
broker.setNotificationBroker(getNotificationServiceDependency());\r
broker.setRpcBroker(new RpcProviderRegistryImpl(broker.getIdentifier()));\r
\r
broker.getMountManager().setDataCommitExecutor(SingletonHolder.getDefaultCommitExecutor());\r
broker.getMountManager().setNotificationExecutor(SingletonHolder.getDefaultNotificationExecutor());\r
\r
-\r
+ // FIXME: Also set Async Data Broker\r
DomForwardingUtils.reuseForwardingFrom(broker, broker.getDataBroker());\r
broker.startForwarding();\r
return broker;\r
return bundleContext;\r
}\r
\r
- public void setBundleContext(BundleContext bundleContext) {\r
+ public void setBundleContext(final BundleContext bundleContext) {\r
this.bundleContext = bundleContext;\r
}\r
}\r
Broker domBroker = getDomAsyncBrokerDependency();
ProviderSession session = domBroker.registerProvider(this, getBundleContext());
DOMDataBroker domDataBroker = session.getService(DOMDataBroker.class);
+ SchemaService schemaService = session.getService(SchemaService.class);
ForwardedBackwardsCompatibleDataBroker dataBroker = new ForwardedBackwardsCompatibleDataBroker(domDataBroker,
- mappingService, listeningExecutor);
-
- session.getService(SchemaService.class).registerSchemaServiceListener(dataBroker);
+ mappingService, schemaService,listeningExecutor);
dataBroker.setConnector(BindingDomConnectorDeployer.createConnector(getBindingMappingServiceDependency()));
dataBroker.setDomProviderContext(session);
import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentConnector;
import org.opendaylight.controller.sal.binding.impl.forward.DomForwardedBroker;
import org.opendaylight.controller.sal.core.api.Broker.ProviderSession;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
public abstract class AbstractForwardedDataBroker implements Delegator<DOMDataBroker>, DomForwardedBroker,
- SchemaContextListener {
+ SchemaContextListener, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(AbstractForwardedDataBroker.class);
// The Broker to whom we do all forwarding
private final BindingToNormalizedNodeCodec codec;
private BindingIndependentConnector connector;
private ProviderSession context;
+ private final ListenerRegistration<SchemaServiceListener> schemaListenerRegistration;
protected AbstractForwardedDataBroker(final DOMDataBroker domDataBroker,
- final BindingIndependentMappingService mappingService) {
+ final BindingIndependentMappingService mappingService,final SchemaService schemaService) {
this.domDataBroker = domDataBroker;
this.mappingService = mappingService;
this.codec = new BindingToNormalizedNodeCodec(mappingService);
+ this.schemaListenerRegistration = schemaService.registerSchemaServiceListener(this);
}
protected BindingToNormalizedNodeCodec getCodec() {
// NOOP
}
+ @Override
+ public void close() throws Exception {
+ this.schemaListenerRegistration.close();
+ }
+
}
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
private static final Logger LOG = LoggerFactory.getLogger(ForwardedBackwardsCompatibleDataBroker.class);
private final ConcurrentHashMap<InstanceIdentifier<?>, CommitHandlerRegistrationImpl> commitHandlers = new ConcurrentHashMap<>();
- private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
private final ListeningExecutorService executorService;
public ForwardedBackwardsCompatibleDataBroker(final DOMDataBroker domDataBroker,
- final BindingIndependentMappingService mappingService, final ListeningExecutorService executor) {
- super(domDataBroker, mappingService);
+ final BindingIndependentMappingService mappingService, final SchemaService schemaService,final ListeningExecutorService executor) {
+ super(domDataBroker, mappingService,schemaService);
executorService = executor;
LOG.info("ForwardedBackwardsCompatibleBroker started.");
}
throw new UnsupportedOperationException("Data reader contract is not supported.");
}
- @Override
- public void close() throws Exception {
- // TODO Auto-generated method stub
-
- }
-
public ListenableFuture<RpcResult<TransactionStatus>> commit(final ForwardedBackwardsCompatibleTransacion tx) {
final List<DataCommitTransaction<InstanceIdentifier<? extends DataObject>, DataObject>> subTrans = new ArrayList<>();
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
*/
public class ForwardedBindingDataBroker extends AbstractForwardedDataBroker implements BindingDataBroker {
- public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService) {
- super(domDataBroker, mappingService);
+ public ForwardedBindingDataBroker(final DOMDataBroker domDataBroker, final BindingIndependentMappingService mappingService, final SchemaService schemaService) {
+ super(domDataBroker, mappingService,schemaService);
}
@Override
import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils
import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
+import org.opendaylight.yangtools.yang.binding.RpcService
class RuntimeCodeGenerator extends AbstractRuntimeCodeGenerator {
val proxyName = iface.directProxyName;
val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(proxyName)
if(potentialClass != null) {
- return potentialClass.newInstance;
+ return potentialClass.newInstance as RpcService;
}
val supertype = iface.asCtClass
val createdCls = createClass(iface.directProxyName, supertype) [
'''
]
]
- return createdCls.toClass(iface.classLoader).newInstance
+ return createdCls.toClass(iface.classLoader).newInstance as RpcService
]
}
val routerName = iface.routerName;
val potentialClass = ClassLoaderUtils.tryToLoadClassWithTCCL(routerName)
if(potentialClass != null) {
- return potentialClass.newInstance;
+ return potentialClass.newInstance as RpcService;
}
val targetCls = createClass(iface.routerName, supertype) [
'''
]
]
- return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance
+ return targetCls.toClass(iface.classLoader,iface.protectionDomain).newInstance as RpcService
];
}
*/
package org.opendaylight.controller.sal.binding.impl;
-import com.google.common.collect.ImmutableClassToInstanceMap;
+import static com.google.common.base.Preconditions.checkState;
+
+import org.opendaylight.controller.md.sal.binding.api.BindingDataBroker;
import org.opendaylight.controller.md.sal.binding.util.AbstractBindingSalProviderInstance;
import org.opendaylight.controller.md.sal.binding.util.BindingContextUtils;
import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.collect.ImmutableClassToInstanceMap;
public class RootBindingAwareBroker implements //
Mutable, //
Identifiable<String>, //
- BindingAwareBroker, AutoCloseable,
- RpcProviderRegistry {
+ BindingAwareBroker, AutoCloseable, RpcProviderRegistry {
private final static Logger LOG = LoggerFactory.getLogger(RootBindingAwareBroker.class);
private NotificationProviderService notificationBroker;
- private DataProviderService dataBroker;
+ private DataProviderService legacyDataBroker;
+
+ private BindingDataBroker dataBroker;
private MountPointManagerImpl mountManager;
return mountManager;
}
- public void setMountManager(MountPointManagerImpl mountManager) {
+ public void setMountManager(final MountPointManagerImpl mountManager) {
this.mountManager = mountManager;
}
private ImmutableClassToInstanceMap<BindingAwareService> supportedProviderServices;
- public RootBindingAwareBroker(String instanceName) {
+ public RootBindingAwareBroker(final String instanceName) {
this.identifier = instanceName;
mountManager = new MountPointManagerImpl();
}
+ @Override
public String getIdentifier() {
return identifier;
}
}
public DataProviderService getDataBroker() {
- return this.dataBroker;
+ return this.legacyDataBroker;
}
public NotificationProviderService getNotificationBroker() {
return rpcBroker;
}
- public void setRpcBroker(RpcProviderRegistry rpcBroker) {
+ public void setRpcBroker(final RpcProviderRegistry rpcBroker) {
this.rpcBroker = rpcBroker;
}
- public void setNotificationBroker(NotificationProviderService notificationBroker) {
+ public void setNotificationBroker(final NotificationProviderService notificationBroker) {
this.notificationBroker = notificationBroker;
}
- public void setDataBroker(DataProviderService dataBroker) {
- this.dataBroker = dataBroker;
+ public void setLegacyDataBroker(final DataProviderService dataBroker) {
+ this.legacyDataBroker = dataBroker;
}
public void start() {
controllerRoot = new RootSalInstance(getRpcProviderRegistry(), getNotificationBroker(), getDataBroker());
+ ImmutableClassToInstanceMap.Builder<BindingAwareService> consBuilder = ImmutableClassToInstanceMap.builder();
- supportedConsumerServices = ImmutableClassToInstanceMap.<BindingAwareService> builder()
- .put(NotificationService.class, getRoot()) //
- .put(DataBrokerService.class, getRoot()) //
- .put(RpcConsumerRegistry.class, getRoot()) //
- .put(MountService.class, mountManager).build();
-
+ consBuilder.put(NotificationService.class, getRoot());
+ consBuilder.put(DataBrokerService.class, getRoot());
+ consBuilder.put(RpcConsumerRegistry.class, getRoot());
+ if(dataBroker != null) {
+ consBuilder.put(BindingDataBroker.class, dataBroker);
+ }
+ consBuilder.put(MountService.class, mountManager).build();
+ supportedConsumerServices = consBuilder.build();
supportedProviderServices = ImmutableClassToInstanceMap.<BindingAwareService> builder()
- .putAll(supportedConsumerServices)
- .put(NotificationProviderService.class, getRoot()) //
- .put(DataProviderService.class, getRoot()) //
- .put(RpcProviderRegistry.class, getRoot()) //
+ .putAll(supportedConsumerServices).put(NotificationProviderService.class, getRoot())
+ .put(DataProviderService.class, getRoot()).put(RpcProviderRegistry.class, getRoot())
.put(MountProviderService.class, mountManager).build();
}
@Override
- public ConsumerContext registerConsumer(BindingAwareConsumer consumer, BundleContext ctx) {
+ public ConsumerContext registerConsumer(final BindingAwareConsumer consumer, final BundleContext ctx) {
checkState(supportedConsumerServices != null, "Broker is not initialized.");
return BindingContextUtils.createConsumerContextAndInitialize(consumer, supportedConsumerServices);
}
@Override
- public ProviderContext registerProvider(BindingAwareProvider provider, BundleContext ctx) {
+ public ProviderContext registerProvider(final BindingAwareProvider provider, final BundleContext ctx) {
checkState(supportedProviderServices != null, "Broker is not initialized.");
return BindingContextUtils.createProviderContextAndInitialize(provider, supportedProviderServices);
}
}
@Override
- public <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(Class<T> type, T implementation)
- throws IllegalStateException {
+ public <T extends RpcService> RoutedRpcRegistration<T> addRoutedRpcImplementation(final Class<T> type,
+ final T implementation) throws IllegalStateException {
return getRoot().addRoutedRpcImplementation(type, implementation);
}
@Override
- public <T extends RpcService> RpcRegistration<T> addRpcImplementation(Class<T> type, T implementation)
+ public <T extends RpcService> RpcRegistration<T> addRpcImplementation(final Class<T> type, final T implementation)
throws IllegalStateException {
return getRoot().addRpcImplementation(type, implementation);
}
@Override
- public <T extends RpcService> T getRpcService(Class<T> module) {
+ public <T extends RpcService> T getRpcService(final Class<T> module) {
return getRoot().getRpcService(module);
}
+
@Override
public <L extends RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> ListenerRegistration<L> registerRouteChangeListener(
- L arg0) {
+ final L arg0) {
return getRoot().registerRouteChangeListener(arg0);
}
-
public class RootSalInstance extends
AbstractBindingSalProviderInstance<DataProviderService, NotificationProviderService, RpcProviderRegistry> {
- public RootSalInstance(RpcProviderRegistry rpcRegistry, NotificationProviderService notificationBroker,
- DataProviderService dataBroker) {
+ public RootSalInstance(final RpcProviderRegistry rpcRegistry,
+ final NotificationProviderService notificationBroker, final DataProviderService dataBroker) {
super(rpcRegistry, notificationBroker, dataBroker);
}
}
+
+ public void setDataBroker(final BindingDataBroker asyncDataBroker) {
+ dataBroker = asyncDataBroker;
+ }
}
config:provided-service sal:binding-data-consumer-broker;
config:java-name-prefix ForwardedCompatibleDataBrokerImpl;
}
+
+ identity binding-forwarded-data-broker {
+ base config:module-type;
+ config:provided-service sal:binding-async-data-broker;
+ config:java-name-prefix BindingAsyncDataBrokerImpl;
+ }
identity binding-rpc-broker {
base config:module-type;
config:java-name-prefix RuntimeMapping;
}
+ grouping dom-forwarding-component {
+ container dom-async-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+
+ container binding-mapping-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity binding-dom-mapping-service;
+ }
+ }
+ }
+ }
+
augment "/config:modules/config:module/config:configuration" {
case binding-broker-impl {
when "/config:modules/config:module/config:type = 'binding-broker-impl'";
case binding-data-compatible-broker {
when "/config:modules/config:module/config:type = 'binding-data-compatible-broker'";
- container dom-async-broker {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity dom:dom-broker-osgi-registry;
- }
- }
- }
-
- container binding-mapping-service {
- uses config:service-ref {
- refine type {
- mandatory true;
- config:required-identity binding-dom-mapping-service;
- }
- }
+ uses dom-forwarding-component;
+ }
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case binding-forwarded-data-broker {
+ when "/config:modules/config:module/config:type = 'binding-forwarded-data-broker'";
+ container binding-forwarded-data-broker {
+ uses dom-forwarding-component;
}
}
}
import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareDataStoreAdapter;
import org.opendaylight.controller.sal.dom.broker.impl.SchemaAwareRpcBroker;
-import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
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.parser.impl.YangParserImpl;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ListeningExecutorService;
-public class BindingTestContext implements AutoCloseable, SchemaContextProvider {
+public class BindingTestContext implements AutoCloseable {
public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier TREE_ROOT = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
.builder().toInstance();
private MountPointManagerImpl biMountImpl;
- private SchemaContext schemaContext;
+
private ImmutableMap<LogicalDatastoreType, DOMStore> newDatastores;
private BackwardsCompatibleDataBroker biCompatibleBroker;
- private final List<SchemaContextListener> schemaListeners = new ArrayList<>();
-
private DataProviderService baData;
private DOMDataBroker newDOMDataBroker;
- @Override
- public SchemaContext getSchemaContext() {
- return schemaContext;
- }
+ private final MockSchemaService mockSchemaService = new MockSchemaService();
+
+
public DOMDataBroker getDomAsyncDataBroker() {
return newDOMDataBroker;
this.startWithSchema = startWithSchema;
}
+ @Deprecated
public void startDomDataStore() {
checkState(dataStore == null, "DataStore already started.");
checkState(biDataImpl != null, "Dom Data Broker not present");
} else {
dataStore = schemaAwareDataStore;
}
-
+ mockSchemaService.registerSchemaServiceListener(schemaAwareDataStore);
biDataImpl.registerConfigurationReader(TREE_ROOT, dataStore);
biDataImpl.registerOperationalReader(TREE_ROOT, dataStore);
biDataImpl.registerCommitHandler(TREE_ROOT, dataStore);
biCompatibleBroker = new BackwardsCompatibleDataBroker(newDOMDataBroker);
- schemaListeners.add(configStore);
- schemaListeners.add(operStore);
- schemaListeners.add(biCompatibleBroker);
+ mockSchemaService.registerSchemaServiceListener(configStore);
+ mockSchemaService.registerSchemaServiceListener(operStore);
+ mockSchemaService.registerSchemaServiceListener(biCompatibleBroker);
biDataLegacyBroker = biCompatibleBroker;
}
baBrokerImpl.getMountManager().setDataCommitExecutor(executor);
baBrokerImpl.getMountManager().setNotificationExecutor(executor);
baBrokerImpl.setRpcBroker(new RpcProviderRegistryImpl("test"));
- baBrokerImpl.setDataBroker(baData);
+ baBrokerImpl.setLegacyDataBroker(baData);
baBrokerImpl.setNotificationBroker(baNotifyImpl);
baBrokerImpl.start();
}
public void startBindingToDomMappingService() {
checkState(classPool != null, "ClassPool needs to be present");
mappingServiceImpl = new RuntimeGeneratedMappingServiceImpl(classPool);
+ mockSchemaService.registerSchemaServiceListener(mappingServiceImpl);
}
public void updateYangSchema(final String[] files) {
- schemaContext = getContext(files);
-
- if (schemaAwareDataStore != null) {
- schemaAwareDataStore.onGlobalContextUpdated(schemaContext);
- }
- if (mappingServiceImpl != null) {
- mappingServiceImpl.onGlobalContextUpdated(schemaContext);
- }
- for(SchemaContextListener listener : schemaListeners) {
- listener.onGlobalContextUpdated(schemaContext);
- }
+ mockSchemaService.changeSchema(getContext(files));
}
public static String[] getAllYangFilesOnClasspath() {
}
public void startNewBindingDataBroker() {
- ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl, executor);
- schemaListeners.add(forwarded);
+ ForwardedBackwardsCompatibleDataBroker forwarded = new ForwardedBackwardsCompatibleDataBroker(newDOMDataBroker, mappingServiceImpl,mockSchemaService, executor);
baData = forwarded;
}
private void startDomBroker() {
checkState(executor != null);
biBrokerImpl = new BrokerImpl();
- biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
+ biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", mockSchemaService));
}
public MountProvisionService getDomMountProviderService() {
return biMountImpl;
}
+
+
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.sal.binding.test.util;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.dom.broker.impl.SchemaContextProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
+
+@SuppressWarnings("deprecation")
+public final class MockSchemaService implements SchemaService, SchemaContextProvider {
+
+ private SchemaContext schemaContext;
+
+ ListenerRegistry<SchemaServiceListener> listeners = ListenerRegistry.create();
+
+ @Override
+ public void addModule(final Module module) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized SchemaContext getGlobalContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public synchronized SchemaContext getSessionContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(
+ final SchemaServiceListener listener) {
+ return listeners.register(listener);
+ }
+
+ @Override
+ public void removeModule(final Module module) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public synchronized SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ public synchronized void changeSchema(final SchemaContext newContext) {
+ schemaContext = newContext;
+ for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+ listener.getInstance().onGlobalContextUpdated(schemaContext);
+ }
+ }
+}
\ No newline at end of file
base "config:service-type";
config:java-class "org.opendaylight.controller.sal.binding.api.data.DataProviderService";
}
+
+ identity binding-async-data-broker {
+ base "config:service-type";
+ config:java-class "org.opendaylight.controller.md.sal.binding.api.BindingDataBroker";
+ }
identity binding-data-consumer-broker {
base "config:service-type";
<artifactId>akka-remote_${scala.version}</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-testkit_${scala.version}</artifactId>
+ </dependency>
+
<!-- SAL Dependencies -->
<dependency>
<artifactId>sal-binding-config</artifactId>
</dependency>
+ <!--
+ Adding a temporary dependency on the sal-broker-impl so that we can use InMemoryDOMDataStore
+
+ InMemoryDOMDataStore needs to be moved into its own module and be wired up using config subsystem before
+ this bundle can use it
+ -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal-common-api</artifactId>
<artifactId>org.osgi.core</artifactId>
</dependency>
- <!-- AKKA Dependencies -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.datastore.messages.CloseListenerRegistration;
+import org.opendaylight.controller.cluster.datastore.messages.CloseListenerRegistrationReply;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class ListenerRegistration extends UntypedActor{
+
+ private final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration;
+
+ public ListenerRegistration(org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration) {
+ this.registration = registration;
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ if(message instanceof CloseListenerRegistration){
+ closeListenerRegistration((CloseListenerRegistration) message);
+ }
+ }
+
+ public static Props props(final org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration){
+ return Props.create(new Creator<ListenerRegistration>(){
+
+ @Override
+ public ListenerRegistration create() throws Exception {
+ return new ListenerRegistration(registration);
+ }
+ });
+ }
+
+ private void closeListenerRegistration(CloseListenerRegistration message){
+ registration.close();
+ getSender().tell(new CloseListenerRegistrationReply(), getSelf());
+ }
+}
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.persistence.UntypedProcessor;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.concurrent.Executors;
+
+/**
+ * A Shard represents a portion of the logical data tree
+ * <p/>
+ * Our Shard uses InMemoryDataStore as it's internal representation and delegates all requests it
+ *
+ */
+public class Shard extends UntypedProcessor {
+
+ ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(2));
+
+ private final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+ LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ if (message instanceof CreateTransactionChain) {
+ createTransactionChain();
+ } else if(message instanceof RegisterChangeListener){
+ registerChangeListener((RegisterChangeListener) message);
+ } else if(message instanceof UpdateSchemaContext){
+ updateSchemaContext((UpdateSchemaContext) message);
+ }
+ }
+
+ private void updateSchemaContext(UpdateSchemaContext message) {
+ store.onGlobalContextUpdated(message.getSchemaContext());
+ }
+
+ private void registerChangeListener(RegisterChangeListener registerChangeListener) {
+ org.opendaylight.yangtools.concepts.ListenerRegistration<AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> registration =
+ store.registerChangeListener(registerChangeListener.getPath(), registerChangeListener.getListener(), registerChangeListener.getScope());
+ ActorRef listenerRegistration = getContext().actorOf(ListenerRegistration.props(registration));
+ getSender().tell(new RegisterChangeListenerReply(listenerRegistration.path()), getSelf());
+ }
+
+ private void createTransactionChain() {
+ DOMStoreTransactionChain chain = store.createTransactionChain();
+ ActorRef transactionChain = getContext().actorOf(ShardTransactionChain.props(chain));
+ getSender().tell(new CreateTransactionChainReply(transactionChain.path()), getSelf());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.Address;
+import akka.actor.UntypedActor;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The ShardManager has the following jobs,
+ *
+ * - Create all the local shard replicas that belong on this cluster member
+ * - Find the primary replica for any given shard
+ * - Engage in shard replica elections which decide which replica should be the primary
+ *
+ * Creation of Shard replicas
+ * ==========================
+ * When the ShardManager is constructed it reads the cluster configuration to find out which shard replicas
+ * belong on this member. It finds out the name of the current cluster member from the Akka Clustering Service.
+ *
+ * Replica Elections
+ * =================
+ * The Shard Manager uses multiple cues to initiate election.
+ * - When a member of the cluster dies
+ * - When a local shard replica dies
+ * - When a local shard replica comes alive
+ */
+public class ShardManager extends UntypedActor {
+
+ // Stores a mapping between a shard name and the address of the current primary
+ private final Map<String, Address> shardNameToPrimaryAddress = new HashMap<>();
+
+ // Stores a mapping between a member name and the address of the member
+ private final Map<String, Address> memberNameToAddress = new HashMap<>();
+
+ // Stores a mapping between the shard name and all the members on which a replica of that shard are available
+ private final Map<String, List<String>> shardNameToMembers = new HashMap<>();
+
+ LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ if(message instanceof FindPrimary ){
+ FindPrimary msg = ((FindPrimary) message);
+ getSender().tell(new PrimaryNotFound(msg.getShardName()), getSelf());
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.event.Logging;
+import akka.event.LoggingAdapter;
+import akka.japi.Creator;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * The ShardTransaction Actor represents a remote transaction
+ *
+ * The ShardTransaction Actor delegates all actions to DOMDataReadWriteTransaction
+ *
+ * Even though the DOMStore and the DOMStoreTransactionChain implement multiple types of transactions
+ * the ShardTransaction Actor only works with read-write transactions. This is just to keep the logic simple. At this
+ * time there are no known advantages for creating a read-only or write-only transaction which may change over time
+ * at which point we can optimize things in the distributed store as well.
+ *
+ * Handles Messages
+ * ----------------
+ * {@link org.opendaylight.controller.cluster.datastore.messages.ReadData}
+ * {@link org.opendaylight.controller.cluster.datastore.messages.WriteData}
+ * {@link org.opendaylight.controller.cluster.datastore.messages.MergeData}
+ * {@link org.opendaylight.controller.cluster.datastore.messages.DeleteData}
+ * {@link org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction}
+ * {@link org.opendaylight.controller.cluster.datastore.messages.CloseTransaction}
+ */
+public class ShardTransaction extends UntypedActor {
+
+ private final DOMStoreReadWriteTransaction transaction;
+
+ private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
+
+ public ShardTransaction(DOMStoreReadWriteTransaction transaction) {
+ this.transaction = transaction;
+ }
+
+
+ public static Props props(final DOMStoreReadWriteTransaction transaction){
+ return Props.create(new Creator<ShardTransaction>(){
+
+ @Override
+ public ShardTransaction create() throws Exception {
+ return new ShardTransaction(transaction);
+ }
+ });
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ if(message instanceof ReadData){
+ readData((ReadData) message);
+ } else if(message instanceof WriteData){
+ writeData((WriteData) message);
+ } else if(message instanceof MergeData){
+ mergeData((MergeData) message);
+ } else if(message instanceof DeleteData){
+ deleteData((DeleteData) message);
+ } else if(message instanceof ReadyTransaction){
+ readyTransaction((ReadyTransaction) message);
+ } else if(message instanceof CloseTransaction){
+ closeTransaction((CloseTransaction) message);
+ }
+ }
+
+ private void readData(ReadData message) {
+ final ActorRef sender = getSender();
+ final ActorRef self = getSelf();
+ final InstanceIdentifier path = message.getPath();
+ final ListenableFuture<Optional<NormalizedNode<?, ?>>> future = transaction.read(path);
+
+ future.addListener(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Optional<NormalizedNode<?, ?>> optional = future.get();
+ if(optional.isPresent()){
+ sender.tell(new ReadDataReply(optional.get()), self);
+ } else {
+ //TODO : Need to decide what to do here
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ log.error(e, "An exception happened when reading data from path : " + path.toString());
+ }
+
+ }
+ }, getContext().dispatcher());
+ }
+
+
+ private void writeData(WriteData message){
+ transaction.write(message.getPath(), message.getData());
+ getSender().tell(new WriteDataReply(), getSelf());
+ }
+
+ private void mergeData(MergeData message){
+ transaction.merge(message.getPath(), message.getData());
+ getSender().tell(new MergeDataReply(), getSelf());
+ }
+
+ private void deleteData(DeleteData message){
+ transaction.delete(message.getPath());
+ getSender().tell(new DeleteDataReply(), getSelf());
+ }
+
+ private void readyTransaction(ReadyTransaction message){
+ DOMStoreThreePhaseCommitCohort cohort = transaction.ready();
+ ActorRef cohortActor = getContext().actorOf(ThreePhaseCommitCohort.props(cohort));
+ getSender().tell(new ReadyTransactionReply(cohortActor.path()), getSelf());
+
+ }
+
+ private void closeTransaction(CloseTransaction message){
+ transaction.close();
+ getSender().tell(new CloseTransactionReply(), getSelf());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
+
+/**
+ * The ShardTransactionChain Actor represents a remote TransactionChain
+ */
+public class ShardTransactionChain extends UntypedActor{
+
+ private final DOMStoreTransactionChain chain;
+
+ public ShardTransactionChain(DOMStoreTransactionChain chain) {
+ this.chain = chain;
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ if(message instanceof CreateTransaction){
+ DOMStoreReadWriteTransaction transaction = chain.newReadWriteTransaction();
+ ActorRef transactionActor = getContext().actorOf(ShardTransaction.props(transaction));
+ getSender().tell(new CreateTransactionReply(transactionActor.path()), getSelf());
+ } else if (message instanceof CloseTransactionChain){
+ chain.close();
+ getSender().tell(new CloseTransactionChainReply(), getSelf());
+ }
+ }
+
+ public static Props props(final DOMStoreTransactionChain chain){
+ return Props.create(new Creator<ShardTransactionChain>(){
+
+ @Override
+ public ShardTransactionChain create() throws Exception {
+ return new ShardTransactionChain(chain);
+ }
+ });
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.Props;
+import akka.actor.UntypedActor;
+import akka.japi.Creator;
+import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
+
+public class ThreePhaseCommitCohort extends UntypedActor{
+ private final DOMStoreThreePhaseCommitCohort cohort;
+
+ public ThreePhaseCommitCohort(DOMStoreThreePhaseCommitCohort cohort) {
+
+ this.cohort = cohort;
+ }
+
+ @Override
+ public void onReceive(Object message) throws Exception {
+ throw new UnsupportedOperationException("onReceive");
+ }
+
+ public static Props props(final DOMStoreThreePhaseCommitCohort cohort) {
+ return Props.create(new Creator<ThreePhaseCommitCohort>(){
+ @Override
+ public ThreePhaseCommitCohort create() throws Exception {
+ return new ThreePhaseCommitCohort(cohort);
+ }
+ });
+ }
+}
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
import com.google.common.base.Optional;
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseListenerRegistration {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseListenerRegistrationReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseTransaction {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseTransactionChain {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseTransactionChainReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CloseTransactionReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CreateTransaction {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class CreateTransactionChain {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class CreateTransactionChainReply {
+ private final ActorPath transactionChainPath;
+
+ public CreateTransactionChainReply(ActorPath transactionChainPath) {
+ this.transactionChainPath = transactionChainPath;
+ }
+
+ public ActorPath getTransactionChainPath() {
+ return transactionChainPath;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class CreateTransactionReply {
+ private final ActorPath transactionPath;
+
+ public CreateTransactionReply(ActorPath transactionPath) {
+ this.transactionPath = transactionPath;
+ }
+
+ public ActorPath getTransactionPath() {
+ return transactionPath;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class DeleteData {
+ private final InstanceIdentifier path;
+
+ public DeleteData(InstanceIdentifier path) {
+ this.path = path;
+ }
+
+ public InstanceIdentifier getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class DeleteDataReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * The FindPrimary message is used to locate the primary of any given shard
+ *
+ * TODO : Make this serializable
+ */
+public class FindPrimary{
+ private final String shardName;
+
+ public FindPrimary(String shardName){
+
+ Preconditions.checkNotNull(shardName, "shardName should not be null");
+
+ this.shardName = shardName;
+ }
+
+ public String getShardName() {
+ return shardName;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class MergeData extends ModifyData {
+ public MergeData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+ super(path, data);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class MergeDataReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public abstract class ModifyData {
+ private final InstanceIdentifier path;
+ private final NormalizedNode<?,?> data;
+
+ public ModifyData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+ this.path = path;
+ this.data = data;
+ }
+
+ public InstanceIdentifier getPath() {
+ return path;
+ }
+
+ public NormalizedNode<?, ?> getData() {
+ return data;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class PrimaryFound {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import com.google.common.base.Preconditions;
+
+public class PrimaryNotFound {
+
+ private final String shardName;
+
+ public PrimaryNotFound(String shardName){
+
+ Preconditions.checkNotNull(shardName, "shardName should not be null");
+
+ this.shardName = shardName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PrimaryNotFound that = (PrimaryNotFound) o;
+
+ if (shardName != null ? !shardName.equals(that.shardName) : that.shardName != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return shardName != null ? shardName.hashCode() : 0;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+public class ReadData {
+ private final InstanceIdentifier path;
+
+ public ReadData(InstanceIdentifier path) {
+ this.path = path;
+ }
+
+ public InstanceIdentifier getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class ReadDataReply {
+ private final NormalizedNode<?, ?> normalizedNode;
+
+ public ReadDataReply(NormalizedNode<?, ?> normalizedNode){
+
+ this.normalizedNode = normalizedNode;
+ }
+
+ public NormalizedNode<?, ?> getNormalizedNode() {
+ return normalizedNode;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class ReadyTransaction {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class ReadyTransactionReply {
+ private final ActorPath path;
+
+ public ReadyTransactionReply(ActorPath path) {
+
+ this.path = path;
+ }
+
+ public ActorPath getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class RegisterChangeListener {
+ private final InstanceIdentifier path;
+ private final AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener;
+ private final AsyncDataBroker.DataChangeScope scope;
+
+
+ public RegisterChangeListener(InstanceIdentifier path, AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> listener, AsyncDataBroker.DataChangeScope scope) {
+ this.path = path;
+ this.listener = listener;
+ this.scope = scope;
+ }
+
+ public InstanceIdentifier getPath() {
+ return path;
+ }
+
+ public AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> getListener() {
+ return listener;
+ }
+
+ public AsyncDataBroker.DataChangeScope getScope() {
+ return scope;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import akka.actor.ActorPath;
+
+public class RegisterChangeListenerReply {
+ private final ActorPath listenerRegistrationPath;
+
+ public RegisterChangeListenerReply(ActorPath listenerRegistrationPath) {
+ this.listenerRegistrationPath = listenerRegistrationPath;
+ }
+
+ public ActorPath getListenerRegistrationPath() {
+ return listenerRegistrationPath;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class UpdateSchemaContext {
+ private final SchemaContext schemaContext;
+
+ public UpdateSchemaContext(SchemaContext schemaContext) {
+ this.schemaContext = schemaContext;
+ }
+
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class WriteData extends ModifyData{
+
+ public WriteData(InstanceIdentifier path, NormalizedNode<?, ?> data) {
+ super(path, data);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.messages;
+
+public class WriteDataReply {
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.shardstrategy;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+/**
+ * The DefaultShardStrategy basically puts all data into the default Shard
+ * <p>
+ * The default shard stores data for all modules for which a specific set of shards has not been configured
+ * </p>
+ */
+public class DefaultShardStrategy implements ShardStrategy{
+
+ public static final String NAME = "default";
+ public static final String DEFAULT_SHARD = "default";
+
+ @Override
+ public String findShard(InstanceIdentifier path) {
+ return DEFAULT_SHARD;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.shardstrategy;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+/**
+ * The role of ShardStrategy is to figure out which Shards a given piece of data belongs to
+ */
+public interface ShardStrategy {
+ /**
+ * Find the name of the shard in which the data pointed to by the specified path belongs in
+ *
+ * @param path The location of the data in the logical tree
+ * @return
+ */
+ String findShard(InstanceIdentifier path);
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore.shardstrategy;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ShardStrategyFactory {
+ private static final Map<String, ShardStrategy> moduleNameToStrategyMap = new ConcurrentHashMap();
+
+ private static final String UNKNOWN_MODULE_NAME = "unknown";
+
+ public static ShardStrategy getStrategy(InstanceIdentifier path){
+ Preconditions.checkNotNull(path, "path should not be null");
+
+ String moduleName = getModuleName(path);
+ ShardStrategy shardStrategy = moduleNameToStrategyMap.get(moduleName);
+ if(shardStrategy == null){
+ return new DefaultShardStrategy();
+ }
+
+ return shardStrategy;
+ }
+
+
+ private static String getModuleName(InstanceIdentifier path){
+ return UNKNOWN_MODULE_NAME;
+ }
+
+ /**
+ * This is to be used in the future to register a custom shard strategy
+ *
+ * @param moduleName
+ * @param shardStrategy
+ */
+ public static void registerShardStrategy(String moduleName, ShardStrategy shardStrategy){
+ throw new UnsupportedOperationException("registering a custom shard strategy not supported yet");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.cluster.datastore;
+
+import akka.actor.ActorSystem;
+import akka.testkit.JavaTestKit;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+public abstract class AbstractActorTest {
+ private static ActorSystem system;
+
+ @BeforeClass
+ public static void setUp(){
+ system = ActorSystem.create("test");
+ }
+
+ @AfterClass
+ public static void tearDown(){
+ JavaTestKit.shutdownActorSystem(system);
+ system = null;
+ }
+
+ protected ActorSystem getSystem(){
+ return system;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseListenerRegistration;
+import org.opendaylight.controller.cluster.datastore.messages.CloseListenerRegistrationReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import static org.junit.Assert.assertEquals;
+
+public class ListenerRegistrationTest extends AbstractActorTest {
+ private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+ private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+ static {
+ store.onGlobalContextUpdated(TestModel.createTestContext());
+ }
+
+
+ @Test
+ public void testOnReceiveCloseListenerRegistration() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ListenerRegistration.props(store.registerChangeListener(TestModel.TEST_PATH, noOpDataChangeListener(), AsyncDataBroker.DataChangeScope.BASE));
+ final ActorRef subject = getSystem().actorOf(props, "testCloseListenerRegistration");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new CloseListenerRegistration(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof CloseListenerRegistrationReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ private AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> noOpDataChangeListener(){
+ return new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
+ @Override
+ public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+
+ }
+ };
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.FindPrimary;
+import org.opendaylight.controller.cluster.datastore.messages.PrimaryNotFound;
+import scala.concurrent.duration.Duration;
+
+public class ShardManagerTest {
+ private static ActorSystem system;
+
+ @BeforeClass
+ public static void setUp(){
+ system = ActorSystem.create("test");
+ }
+
+ @AfterClass
+ public static void tearDown(){
+ JavaTestKit.shutdownActorSystem(system);
+ system = null;
+ }
+
+ @Test
+ public void testOnReceiveFindPrimary() throws Exception {
+
+ new JavaTestKit(system) {{
+ final Props props = Props.create(ShardManager.class);
+ final TestActorRef<ShardManager> subject = TestActorRef.create(system, props, "test");
+
+ // can also use JavaTestKit “from the outside”
+ final JavaTestKit probe = new JavaTestKit(system);
+
+ // the run() method needs to finish within 3 seconds
+ new Within(duration("3 seconds")) {
+ protected void run() {
+
+ subject.tell(new FindPrimary("inventory"), getRef());
+
+ expectMsgEquals(Duration.Zero(), new PrimaryNotFound("inventory"));
+
+ // Will wait for the rest of the 3 seconds
+ expectNoMsg();
+ }
+ };
+ }};
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListener;
+import org.opendaylight.controller.cluster.datastore.messages.RegisterChangeListenerReply;
+import org.opendaylight.controller.cluster.datastore.messages.UpdateSchemaContext;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import static org.junit.Assert.assertTrue;
+
+public class ShardTest extends AbstractActorTest{
+ @Test
+ public void testOnReceiveCreateTransactionChain() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = Props.create(Shard.class);
+ final ActorRef subject = getSystem().actorOf(props, "testCreateTransactionChain");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new CreateTransactionChain(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof CreateTransactionChainReply) {
+ CreateTransactionChainReply reply = (CreateTransactionChainReply) in;
+ return reply.getTransactionChainPath().toString();
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransactionChain\\/\\$.*"));
+ // Will wait for the rest of the 3 seconds
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ @Test
+ public void testOnReceiveRegisterListener() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = Props.create(Shard.class);
+ final ActorRef subject = getSystem().actorOf(props, "testRegisterChangeListener");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new UpdateSchemaContext(TestModel.createTestContext()), getRef());
+
+ subject.tell(new RegisterChangeListener(InstanceIdentifier.builder().build(), noOpDataChangeListener() , AsyncDataBroker.DataChangeScope.BASE), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof RegisterChangeListenerReply) {
+ RegisterChangeListenerReply reply = (RegisterChangeListenerReply) in;
+ return reply.getListenerRegistrationPath().toString();
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertTrue(out.matches("akka:\\/\\/test\\/user\\/testRegisterChangeListener\\/\\$.*"));
+ // Will wait for the rest of the 3 seconds
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ private AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>> noOpDataChangeListener(){
+ return new AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>() {
+ @Override
+ public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change) {
+
+ }
+ };
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChainReply;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ShardTransactionChainTest extends AbstractActorTest {
+
+ private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+ private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+ static {
+ store.onGlobalContextUpdated(TestModel.createTestContext());
+ }
+ @Test
+ public void testOnReceiveCreateTransaction() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransactionChain.props(store.createTransactionChain());
+ final ActorRef subject = getSystem().actorOf(props, "testCreateTransaction");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new CreateTransaction(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof CreateTransactionReply) {
+ return ((CreateTransactionReply) in).getTransactionPath().toString();
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertTrue(out.matches("akka:\\/\\/test\\/user\\/testCreateTransaction\\/\\$.*"));
+ // Will wait for the rest of the 3 seconds
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ @Test
+ public void testOnReceiveCloseTransactionChain() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransactionChain.props(store.createTransactionChain());
+ final ActorRef subject = getSystem().actorOf(props, "testCloseTransactionChain");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new CloseTransactionChain(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof CloseTransactionChainReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+ // Will wait for the rest of the 3 seconds
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore;
+
+import akka.actor.ActorRef;
+import akka.actor.Props;
+import akka.testkit.JavaTestKit;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
+import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.MergeData;
+import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadData;
+import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.WriteData;
+import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+import static org.junit.Assert.assertEquals;
+
+public class ShardTransactionTest extends AbstractActorTest {
+ private static ListeningExecutorService storeExecutor = MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
+
+ private static final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", storeExecutor);
+
+ static {
+ store.onGlobalContextUpdated(TestModel.createTestContext());
+ }
+
+ @Test
+ public void testOnReceiveReadData() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testReadData");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new ReadData(InstanceIdentifier.builder().build()), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof ReadDataReply) {
+ if (((ReadDataReply) in).getNormalizedNode() != null) {
+ return "match";
+ }
+ return null;
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ @Test
+ public void testOnReceiveWriteData() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testWriteData");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new WriteData(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof WriteDataReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ @Test
+ public void testOnReceiveMergeData() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testMergeData");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new MergeData(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME)), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof MergeDataReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+ @Test
+ public void testOnReceiveDeleteData() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testDeleteData");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new DeleteData(TestModel.TEST_PATH), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof DeleteDataReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+ }
+
+
+ @Test
+ public void testOnReceiveReadyTransaction() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testReadyTransaction");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new ReadyTransaction(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof ReadyTransactionReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+
+ }
+
+ @Test
+ public void testOnReceiveCloseTransaction() throws Exception {
+ new JavaTestKit(getSystem()) {{
+ final Props props = ShardTransaction.props(store.newReadWriteTransaction());
+ final ActorRef subject = getSystem().actorOf(props, "testCloseTransaction");
+
+ new Within(duration("1 seconds")) {
+ protected void run() {
+
+ subject.tell(new CloseTransaction(), getRef());
+
+ final String out = new ExpectMsg<String>("match hint") {
+ // do not put code outside this method, will run afterwards
+ protected String match(Object in) {
+ if (in instanceof CloseTransactionReply) {
+ return "match";
+ } else {
+ throw noMatch();
+ }
+ }
+ }.get(); // this extracts the received message
+
+ assertEquals("match", out);
+
+ expectNoMsg();
+ }
+
+
+ };
+ }};
+
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.messages;
+
+import org.junit.Test;
+
+public class FindPrimaryTest {
+
+ @Test
+ public void testNewBuilderForType() throws Exception {
+
+ }
+
+ @Test
+ public void testToBuilder() throws Exception {
+
+ }
+
+ @Test
+ public void testGetDefaultInstanceForType() throws Exception {
+
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.shardstrategy;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+
+public class DefaultShardStrategyTest {
+
+ @Test
+ public void testFindShard() throws Exception {
+ String shard = new DefaultShardStrategy().findShard(TestModel.TEST_PATH);
+ Assert.assertEquals(DefaultShardStrategy.DEFAULT_SHARD, shard);
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.shardstrategy;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+
+import static junit.framework.Assert.assertNotNull;
+
+public class ShardStrategyFactoryTest {
+
+ @Rule
+ public ExpectedException expectedEx = ExpectedException.none();
+
+ @Test
+ public void testGetStrategy(){
+ ShardStrategy strategy = ShardStrategyFactory.getStrategy(TestModel.TEST_PATH);
+ assertNotNull(strategy);
+ }
+
+ @Test
+ public void testGetStrategyNullPointerExceptionWhenPathIsNull(){
+ expectedEx.expect(NullPointerException.class);
+ expectedEx.expectMessage("path should not be null");
+
+ ShardStrategyFactory.getStrategy(null);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.md.cluster.datastore.model;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
+public class TestModel {
+
+ public static final QName TEST_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13",
+ "test");
+ public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+ public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+ public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+ public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+ public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+ public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+ private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+ public static final InstanceIdentifier TEST_PATH = InstanceIdentifier.of(TEST_QNAME);
+ public static final InstanceIdentifier OUTER_LIST_PATH = InstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+ public static final QName TWO_QNAME = QName.create(TEST_QNAME,"two");
+ public static final QName THREE_QNAME = QName.create(TEST_QNAME,"three");
+
+
+ public static final InputStream getDatastoreTestInputStream() {
+ return getInputStream(DATASTORE_TEST_YANG);
+ }
+
+ private static InputStream getInputStream(final String resourceName) {
+ return TestModel.class.getResourceAsStream(DATASTORE_TEST_YANG);
+ }
+
+ public static SchemaContext createTestContext() {
+ YangParserImpl parser = new YangParserImpl();
+ Set<Module> modules = parser.parseYangModelsFromStreams(Collections.singletonList(getDatastoreTestInputStream()));
+ return parser.resolveSchemaContext(modules);
+ }
+}
--- /dev/null
+module odl-datastore-test {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+ prefix "store-test";
+
+ revision "2014-03-13" {
+ description "Initial revision.";
+ }
+
+ container test {
+ list outer-list {
+ key id;
+ leaf id {
+ type uint16;
+ }
+ choice outer-choice {
+ case one {
+ leaf one {
+ type string;
+ }
+ }
+ case two-three {
+ leaf two {
+ type string;
+ }
+ leaf three {
+ type string;
+ }
+ }
+ }
+ list inner-list {
+ key name;
+ leaf name {
+ type string;
+ }
+ leaf value {
+ type string;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>> afterCont = (NormalizedNodeContainer<?, PathArgument, NormalizedNode<PathArgument, ?>>) afterData;
return resolveNodeContainerReplaced(path, listeners, beforeCont, afterCont);
} else if (!beforeData.equals(afterData)) {
- // Node is either of Leaf type (does not contain child nodes)
- // or we do not have listeners, so normal equals method is
- // sufficient for determining change.
+ // Node is Leaf type (does not contain child nodes)
+ // so normal equals method is sufficient for determining change.
LOG.trace("Resolving leaf replace event for {} , before {}, after {}",path,beforeData,afterData);
DOMImmutableDataChangeEvent event = builder(DataChangeScope.BASE).setBefore(beforeData).setAfter(afterData)
.addUpdated(path, beforeData, afterData).build();
eventBuilder.merge(resolveSameEventRecursivelly(path.node(childId), childListeners, child, eventFactory));
}
propagateEvent = eventBuilder.build();
- } else {
- // We do not dispatch leaf events since Binding Aware components do not support them.
- propagateEvent = builder(DataChangeScope.BASE).build();
}
if (!listeners.isEmpty()) {
addPartialTask(listeners, propagateEvent);
*/
package org.opendaylight.controller.md.sal.dom.store.impl.tree.data;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTree;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeCandidate;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataTreeModification;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.DataValidationFailedException;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreUtils;
import org.opendaylight.controller.md.sal.dom.store.impl.tree.spi.TreeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Read-only snapshot of the data tree.
*/
package org.opendaylight.controller.sal.restconf.impl;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
-
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
-
import org.apache.commons.lang3.StringUtils;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
public class RestconfImpl implements RestconfService {
private final static RestconfImpl INSTANCE = new RestconfImpl();
operationsAsData.add(immutableSimpleNode);
String name = module.getName();
- LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName, null);
+ LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder(name, 0, rpcQName,
+ SchemaPath.create(true, QName.create("dummy")));
final LeafSchemaNodeBuilder fakeRpcSchemaNode = leafSchemaNodeBuilder;
fakeRpcSchemaNode.setAugmenting(true);
import java.io.IOException;
import java.util.Collections;
-
import javax.ws.rs.WebApplicationException;
-
import org.junit.BeforeClass;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
import org.opendaylight.controller.sal.restconf.impl.test.DummyType;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
+import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
import org.slf4j.Logger;
private DataSchemaNode prepareDataSchemaNode() {
ContainerSchemaNodeBuilder contBuild = new ContainerSchemaNodeBuilder("module", 1, TestUtils.buildQName("cont",
- "simple:uri", "2012-12-17"), null);
+ "simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
LeafSchemaNodeBuilder leafBuild = new LeafSchemaNodeBuilder("module", 2, TestUtils.buildQName("lf1",
- "simple:uri", "2012-12-17"), null);
+ "simple:uri", "2012-12-17"), SchemaPath.create(true, QName.create("dummy")));
leafBuild.setType(new DummyType());
leafBuild.setConfiguration(true);
<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+
<persisted-snapshots>
<snapshots>
<snapshot>
- <required-capabilities>
- <!-- <capability>urn:opendaylight:l2:types?module=opendaylight-l2-types&revision=2013-08-27</capability>-->
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28
- </capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28</capability>
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:config?module=config&revision=2013-04-05
- </capability>
- <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
- <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf-monitoring&revision=2010-10-04</capability>
- <capability>urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&revision=2013-06-17
- </capability>
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28
- </capability>
- <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2010-09-24
- </capability>
- <capability>urn:ietf:params:netconf:capability:rollback-on-error:1.0</capability>
- <capability>urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2010-09-24
- </capability>
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28
- </capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&revision=2013-07-16</capability>
- <!-- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&revision=2013-07-09</capability>-->
- <capability>
- urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28
- </capability>
- <capability>http://netconfcentral.org/ns/toaster?module=toaster&revision=2009-11-20</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&revision=2014-01-31</capability>
- <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31</capability>
-
- </required-capabilities>
<configuration>
-
<data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:schema-service-singleton</type>
+ <name>yang-schema-service</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:runtime-generated-mapping</type>
+ <name>runtime-mapping-singleton</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-notification-broker</type>
+ <name>binding-notification-broker</name>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-broker-impl</type>
+ <name>binding-broker-impl</name>
+ <notification-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <name>binding-notification-broker</name>
+ </notification-service>
+ <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ </module>
+
+ <!--
+ Tree-based in-memory data store. This is the data store which is currently
+ recommended for single-node deployments.
+ -->
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-inmemory-data-broker</type>
+ <name>inmemory-data-broker</name>
+ <schema-service>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <name>yang-schema-service</name>
+ </schema-service>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">prefix:dom-broker-impl</type>
+ <name>inmemory-dom-broker</name>
+ <async-data-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
+ <name>inmemory-data-broker</name>
+ </async-data-broker>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-data-compatible-broker</type>
+ <name>inmemory-binding-data-broker</name>
+ <dom-async-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-async-broker>
+ <binding-mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+ <name>runtime-mapping-singleton</name>
+ </binding-mapping-service>
+ </module>
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">prefix:binding-forwarded-data-broker</type>
+ <name>binding-async-data-broker</name>
+ <binding-forwarded-data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
+ <dom-async-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
+ <name>dom-broker</name>
+ </dom-async-broker>
+ <binding-mapping-service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-dom-mapping-service</type>
+ <name>runtime-mapping-singleton</name>
+ </binding-mapping-service>
+ </binding-forwarded-data-broker>
+ </module>
+
+ <!-- Toaster Congiguration -->
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
prefix:toaster-provider-impl
<data-broker>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
- <name>ref_binding-data-broker</name>
+ <name>binding-data-broker</name>
</data-broker>
<notification-service>
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-notification-service
</type>
- <name>ref_binding-notification-broker</name>
+ <name>binding-notification-broker</name>
</notification-service>
</module>
+ <!-- Kitchen Service -->
<module>
<type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
prefix:kitchen-service-impl
<type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
binding:binding-notification-service
</type>
- <name>ref_binding-notification-broker</name>
- </notification-service>
- </module>
-
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- prefix:schema-service-singleton
- </type>
- <name>yang-schema-service</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- prefix:hash-map-data-store
- </type>
- <name>hash-map-data-store</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- prefix:dom-broker-impl
- </type>
- <name>dom-broker</name>
- <data-store xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
- dom:dom-data-store
- </type>
- <name>ref_hash-map-data-store</name>
- </data-store>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- prefix:binding-broker-impl
- </type>
- <name>binding-broker-impl</name>
- <notification-service
- xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-notification-service
- </type>
- <name>ref_binding-notification-broker</name>
+ <name>binding-notification-broker</name>
</notification-service>
- <data-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-data-broker
- </type>
- <name>ref_binding-data-broker</name>
- </data-broker>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- prefix:runtime-generated-mapping
- </type>
- <name>runtime-mapping-singleton</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- prefix:binding-notification-broker
- </type>
- <name>binding-notification-broker</name>
- </module>
- <module>
- <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- prefix:binding-data-broker
- </type>
- <name>binding-data-broker</name>
- <dom-broker xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
- dom:dom-broker-osgi-registry
- </type>
- <name>ref_dom-broker</name>
- </dom-broker>
- <mapping-service xmlns="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- binding:binding-dom-mapping-service
- </type>
- <name>ref_runtime-mapping-singleton</name>
- </mapping-service>
</module>
</modules>
-
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
<service>
- <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
- kitchen:kitchen-service
- </type>
- <instance>
- <name>kitchen-service</name>
- <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
- </instance>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:schema-service</type>
+ <instance>
+ <name>yang-schema-service</name>
+ <provider>/modules/module[type='schema-service-singleton'][name='yang-schema-service']</provider>
+ </instance>
</service>
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
- dom:schema-service
- </type>
+ <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding-impl:binding-dom-mapping-service</type>
<instance>
- <name>ref_yang-schema-service</name>
- <provider>
- /config/modules/module[name='schema-service-singleton']/instance[name='yang-schema-service']
- </provider>
+ <name>runtime-mapping-singleton</name>
+ <provider>/modules/module[type='runtime-generated-mapping'][name='runtime-mapping-singleton']</provider>
</instance>
</service>
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-notification-service
- </type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
<instance>
- <name>ref_binding-notification-broker</name>
- <provider>
- /config/modules/module[name='binding-notification-broker']/instance[name='binding-notification-broker']
- </provider>
+ <name>binding-notification-broker</name>
+ <provider>/modules/module[type='binding-notification-broker'][name='binding-notification-broker']</provider>
</instance>
</service>
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
- dom:dom-data-store
- </type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
<instance>
- <name>ref_hash-map-data-store</name>
- <provider>
- /config/modules/module[name='hash-map-data-store']/instance[name='hash-map-data-store']
- </provider>
+ <name>binding-osgi-broker</name>
+ <provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
</instance>
</service>
<service>
<provider>/modules/module[type='binding-broker-impl'][name='binding-broker-impl']</provider>
</instance>
</service>
+
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-broker-osgi-registry
- </type>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-broker-osgi-registry</type>
<instance>
- <name>ref_binding-broker-impl</name>
- <provider>
- /config/modules/module[name='binding-broker-impl']/instance[name='binding-broker-impl']
- </provider>
+ <name>dom-broker</name>
+ <provider>/modules/module[type='dom-broker-impl'][name='inmemory-dom-broker']</provider>
</instance>
</service>
+
<service>
- <type xmlns:binding-impl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">
- binding-impl:binding-dom-mapping-service
- </type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-data-broker</type>
<instance>
- <name>ref_runtime-mapping-singleton</name>
- <provider>
- /config/modules/module[name='runtime-generated-mapping']/instance[name='runtime-mapping-singleton']
- </provider>
+ <name>binding-data-broker</name>
+ <provider>/modules/module[type='binding-data-compatible-broker'][name='inmemory-binding-data-broker']</provider>
</instance>
</service>
+
<service>
- <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
- dom:dom-broker-osgi-registry
- </type>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
<instance>
- <name>ref_dom-broker</name>
- <provider>/config/modules/module[name='dom-broker-impl']/instance[name='dom-broker']
- </provider>
+ <name>binding-data-broker</name>
+ <provider>/modules/module[type='binding-forwarded-data-broker'][name='binding-async-data-broker']</provider>
</instance>
</service>
+
<service>
- <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
- binding:binding-data-broker
- </type>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">dom:dom-async-data-broker</type>
<instance>
- <name>ref_binding-data-broker</name>
- <provider>
- /config/modules/module[name='binding-data-broker']/instance[name='binding-data-broker']
- </provider>
+ <name>inmemory-data-broker</name>
+ <provider>/modules/module[type='dom-inmemory-data-broker'][name='inmemory-data-broker']</provider>
</instance>
</service>
+
+ <!-- Toaster samples -->
+ <service>
+ <type xmlns:kitchen="urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl">
+ kitchen:kitchen-service
+ </type>
+ <instance>
+ <name>kitchen-service</name>
+ <provider>/modules/module[type='kitchen-service-impl'][name='kitchen-service-impl']</provider>
+ </instance>
+ </service>
</services>
</data>
-
</configuration>
- </snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&revision=2013-10-28</capability>
+ <!-- Toaster capabilities -->
+ <capability>http://netconfcentral.org/ns/toaster?module=toaster&revision=2009-11-20</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31</capability>
+
+ </required-capabilities>
+ </snapshot>
</snapshots>
</persisted-snapshots>