Merge "BUG 484 - XmlReader improve readability"
authorTony Tkacik <ttkacik@cisco.com>
Tue, 24 Jun 2014 07:34:49 +0000 (07:34 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 24 Jun 2014 07:34:49 +0000 (07:34 +0000)
98 files changed:
features/base/src/main/resources/features.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/config/config-manager/pom.xml
opendaylight/config/netconf-config-dispatcher/pom.xml
opendaylight/config/pom.xml
opendaylight/config/threadpool-config-impl/pom.xml
opendaylight/config/yang-jmx-generator-plugin/pom.xml
opendaylight/config/yang-test-plugin/pom.xml
opendaylight/config/yang-test/pom.xml
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/pom.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/FromSalConversionsUtils.java
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/FlowCapableInventoryProvider.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryActivator.java
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryOperation.java [new file with mode: 0644]
opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/NodeChangeCommiter.java
opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang [deleted file]
opendaylight/md-sal/pom.xml
opendaylight/md-sal/remoterpc-routingtable/integrationtest/pom.xml
opendaylight/md-sal/remoterpc-routingtable/integrationtest/test-nb/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-it/pom.xml
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataBroker.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeEvent.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncDataTransactionFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncReadWriteTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncTransaction.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/AsyncWriteTransaction.java
opendaylight/md-sal/sal-distributed-datastore/pom.xml
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistrationReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/ResolveDataChangeEventsTask.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/data/InMemoryDataTree.java
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/consumer-service/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/provider-service/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-it/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/integrationtest/test-nb/pom.xml
opendaylight/md-sal/sal-rest-connector/pom.xml
opendaylight/md-sal/sal-rest-docgen/pom.xml
opendaylight/md-sal/samples/l2switch/implementation/pom.xml
opendaylight/md-sal/samples/toaster-it/pom.xml
opendaylight/md-sal/samples/toaster-it/src/test/resources/controller.xml
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/md-sal/topology-manager/pom.xml
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-client/pom.xml
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/virtualsocket/ChannelInputStream.java
opendaylight/netconf/netconf-ssh/pom.xml
opendaylight/netconf/netconf-tcp/pom.xml
opendaylight/netconf/netconf-util/pom.xml

index 5677ab66d0bf971e43541583ce6b5955a57906e0..dd6eec8222988ed499aff01b2e56cb5163b119c2 100644 (file)
@@ -73,7 +73,7 @@
       <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">
index 990276468b7dd3c47098d749ed5ed270e6bcec15..3f25b7283f86c5d47b5651f66c934ef809c8999c 100644 (file)
@@ -20,9 +20,8 @@
     <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>
     <arphandler.version>0.5.2-SNAPSHOT</arphandler.version>
+    <!-- Controller Modules Versions -->
     <asm.version>4.1</asm.version>
     <!-- Plugin Versions -->
     <bouncycastle.version>1.50</bouncycastle.version>
@@ -30,7 +29,7 @@
     <bundlescanner.api.version>0.4.2-SNAPSHOT</bundlescanner.api.version>
     <bundlescanner.implementation.version>0.4.2-SNAPSHOT</bundlescanner.implementation.version>
     <bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
-    <checkstyle.version>2.10</checkstyle.version>
+    <checkstyle.version>2.12</checkstyle.version>
     <clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
     <clustering.services_implementation.version>0.4.3-SNAPSHOT</clustering.services_implementation.version>
     <clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
@@ -49,7 +48,8 @@
     <commons.io.version>2.4</commons.io.version>
     <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.lang.version>2.6</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>
@@ -88,6 +88,7 @@
     <felix.fileinstall.version>3.1.6</felix.fileinstall.version>
     <felix.webconsole.version>4.2.0</felix.webconsole.version>
     <filtervalve.version>1.4.2-SNAPSHOT</filtervalve.version>
+    <findbugs.maven.plugin.version>2.4.0</findbugs.maven.plugin.version>
     <flowprogrammer.northbound.version>0.4.2-SNAPSHOT</flowprogrammer.northbound.version>
     <flows.web.version>0.4.2-SNAPSHOT</flows.web.version>
     <forwarding.staticrouting>0.5.2-SNAPSHOT</forwarding.staticrouting>
     <java.version.target>1.7</java.version.target>
     <javassist.version>3.17.1-GA</javassist.version>
     <javax.annotation.version>1.2</javax.annotation.version>
+    <jdepend.maven.plugin.version>2.0-beta-2</jdepend.maven.plugin.version>
     <!-- Third party version -->
     <jersey-servlet.version>1.17</jersey-servlet.version>
     <jersey.version>1.17</jersey.version>
     <karaf.branding.version>1.0.0-SNAPSHOT</karaf.branding.version>
     <karaf.shell.version>3.0.0</karaf.shell.version>
     <karaf.version>3.0.1</karaf.version>
+    <lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
     <logback.version>1.0.9</logback.version>
     <logging.bridge.version>0.4.2-SNAPSHOT</logging.bridge.version>
     <maven.compile.plugin.version>2.5.1</maven.compile.plugin.version>
     <!-- Java Versions -->
     <maven.compiler.source>1.7</maven.compiler.source>
     <maven.compiler.target>1.7</maven.compiler.target>
+    <maven.plugin.api.version>3.0.5</maven.plugin.api.version>
     <mdsal.version>1.1-SNAPSHOT</mdsal.version>
     <mockito.version>1.9.5</mockito.version>
     <netconf.version>0.2.5-SNAPSHOT</netconf.version>
         <artifactId>guava</artifactId>
         <version>${guava.version}</version>
       </dependency>
+      <!-- 3rd party dependencies needed by config-->
+      <dependency>
+        <groupId>com.jcabi</groupId>
+        <artifactId>jcabi-maven-slf4j</artifactId>
+        <version>0.8</version>
+      </dependency>
 
       <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>commons-io</artifactId>
         <version>${commons.io.version}</version>
       </dependency>
+      <dependency>
+        <groupId>commons-lang</groupId>
+        <artifactId>commons-lang</artifactId>
+        <version>${commons.lang.version}</version>
+      </dependency>
       <dependency>
         <groupId>commons-net</groupId>
         <artifactId>commons-net</artifactId>
         <artifactId>jsr311-api</artifactId>
         <version>${jsr311.api.version}</version>
       </dependency>
+      <dependency>
+        <groupId>net.sourceforge.pmd</groupId>
+        <artifactId>pmd</artifactId>
+        <version>5.1.0</version>
+      </dependency>
       <dependency>
         <groupId>orbit</groupId>
         <artifactId>javax.activation</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>
         <artifactId>enunciate-core-annotations</artifactId>
         <version>${enunciate.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.codehaus.gmaven.runtime</groupId>
+        <artifactId>gmaven-runtime-2.0</artifactId>
+        <version>1.5</version>
+      </dependency>
       <dependency>
         <groupId>org.codehaus.jettison</groupId>
         <artifactId>jettison</artifactId>
         <version>${jettison.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.eclipse</groupId>
+        <artifactId>jdt</artifactId>
+        <version>3.3.0-v20070607-1300</version>
+      </dependency>
+      <dependency>
+        <groupId>org.eclipse.equinox</groupId>
+        <artifactId>app</artifactId>
+        <version>1.0.0-v20070606</version>
+      </dependency>
 
       <!-- equinox http service bridge -->
       <dependency>
         <artifactId>servlet</artifactId>
         <version>1.0.0-v20070606</version>
       </dependency>
+      <dependency>
+        <groupId>org.eclipse.jdt</groupId>
+        <artifactId>core</artifactId>
+        <version>3.3.0-v_771</version>
+      </dependency>
       <dependency>
         <groupId>org.eclipse.persistence</groupId>
         <artifactId>org.eclipse.persistence.antlr</artifactId>
         <artifactId>org.eclipse.xtend.lib</artifactId>
         <version>${xtend.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+        <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+        <version>2.4</version>
+      </dependency>
       <dependency>
         <groupId>org.javassist</groupId>
         <artifactId>javassist</artifactId>
         <version>${javassist.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.jboss.resteasy</groupId>
+        <artifactId>jaxrs-api</artifactId>
+        <version>3.0.4.Final</version>
+      </dependency>
       <dependency>
         <groupId>org.jboss.spec.javax.transaction</groupId>
         <artifactId>jboss-transaction-api_1.1_spec</artifactId>
         <artifactId>filter-valve</artifactId>
         <version>${filtervalve.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>flow-management-compatibility</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>flowprogrammer.northbound</artifactId>
         <artifactId>netconf-client</artifactId>
         <version>${netconf.version}</version>
       </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>netconf-client</artifactId>
+            <version>${netconf.version}</version>
+            <type>test-jar</type>
+        </dependency>
 
       <!--Netconf config-->
       <dependency>
         <artifactId>protocol_plugins.stub</artifactId>
         <version>${protocol_plugins.stub.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>remoterpc-routingtable.implementation</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>routing.dijkstra_implementation</artifactId>
         <artifactId>model-inventory</artifactId>
         <version>${mdsal.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.model</groupId>
+        <artifactId>model-topology</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster-consumer</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+
+      <dependency>
+        <groupId>org.opendaylight.controller.samples</groupId>
+        <artifactId>sample-toaster-provider</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.tests</groupId>
+        <artifactId>sal-remoterpc-connector-test-provider</artifactId>
+        <version>${mdsal.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
         <artifactId>yang-ext</artifactId>
         <version>${yang-ext.version}</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+        <artifactId>antlr4-runtime-osgi-nohead</artifactId>
+        <version>4.0</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.yangtools.thirdparty</groupId>
+        <artifactId>xtend-lib-osgi</artifactId>
+        <version>${xtend.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.openexi</groupId>
         <artifactId>nagasena</artifactId>
         <artifactId>chameleon-mbeans</artifactId>
         <version>1.0.0</version>
       </dependency>
+      <dependency>
+        <groupId>org.reflections</groupId>
+        <artifactId>reflections</artifactId>
+        <version>0.9.9-RC1</version>
+      </dependency>
       <dependency>
         <groupId>org.scala-lang</groupId>
         <artifactId>scala-library</artifactId>
         <version>${slf4j.version}</version>
         <scope>compile</scope>
       </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-simple</artifactId>
+        <version>${slf4j.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>org.springframework.aop</artifactId>
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
index 79fd5268e674c6ee7d6cc53a30b112b8fc5c90b6..fc2c0fd85b86f79a60c30fb34bc8199b1459c1c9 100644 (file)
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
-    <!--
-        <dependency>
-            <groupId>com.googlecode.json-simple</groupId>
-            <artifactId>json-simple</artifactId>
-            <version>1.1</version>
-        </dependency>
-        -->
+
     <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
index 65ebdaf938bd5092bd433f3f8b72dfe6d66a2d14..b9d218ead1ea0fe39efd15c051037ebc2807e8be 100644 (file)
@@ -26,7 +26,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
-      <version>${netconf.version}</version>
     </dependency>
   </dependencies>
 
index 5f34a9aa82d0ab35780b04862882710b7ae47fe8..76fbd7f6e55c057e6248fed354da9c8f801da2bb 100644 (file)
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-antrun-plugin</artifactId>
-          <version>1.3</version>
+          <version>${maven.antrun.plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>2.4</version>
           <executions>
             <execution>
               <goals>
@@ -99,7 +98,6 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
-          <version>2.14.1</version>
           <configuration>
             <redirectTestOutputToFile>true</redirectTestOutputToFile>
             <parallel>classes</parallel>
         <plugin>
           <groupId>org.codehaus.groovy.maven</groupId>
           <artifactId>gmaven-plugin</artifactId>
-          <version>1.0</version>
+          <version>${gmaven.plugin.version}</version>
         </plugin>
         <plugin>
           <groupId>org.opendaylight.yangtools</groupId>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
-        <version>2.12</version>
         <configuration>
           <failsOnError>false</failsOnError>
           <failOnViolation>false</failOnViolation>
index 4bc080bbff91f0cf0f2478432edcf83681e2b3f3..4fd0d681a11e49f5cf5038afaa6bd6c7a3c8c4de 100644 (file)
@@ -23,7 +23,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>threadpool-config-api</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
index b8831f6979ec3205e496c13ee1df15217d3d9feb..5f51980b94b530e3dbdb7e6e87059088c425b61b 100644 (file)
@@ -24,7 +24,6 @@
     <dependency>
       <groupId>com.jcabi</groupId>
       <artifactId>jcabi-maven-slf4j</artifactId>
-      <version>0.8</version>
     </dependency>
 
     <dependency>
@@ -40,7 +39,6 @@
     <dependency>
       <groupId>org.codehaus.gmaven.runtime</groupId>
       <artifactId>gmaven-runtime-2.0</artifactId>
-      <version>1.5</version>
       <exclusions>
         <exclusion>
           <groupId>org.sonatype.gossip</groupId>
     <dependency>
       <groupId>net.sourceforge.pmd</groupId>
       <artifactId>pmd</artifactId>
-      <version>5.1.0</version>
       <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse</groupId>
       <artifactId>jdt</artifactId>
-      <version>3.3.0-v20070607-1300</version>
       <scope>test</scope>
 
       <exclusions>
     <dependency>
       <groupId>org.eclipse.equinox</groupId>
       <artifactId>app</artifactId>
-      <version>1.0.0-v20070606</version>
       <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.eclipse.jdt</groupId>
       <artifactId>core</artifactId>
-      <version>3.3.0-v_771</version>
       <scope>test</scope>
 
       <exclusions>
index 173227f0bc53ddf781534a36eb9df522cae6e636..c7fb73f3854cf5316c0efc7d3b39972f6978e767 100644 (file)
@@ -24,7 +24,7 @@
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-plugin-api</artifactId>
-      <version>3.0.5</version>
+      <version>${maven.plugin.api.version}</version>
     </dependency>
   </dependencies>
 </project>
index 8c8065dd673a05f772ed2e3b2405c835db188f56..247b3c07459ef67531d3085242e38f22c21b770a 100644 (file)
@@ -64,7 +64,7 @@
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
index 6a6a12d1de2499cb1956f02f456b158fd79f470e..7970b3aa00f6fc38bf334ce93b8b52a8597581b2 100644 (file)
@@ -82,7 +82,7 @@
     </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>
index fc58ed96e1b9fba37af9ff846621e107a3671440..62dc2ffa1a147859d300997293d47c2de5031bee 100644 (file)
@@ -49,7 +49,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
index 6c79e053e16b353a5e4bdd51f6e44a469aec8b26..168dd14d10e20aa54b08a30a5417ed94737810ff 100644 (file)
@@ -26,7 +26,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
   </dependencies>
 
index a879a36f8c23e6321f26c8fee0ec47a4569df2a9..36045cabf4bfefc672d3edde8001a75deba46385 100644 (file)
@@ -205,6 +205,7 @@ public class FromSalConversionsUtils {
             VlanIdBuilder vlanIDBuilder = new VlanIdBuilder();
             vlanIDBuilder.setVlanId(new VlanId((NetUtils
                     .getUnsignedShort((short) vlan.getValue()))));
+            vlanIDBuilder.setVlanIdPresent(true);
             vlanMatchBuild.setVlanId(vlanIDBuilder.build());
         }
 
index 9bd63d3c3bb5268d8d6e5142dd38da888a90b906..b3096e6478857aa1ca0286efda6c7a78912b4813 100644 (file)
@@ -18,7 +18,6 @@
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>flow-management-compatibility</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index 7e4190f1df4b7246da4a175d2efabb103282383a..6ed61e3024b9522dbc89d99a979f93fbcb147c7f 100644 (file)
  */
 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();
+        }
     }
 }
index 6c06088fc4abefdeaaa859e52fc0f9a34da38edc..5bcae367e3e98a6270e01e270adbd2f231256fa9 100644 (file)
@@ -12,23 +12,32 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderCo
 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;
+        }
     }
 }
diff --git a/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryOperation.java b/opendaylight/md-sal/inventory-manager/src/main/java/org/opendaylight/controller/md/inventory/manager/InventoryOperation.java
new file mode 100644 (file)
index 0000000..3be5fcf
--- /dev/null
@@ -0,0 +1,16 @@
+/**
+ * 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);
+
+}
index 674ae398d3194d06e8a097d28be01a5b8d7a1ec3..3db3c93fcce11ccf46569514b901ef3c9c99e60d 100644 (file)
@@ -7,15 +7,11 @@
  */
 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;
@@ -31,123 +27,90 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 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);
             }
         });
     }
diff --git a/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang b/opendaylight/md-sal/model/model-inventory/src/main/yang/opendaylight-inventory-config.yang
deleted file mode 100644 (file)
index 1ccdfe8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-module opendaylight-inventory-config {
-    namespace "urn:opendaylight:inventory:config";
-    prefix inv-config;
-
-    import yang-ext {prefix ext; revision-date "2013-07-09";}
-    import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
-
-
-    revision "2013-08-19" {
-        description "Initial revision of Inventory model";
-    }
-    /** Base structure **/
-    container nodes {
-        list node {
-            key "id";
-            ext:context-instance "node-context";
-
-            uses inv:node;
-        }
-    }    
-}
index 8d4901d31b118659980148a20f79c0826b71a171..5b4f1718bccdd5cf1fc14f39b084b237550e9c7a 100644 (file)
@@ -88,7 +88,7 @@
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>findbugs-maven-plugin</artifactId>
-        <version>2.4.0</version>
+        <version>${findbugs.maven.plugin.version}</version>
         <configuration>
           <effort>Max</effort>
           <threshold>Low</threshold>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jdepend-maven-plugin</artifactId>
-        <version>2.0-beta-2</version>
+        <version>${jdepend.maven.plugin.version}</version>
       </plugin>
     </plugins>
   </reporting>
index 6db143ab3ebb801354aeebd6dba88be1650c6ba8..ce11be1e77a1d47c0cae6f35a0559d9ef4303f9a 100644 (file)
     <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>remoterpc-routingtable.implementation</artifactId>
-        <version>0.4.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>clustering.services</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal.implementation</artifactId>
-          <version>0.4.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>containermanager</artifactId>
-          <version>0.5.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>containermanager.it.implementation</artifactId>
-          <version>0.5.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>clustering.stub</artifactId>
-          <version>0.4.0-SNAPSHOT</version>
       </dependency>
         <dependency>
       <groupId>junit</groupId>
        <artifactId>pax-exam-container-native</artifactId>
        <scope>test</scope>
      </dependency>
-     <dependency>
-       <groupId>org.ops4j.pax.exam</groupId>
-       <artifactId>pax-exam-junit4</artifactId>
-       <scope>test</scope>
-     </dependency>
      <dependency>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>pax-exam-link-mvn</artifactId>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal</artifactId>
-          <version>0.5.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.yangtools</groupId>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-connector-api</artifactId>
-          <version>1.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common-util</artifactId>
-          <version>1.0-SNAPSHOT</version>
       </dependency>
 
       <dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-common-api</artifactId>
-          <version>1.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-common-util</artifactId>
-          <version>1.0-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.controller</groupId>
-          <artifactId>sal-binding-broker-impl</artifactId>
-          <version>1.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>sal-binding-broker-impl</artifactId>
-          <version>1.0-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>org.ops4j.pax.exam</groupId>
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>config-manager</artifactId>
-          <version>0.2.3-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>equinoxSDK381</groupId>
           <artifactId>org.eclipse.osgi</artifactId>
-          <version>3.8.1.v20120830-144521</version>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>log4j-over-slf4j</artifactId>
-          <version>1.7.2</version>
       </dependency>
       <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-core</artifactId>
-          <version>1.0.9</version>
       </dependency>
       <dependency>
           <groupId>ch.qos.logback</groupId>
           <artifactId>logback-classic</artifactId>
-          <version>1.0.9</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.yangtools.thirdparty</groupId>
           <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-          <version>4.0</version>
       </dependency>
       <dependency>
           <groupId>org.opendaylight.yangtools.thirdparty</groupId>
           <artifactId>xtend-lib-osgi</artifactId>
-          <version>2.4.3</version>
       </dependency>
 
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>clustering.services</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>junit</groupId>
       <dependency>
           <groupId>equinoxSDK381</groupId>
           <artifactId>org.eclipse.osgi</artifactId>
-          <version>3.8.1.v20120830-144521</version>
       </dependency>
       <dependency>
           <groupId>org.ops4j.pax.exam</groupId>
           <artifactId>pax-exam-junit4</artifactId>
-          <version>3.0.0</version>
-      </dependency>
-      <dependency>
-          <groupId>org.ops4j.pax.exam</groupId>
-          <artifactId>pax-exam-junit4</artifactId>
-          <version>3.0.0</version>
+          <version>${exam.version}</version>
       </dependency>
       <dependency>
           <groupId>org.ops4j.pax.exam</groupId>
           <artifactId>pax-exam</artifactId>
-          <version>3.0.0</version>
+          <version>${exam.version}</version>
       </dependency>
   </dependencies>
   <properties>
index 1fd4b762c173089c720ddf3842ccc202faf5c91c..d74e7130a41a607a5db322ce48cc44fa062a5152 100644 (file)
@@ -5,7 +5,7 @@
   <parent>
     <artifactId>sal-remoterpc-connector-test-parent</artifactId>
     <groupId>org.opendaylight.controller.tests</groupId>
-    <version>1.0-SNAPSHOT</version>
+    <version>1.1-SNAPSHOT</version>
   </parent>
 
   <artifactId>remoterpc-routingtable-nb-it</artifactId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>commons.northbound</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
-      <version>5.0.0</version>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
@@ -81,7 +77,6 @@
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>remoterpc-routingtable.implementation</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>com.google.guava</groupId>
index 7fc467670df5f686a0f7e2deb2a51a6a0f127974..35b186db6aeeaf5ed53ee8a7e43bf5d9e4fb1b82 100644 (file)
@@ -82,7 +82,6 @@
     <dependency>
       <groupId>org.reflections</groupId>
       <artifactId>reflections</artifactId>
-      <version>0.9.9-RC1</version>
       <scope>compile</scope>
     </dependency>
     <dependency>
index d1354f897fdcd45133c3ae17c5045a1ddf046095..fd5c5be18dc787c2bc6ae2237df3ce848b930ee7 100644 (file)
@@ -48,7 +48,6 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
-      <version>1.7.2</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
index 70847aabea0bdeb3670352f2a44c17c8aca3b703..b8bb891e790f7e905edc071c04e61608d4f277c1 100644 (file)
@@ -9,11 +9,9 @@
   <artifactId>sal-binding-it</artifactId>
 
   <properties>
-    <exam.version>3.0.0</exam.version>
     <sonar.jacoco.itReportPath>../sal-binding-broker/target/jacoco-it.exec</sonar.jacoco.itReportPath>
     <!-- Sonar jacoco plugin to get integration test coverage info -->
     <sonar.jacoco.reportPath>../sal-binding-broker/target/jacoco.exec</sonar.jacoco.reportPath>
-    <url.version>1.5.0</url.version>
   </properties>
 
   <dependencies>
@@ -80,7 +78,6 @@
     <dependency>
       <groupId>org.opendaylight.yangtools.thirdparty</groupId>
       <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-      <version>4.0</version>
     </dependency>
     <!--Compile scopes for all testing dependencies are intentional-->
     <!--This way, all testing dependencies can be transitively used by other integration test modules-->
@@ -90,7 +87,6 @@
     <dependency>
       <groupId>org.opendaylight.yangtools.thirdparty</groupId>
       <artifactId>xtend-lib-osgi</artifactId>
-      <version>2.4.3</version>
     </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
         <plugin>
           <groupId>org.eclipse.m2e</groupId>
           <artifactId>lifecycle-mapping</artifactId>
-          <version>1.0.0</version>
+          <version>${lifecycle.mapping.version}</version>
           <configuration>
             <lifecycleMappingMetadata>
               <pluginExecutions>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.14.1</version>
         <configuration>
           <reuseForks>false</reuseForks>
         </configuration>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index 87bbfd3d065a374e729c5f4e894bc4f40ddb17f9..fb429e5fd1342c0ca675040a315c1b8ad76456c7 100644 (file)
@@ -10,6 +10,52 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ *
+ * Provides access to a conceptual data tree store.
+ *
+ * <p>
+ * Also provides the ability to subscribe for changes to data under a given
+ * branch of the tree.
+ *
+ * <p>
+ * All operations on data tree are performed via one of the transactions:
+ * <ul>
+ * <li>Read-Only - allocated using {@link #newReadOnlyTransaction()}
+ * <li>Write-Only - allocated using {@link #newWriteOnlyTransaction()}
+ * <li>Read-Write - allocated using {@link #newReadWriteTransaction()}
+ * </ul>
+ *
+ * <p>
+ * These transactions provide a stable isolated view of data tree, which is
+ * guaranteed to be not affected by other concurrent transactions, until
+ * transaction is committed.
+ *
+ * <p>
+ * For a detailed explanation of how transaction are isolated and how transaction-local
+ * changes are committed to global data tree, see
+ * {@link AsyncReadTransaction}, {@link AsyncWriteTransaction},
+ * {@link AsyncReadWriteTransaction} and {@link AsyncWriteTransaction#commit()}.
+ *
+ *
+ * <p>
+ * It is strongly recommended to use the type of transaction, which
+ * provides only the minimal capabilities you need. This allows for
+ * optimizations at the data broker / data store level. For example,
+ * implementations may optimize the transaction for reading if they know ahead
+ * of time that you only need to read data - such as not keeping additional meta-data,
+ * which may be required for write transactions.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataBroker<P extends Path<P>, D, L extends AsyncDataChangeListener<P, D>> extends //
         AsyncDataTransactionFactory<P, D> {
 
@@ -17,52 +63,150 @@ public interface AsyncDataBroker<P extends Path<P>, D, L extends AsyncDataChange
      *
      * Scope of Data Change
      *
+     * <p>
      * Represents scope of data change (addition, replacement, deletion).
      *
-     * The terminology for types is reused from LDAP
+     * The terminology for scope types is reused from LDAP.
+     *
+     * <h2>Examples</h2>
+     *
+     * Following is an example model with comments describing what notifications
+     * you would receive based on the scope you specify, when you are
+     * registering for changes on container a.
      *
-     * @see http://www.idevelopment.info/data/LDAP/LDAP_Resources/SEARCH_Setting_the_SCOPE_Parameter.shtml
+     * <pre>
+     * container a              // scope BASE, ONE, SUBTREE
+     *    leaf "foo"            // scope ONE, SUBTREE
+     *    container             // scope ONE, SUBTREE
+     *       leaf  "bar"        // scope SUBTREE
+     *    list list             // scope ONE, SUBTREE
+     *      list [a]            // scope SUBTREE
+     *        id "a"            // scope SUBTREE
+     *      list [b]            // scope SUBTREE
+     *        id "b"            // scope SUBTREE
+     * </pre>
+     *
+     * Following is an example model with comments describing what notifications
+     * you would receive based on the scope you specify, when you are
+     * registering for changes on list list (without specifying concrete item in
+     * the list).
+     *
+     * <pre>
+     *  list list               // scope BASE, ONE, SUBTREE
+     *      list [a]            // scope ONE, SUBTREE
+     *        id "a"            // scope SUBTREE
+     *      list [b]            // scope ONE, SUBTREE
+     *        id "b"            // scope SUBTREE
+     * </pre>
+     *
+     *
+     * @see http://www.idevelopment.info/data/LDAP/LDAP_Resources/
+     *      SEARCH_Setting_the_SCOPE_Parameter.shtml
      */
     public enum DataChangeScope {
 
-       /**
-        * Represents only a direct change of the node, such as replacement of node,
-        * addition or deletion.
-        *
-        */
-       BASE,
-       /**
-        * Represent a change (addition,replacement,deletion)
-        * of the node or one of it's direct childs.
-        *
-        */
-       ONE,
-       /**
-        * Represents a change of the node or any of it's child nodes.
-        *
-        */
-       SUBTREE
+        /**
+         * Represents only a direct change of the node, such as replacement of a
+         * node, addition or deletion.
+         *
+         */
+        BASE,
+        /**
+         * Represent a change (addition,replacement,deletion) of the node or one
+         * of its direct children.
+         *
+         * This scope is superset of {@link #BASE}.
+         *
+         */
+        ONE,
+        /**
+         * Represents a change of the node or any of or any of its child nodes,
+         * direct and nested.
+         *
+         * This scope is superset of {@link #ONE} and {@link #BASE}.
+         *
+         */
+        SUBTREE
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public AsyncReadTransaction<P, D> newReadOnlyTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public AsyncReadWriteTransaction<P,D> newReadWriteTransaction();
+    public AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
 
     /**
-     * Registers {@link DataChangeListener} for Data Change callbacks
-     * which will be triggered on which will be triggered on the store
+     * Registers a {@link AsyncDataChangeListener} to receive
+     * notifications when data changes under a given path in the conceptual data
+     * tree.
+     * <p>
+     * You are able to register for notifications  for any node or subtree
+     * which can be reached via the supplied path.
+     * <p>
+     * If path type <code>P</code> allows it, you may specify paths up to the leaf nodes
+     * then it is possible to listen on leaf nodes.
+     * <p>
+     * You are able to register for data change notifications for a subtree even
+     * if it does not exist. You will receive notification once that node is
+     * created.
+     * <p>
+     * If there is any preexisting data in data tree on path for which you are
+     * registering, you will receive initial data change event, which will
+     * contain all preexisting data, marked as created.
+     *
+     * <p>
+     * You are also able to specify the scope of the changes you want to be
+     * notified.
+     * <p>
+     * Supported scopes are:
+     * <ul>
+     * <li>{@link DataChangeScope#BASE} - notification events will only be
+     * triggered when a node referenced by path is created, removed or replaced.
+     * <li>{@link DataChangeScope#ONE} - notifications events will only be
+     * triggered when a node referenced by path is created, removed or replaced,
+     * or any or any of its immediate children are created, updated or removed.
+     * <li>{@link DataChangeScope#SUBTREE} - notification events will be
+     * triggered when a node referenced by the path is created, removed
+     * or replaced or any of the children in its subtree are created, removed
+     * or replaced.
+     * </ul>
+     * See {@link DataChangeScope} for examples.
+     * <p>
+     * This method returns a {@link ListenerRegistration} object. To
+     * "unregister" your listener for changes call the "close" method on this
+     * returned object.
+     * <p>
+     * You MUST call close when you no longer need to receive notifications
+     * (such as during shutdown or for example if your bundle is shutting down).
      *
-     * @param store Logical store in which listener is registered.
-     * @param path Path (subtree identifier) on which client listener will be invoked.
-     * @param listener Instance of listener which should be invoked on
-     * @param triggeringScope Scope of change which triggers callback.
-     * @return Listener registration of the listener, call {@link ListenerRegistration#close()}
-     *         to stop delivery of change events.
+     * @param store
+     *            Logical Data Store - Logical Datastore you want to listen for
+     *            changes in. For example
+     *            {@link LogicalDatastoreType#OPERATIONAL} or
+     *            {@link LogicalDatastoreType#CONFIGURATION}
+     * @param path
+     *            Path (subtree identifier) on which client listener will be
+     *            invoked.
+     * @param listener
+     *            Instance of listener which should be invoked on
+     * @param triggeringScope
+     *            Scope of change which triggers callback.
+     * @return Listener registration object, which may be used to unregister
+     *         your listener using {@link ListenerRegistration#close()} to stop
+     *         delivery of change events.
      */
-    ListenerRegistration<L> registerDataChangeListener(LogicalDatastoreType store, P path, L listener, DataChangeScope triggeringScope);
+    ListenerRegistration<L> registerDataChangeListener(LogicalDatastoreType store, P path, L listener,
+            DataChangeScope triggeringScope);
 }
index f612e51747aa4cb5e066cb00b6fd85bea74ed0a3..29c9bae31f76e2b1a1269116c2b3438cfa572172 100644 (file)
@@ -13,63 +13,128 @@ import java.util.Set;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Path;
 
-public interface AsyncDataChangeEvent<P extends Path<P>,D> extends Immutable {
+/**
+ *
+ * An event which contains a capture of changes in a data subtree
+ *
+ * <p>
+ * Represents a notification indicating that some data at or under a particular
+ * path has changed. The notification contains a capture of the changes in the data
+ * subtree. This event is triggered by successful application of modifications
+ * from a transaction on the global data tree. Use the
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * method to register a listener for data change events.
+ *
+ * <p>
+ * A listener will only receive notifications for changes to data under the path
+ * they register for. See
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * to learn more about registration scopes.
+ *
+ * <p>
+ * The entire subtree under the path will be provided via instance methods of Data
+ * Change Event even if just a leaf node changes.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
+public interface AsyncDataChangeEvent<P extends Path<P>, D> extends Immutable {
     /**
-     * Returns a immutable map of paths and newly created objects
+     * Returns a map of paths and newly created objects, which were introduced by
+     * this change into conceptual data tree, if no new objects were introduced
+     * this map will be empty.
+     *<p>
+     * This map contains all data tree nodes (and paths to them) which were created
+     * and are in  the scope of listener registration. The data tree nodes
+     * contain their whole subtree with their current state.
      *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedData();
 
     /**
-     * Returns a immutable map of paths and respective updated objects after update.
-     *
-     * Original state of the object is in
-     * {@link #getOriginalData()}
+     * Returns a map of paths and objects which were updated by this change in the
+     * conceptual data tree if no existing objects were updated
+     * this map will be empty.
+     *<p>
+     * This map contains all data tree nodes (and paths to them) which were updated
+     * and are in the scope of listener registration. The data tree nodes
+     * contain their whole subtree with their current state.
+     *<p>
+     * A Node is considered updated if it contents were replaced or one of its
+     * children was created, removed or updated.
+     *<p>
+     * Original state of the updated data tree nodes is in
+     * {@link #getOriginalData()} stored with same path.
      *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedData();
 
     /**
-     * Returns a immutable set of removed paths.
-     *
-     * Original state of the object is in
-     * {@link #getOriginalData()}
+     * Returns an immutable set of removed paths.
+     *<p>
+     * This set contains the paths to the data tree nodes which are in the scope
+     * of the listener registration that have been removed.
+     *<p>
+     * Original state of the removed data tree nodes is in
+     * {@link #getOriginalData()} stored with same path.
      *
      * @return set of removed paths
      */
     Set<P> getRemovedPaths();
 
     /**
-     * Return a immutable map of paths and original state of updated and removed objects.
+     * Returns an immutable map of updated or removed paths and their original
+     * states prior to this change.
      *
-     * This map is populated if at changed path was previous object, and captures
-     * state of previous object.
+     *<p>
+     * This map contains the original version of the data tree nodes (and paths
+     * to them), which are in the scope of the listener registration.
      *
      * @return map of paths and original state of updated and removed objects.
      */
     Map<P, ? extends D> getOriginalData();
 
     /**
-     * Returns a  immutable stable view of data state, which
-     * captures state of data store before the reported change.
+     * Returns an immutable stable view of data state, which captures the state of
+     * data store before the reported change.
      *
+     *<p>
+     * The view is rooted at the point where the listener, to which the event is
+     * being delivered, was registered.
+     *<p>
+     * If listener used a wildcarded path (if supported by path type) during
+     * registration for change listeners this method returns null, and original
+     * state can be accessed only via {@link #getOriginalData()}
      *
-     * The view is rooted at the point where the listener, to which the event is being delivered, was registered.
-     *
-     * @return Stable view of data before the change happened, rooted at the listener registration path.
+     * @return Stable view of data before the change happened, rooted at the
+     *         listener registration path.
      *
      */
     D getOriginalSubtree();
 
     /**
-     * Returns a immutable stable view of data, which captures state of data store
-     * after the reported change.
-     *
-     * The view is rooted at the point where the listener, to which the event is being delivered, was registered.
+     * Returns an immutable stable view of data, which captures the state of data
+     * store after the reported change.
+     *<p>
+     * The view is rooted at the point where the listener, to which the event is
+     * being delivered, was registered.
+     *<p>
+     * If listener used a wildcarded path (if supported by path type) during
+     * registration for change listeners this method returns null, and state
+     * can be accessed only via {@link #getCreatedData()},
+     * {@link #getUpdatedData()}, {@link #getRemovedPaths()}
      *
-     * @return Stable view of data after the change happened, rooted at the listener registration path.
+     * @return Stable view of data after the change happened, rooted at the
+     *         listener registration path.
      */
     D getUpdatedSubtree();
 }
index 49f07bc52b4f8aecefab507121d8d91984f1f8d3..dca5200d392687e25493876f945e347d3e394bf4 100644 (file)
@@ -11,13 +11,42 @@ import java.util.EventListener;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ * Listener of data change events on particular subtree.
+ *
+ * <p>
+ * User-supplied implementations of this listener interface MUST register via
+ * {@link AsyncDataBroker#registerDataChangeListener(LogicalDatastoreType, Path, AsyncDataChangeListener, AsyncDataBroker.DataChangeScope)}
+ * in order to start receiving data change events, which capture state changes
+ * in a subtree.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is intended to be implemented
+ * by users of MD-SAL.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataChangeListener<P extends Path<P>, D> extends EventListener {
     /**
-     * Note that this method may be invoked from a shared thread pool, so
+     *
+     * Invoked when there is data change for the particular path, which was used to
+     * register this listener.
+     * <p>
+     * This method may be also invoked during registration of the listener if
+     * there is any preexisting data in the conceptual data tree for supplied path.
+     * This initial event will contain all preexisting data as created.
+     *
+     * <p>
+     * <b>Note</b> that this method may be invoked from a shared thread pool, so
      * implementations SHOULD NOT perform CPU-intensive operations and they
      * definitely MUST NOT invoke any potentially blocking operations.
      *
-     * @param change Data Change Event being delivered.
+     * @param change
+     *            Data Change Event being delivered.
      */
     void onDataChanged(AsyncDataChangeEvent<P, D> change);
 }
index 732fed0f3f482466ee3a4acb682b73f6826ea8ea..cedd883b220199116502b47bc034ac1fe98ea5f2 100644 (file)
@@ -9,12 +9,110 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Path;
 
+/**
+ * A factory which allocates new transactions to operate on the data
+ * tree.
+ *
+ * <p>
+ * <b>Note:</b> This interface is not intended to be used directly, but rather
+ * via subinterfaces which introduces additional semantics to allocated
+ * transactions.
+ * <ul>
+ * <li> {@link AsyncDataBroker}
+ * <li> {@link TransactionChain}
+ * </ul>
+ *
+ * <p>
+ * All operations on the data tree are performed via one of the transactions:
+ * <ul>
+ * <li>Read-Only - allocated using {@link #newReadOnlyTransaction()}
+ * <li>Write-Only - allocated using {@link #newWriteOnlyTransaction()}
+ * <li>Read-Write - allocated using {@link #newReadWriteTransaction()}
+ * </ul>
+ *
+ * <p>
+ * These transactions provides a stable isolated view of the data tree, which is
+ * guaranteed to be not affected by other concurrent transactions, until
+ * transaction is committed.
+ *
+ * <p>
+ * For a detailed explanation of how transaction are isolated and how transaction-local
+ * changes are committed to global data tree, see
+ * {@link AsyncReadTransaction}, {@link AsyncWriteTransaction},
+ * {@link AsyncReadWriteTransaction} and {@link AsyncWriteTransaction#commit()}.
+ *
+ * <p>
+ * It is strongly recommended to use the type of transaction, which
+ * provides only the minimal capabilities you need. This allows for
+ * optimizations at the data broker / data store level. For example,
+ * implementations may optimize the transaction for reading if they know ahead
+ * of time that you only need to read data - such as not keeping additional meta-data,
+ * which may be required for write transactions.
+ *<p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @see AsyncDataBroker
+ * @see TransactionChain
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncDataTransactionFactory<P extends Path<P>, D> {
 
+    /**
+     * Allocates a new read-only transaction which provides an immutable snapshot of
+     * the data tree.
+     *<p>
+     * The view of data tree is an immutable snapshot of current data tree state when
+     * transaction was allocated.
+     *
+     * @return new read-only transaction
+     */
     AsyncReadTransaction<P, D> newReadOnlyTransaction();
 
+    /**
+     * Allocates new read-write transaction which provides a mutable view of the data
+     * tree.
+     *
+     * <p>
+     * Preconditions for mutation of data tree are captured from the snapshot of
+     * data tree state, when the transaction is allocated. If data was
+     * changed during transaction in an incompatible way then the commit of this transaction
+     * will fail. See {@link AsyncWriteTransaction#commit()} for more
+     * details about conflicting and not-conflicting changes and
+     * failure scenarios.
+     *
+     * @return new read-write transaction
+     */
     AsyncReadWriteTransaction<P, D> newReadWriteTransaction();
 
-    AsyncWriteTransaction<P,D> newWriteOnlyTransaction();
+    /**
+     * Allocates new write-only transaction based on latest state of data
+     * tree.
+     *
+     * <p>
+     * Preconditions for mutation of data tree are captured from the snapshot of
+     * data tree state, when the transaction is allocated. If data was
+     * changed during transaction in an incompatible way then the commit of this transaction
+     * will fail. See {@link AsyncWriteTransaction#commit()} for more
+     * details about conflicting and not-conflicting changes and
+     * failure scenarios.
+     *
+     * <p>
+     * Since this transaction does not provide a view of the data it SHOULD BE
+     * used only by callers which are exclusive writers (exporters of data)
+     * to the subtree they modify. This prevents optimistic
+     * lock failures as described in {@link AsyncWriteTransaction#commit()}.
+     * <p>
+     * Exclusivity of writers to particular subtree SHOULD BE enforced by
+     * external locking mechanism.
+     *
+     * @return new write-only transaction
+     */
+    AsyncWriteTransaction<P, D> newWriteOnlyTransaction();
 
 }
index 7744f71888fe0ac6017bea1513962e00915da57e..6cf5a5b532d41725ce76f45299536de76c63ece2 100644 (file)
@@ -12,12 +12,61 @@ import org.opendaylight.yangtools.concepts.Path;
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.ListenableFuture;
 
+/**
+ *
+ * Provides a stateful read-only view of the data tree.
+ *
+ * <p>
+ * View of the data tree is a stable point-in-time snapshot of the current data tree state when
+ * the transaction was created. It's state and underlying data tree
+ * is not affected by other concurrently running transactions.
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * <h2>Transaction isolation example</h2> Lest assume initial state of data tree
+ * for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * txRead = broker.newReadOnlyTransaction();   // read Transaction is snapshot of data
+ * txWrite = broker.newReadWriteTransactoin(); // concurrent write transaction
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // will return Optional containing A
+ * txWrite = broker.put(OPERATIONAL,PATH,B);   // writes B to PATH
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * txAfterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * txAfterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B;
+ * </pre>
+ *
+ * <p>
+ * <b>Note:</b> example contains blocking calls on future only to illustrate
+ * that action happened after other asynchronous action. Use of blocking call
+ * {@link ListenableFuture#get()} is discouraged for most uses and you should
+ * use
+ * {@link com.google.common.util.concurrent.Futures#addCallback(ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * or other functions from {@link com.google.common.util.concurrent.Futures} to
+ * register more specific listeners.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
 public interface AsyncReadTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
 
     /**
      *
-     * Reads data from provided logical data store located at provided path
-     *
+     * Reads data from provided logical data store located at the provided path.
+     *<p>
+     * If the target is a subtree, then the whole subtree is read (and will be
+     * accessible from the returned data object).
      *
      * @param store
      *            Logical data store from which read should occur.
@@ -26,10 +75,11 @@ public interface AsyncReadTransaction<P extends Path<P>, D> extends AsyncTransac
      *            read
      * @return Listenable Future which contains read result
      *         <ul>
-     *         <li>If data at supplied path exists the {@link Future#get()}
-     *         returns Optional object containing data
+     *         <li>If data at supplied path exists the
+     *         {@link ListeblaFuture#get()} returns Optional object containing
+     *         data once read is done.
      *         <li>If data at supplied path does not exists the
-     *         {@link Future#get()} returns {@link Optional#absent()}.
+     *         {@link ListenbleFuture#get()} returns {@link Optional#absent()}.
      *         </ul>
      */
     ListenableFuture<Optional<D>> read(LogicalDatastoreType store, P path);
index ce740bf41d9d798bb69bf42c573f4a6a98ecbaa9..34101366c806fe56884622ed3118e7d35090228c 100644 (file)
@@ -10,12 +10,126 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import org.opendaylight.yangtools.concepts.Path;
 
 /**
- * Transaction enabling client to have combined transaction,
- * which provides read and write capabilities.
+ * Transaction enabling a client to have a combined read/write capabilities.
  *
+ * <p>
+ * The initial state of the write transaction is stable snapshot of current data tree
+ * state captured when transaction was created and it's state and underlying
+ * data tree are not affected by other concurrently running transactions.
  *
- * @param <P> Path Type
- * @param <D> Data Type
+ * <p>
+ * Write transactions are isolated from other concurrent write transactions. All
+ * writes are local to the transaction and represents only a proposal of state
+ * change for data tree and it is not visible to any other concurrently running
+ * transactions.
+ *
+ * <p>
+ * Applications publish the changes proposed in the transaction by calling {@link #commit}
+ * on the transaction. This seals the transaction
+ * (preventing any further writes using this transaction) and submits it to be
+ * processed and applied to global conceptual data tree.
+ *
+ * <p>
+ * The transaction commit may fail due to a concurrent transaction modifying and committing data in
+ * an incompatible way. See {@link #commit()} for more concrete commit failure examples.
+ *
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * <h2>Examples</h2>
+ *
+ * <h3>Transaction local state</h3>
+ *
+ * Let assume initial state of data tree for <code>PATH</code> is <code>A</code>
+ * .
+ *
+ * <pre>
+ * txWrite = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ * txWrite.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ * </pre>
+ *
+ * As you could see read-write transaction provides capabilities as
+ * {@link AsyncWriteTransaction} but also allows for reading proposed changes as
+ * if they already happened.
+ *
+ * <h3>Transaction isolation (read transaction, read-write transaction)</h3> Let
+ * assume initial state of data tree for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * txRead = broker.newReadOnlyTransaction();   // read Transaction is snapshot of data
+ * txWrite = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // will return Optional containing A
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ *
+ * txWrite.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * txWrite.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * txRead.read(OPERATIONAL,PATH).get();        // concurrent read transaction still returns
+ *                                             // Optional containing A
+ *
+ * txWrite.commit().get();                     // data tree is updated, PATH contains B
+ * txRead.read(OPERATIONAL,PATH).get();        // still returns Optional containing A
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ * </pre>
+ *
+ * <h3>Transaction isolation (2 concurrent read-write transactions)</h3> Let
+ * assume initial state of data tree for <code>PATH</code> is <code>A</code>.
+ *
+ * <pre>
+ * tx1 = broker.newReadWriteTransaction(); // read Transaction is snapshot of data
+ * tx2 = broker.newReadWriteTransaction(); // concurrent write transaction
+ *
+ * tx1.read(OPERATIONAL,PATH).get();       // will return Optional containing A
+ * tx2.read(OPERATIONAL,PATH).get()        // will return Optional containing A
+ *
+ * tx2.put(OPERATIONAL,PATH,B);            // writes B to PATH
+ * tx2.read(OPERATIONAL,PATH).get()        // will return Optional Containing B
+ *
+ * tx1.read(OPERATIONAL,PATH).get();       // tx1 read-write transaction still sees Optional
+ *                                         // containing A since is isolated from tx2
+ * tx1.put(OPERATIONAL,PATH,C);            // writes C to PATH
+ * tx1.read(OPERATIONAL,PATH).get()        // will return Optional Containing C
+ *
+ * tx2.read(OPERATIONAL,PATH).get()        // tx2 read-write transaction still sees Optional
+ *                                         // containing B since is isolated from tx1
+ *
+ * tx2.commit().get();                     // data tree is updated, PATH contains B
+ * tx1.read(OPERATIONAL,PATH).get();       // still returns Optional containing C since is isolated from tx2
+ *
+ * tx1afterCommit = broker.newReadOnlyTransaction(); // read Transaction is snapshot of new state
+ * tx1afterCommit.read(OPERATIONAL,PATH).get(); // returns Optional containing B
+ *
+ * tx1.commit()                            // Will fail with OptimisticLockFailedException
+ *                                         // which means concurrent transaction changed the same PATH
+ *
+ * </pre>
+ *
+ * <p>
+ * <b>Note:</b> examples contains blocking calls on future only to illustrate
+ * that action happened after other asynchronous action. Use of blocking call
+ * {@link com.google.common.util.concurrent.ListenableFuture#get()} is discouraged for most uses and you should
+ * use
+ * {@link com.google.common.util.concurrent.Futures#addCallback(com.google.common.util.concurrent.ListenableFuture, com.google.common.util.concurrent.FutureCallback)}
+ * or other functions from {@link com.google.common.util.concurrent.Futures} to
+ * register more specific listeners.
+ *
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
  */
 public interface AsyncReadWriteTransaction<P extends Path<P>, D> extends AsyncReadTransaction<P, D>,
         AsyncWriteTransaction<P, D> {
index 23ca275ef20ef24a710b39d5f06ff96fa9ca00ce..c7cc91528b7c255f60416df67e1ebddf4660c7b5 100644 (file)
@@ -13,7 +13,17 @@ import org.opendaylight.yangtools.concepts.Path;
 
 /**
  *
- * @author
+ * A common parent for all transactions which operate on a conceptual data tree.
+ *
+ * See derived transaction types for more concrete behavior:
+ * <ul>
+ * <li>{@link AsyncReadTransaction} - Read capabilities, user is able to read data from data tree</li>
+ * <li>{@link AsyncWriteTransaction} - Write capabilities, user is able to propose changes to data tree</li>
+ * <li>{@link AsyncReadWriteTransaction} - Read and Write capabilities, user is able to read state and to propose changes of state.</li>
+ * </ul>
+ *
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL.
  *
  * @param <P> Type of path (subtree identifier), which represents location in tree
  * @param <D> Type of data (payload), which represents data payload
index 82c48d2ddb27e657c12cb9c8f56f49997923b370..e2734eaddc4845396e3d866dec8d918ac9fe4bca 100644 (file)
@@ -13,56 +13,118 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-public interface AsyncWriteTransaction<P extends Path<P>, D>  extends AsyncTransaction<P, D> {
+/**
+ * Write transaction provides mutation capabilities for a data tree.
+ *
+ * <p>
+ * Initial state of write transaction is a stable snapshot of the current data tree.
+ * The state is captured when the transaction is created and its state and underlying
+ * data tree are not affected by other concurrently running transactions.
+ * <p>
+ * Write transactions are isolated from other concurrent write transactions. All
+ * writes are local to the transaction and represent only a proposal of state
+ * change for the data tree and it is not visible to any other concurrently running
+ * transaction.
+ * <p>
+ * Applications publish the changes proposed in the transaction by calling {@link #commit}
+ * on the transaction. This seals the transaction
+ * (preventing any further writes using this transaction) and submits it to be
+ * processed and applied to global conceptual data tree.
+ * <p>
+ * The transaction commit may fail due to a concurrent transaction modifying and committing data in
+ * an incompatible way. See {@link #commit()} for more concrete commit failure examples.
+ *
+ *
+ * <p>
+ * <b>Implementation Note:</b> This interface is not intended to be implemented
+ * by users of MD-SAL, but only to be consumed by them.
+ *
+ * @param <P>
+ *            Type of path (subtree identifier), which represents location in
+ *            tree
+ * @param <D>
+ *            Type of data (payload), which represents data payload
+ */
+public interface AsyncWriteTransaction<P extends Path<P>, D> extends AsyncTransaction<P, D> {
     /**
-     * Cancels transaction.
+     * Cancels the transaction.
      *
-     * Transaction could be only cancelled if it's status
-     * is {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED}
+     * Transactions can only be cancelled if it's status is
+     * {@link TransactionStatus#NEW} or {@link TransactionStatus#SUBMITED}
      *
-     * Invoking cancel() on {@link TransactionStatus#FAILED} or {@link TransactionStatus#CANCELED}
-     * will have no effect.
+     * Invoking cancel() on {@link TransactionStatus#FAILED} or
+     * {@link TransactionStatus#CANCELED} will have no effect.
      *
-     * @throws IllegalStateException If transaction status is {@link TransactionStatus#COMMITED}
+     * @throws IllegalStateException
+     *             If transaction status is {@link TransactionStatus#COMMITED}
      *
      */
     public void cancel();
 
     /**
-     * Store a piece of data at specified path. This acts as a add / replace operation,
-     * which is to say that whole subtree will be replaced by specified path.
+     * Store a piece of data at specified path. This acts as an add / replace
+     * operation, which is to say that whole subtree will be replaced by
+     * specified path. Performing the following put operations:
+     *
+     * <pre>
+     * 1) container { list [ a ] }
+     * 2) container { list [ b ] }
+     * </pre>
+     *
+     * will result in the following data being present:
+     *
+     * <pre>
+     * container { list [ b ] }
+     * </pre>
      *
-     * If you need add or merge of current object with specified use {@link #merge(LogicalDatastoreType, Path, Object)}
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @param data Data object to be written to specified path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * If you need to make sure that a parent object exists, but you do not want modify
+     * its preexisting state by using put, consider using
+     * {@link #merge(LogicalDatastoreType, Path, Object)}
+     *
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @param data
+     *            Data object to be written to specified path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void put(LogicalDatastoreType store, P path, D data);
 
     /**
-     * Store a piece of data at specified path. This acts as a merge operation,
+     * Store a piece of data at the specified path. This acts as a merge operation,
      * which is to say that any pre-existing data which is not explicitly
      * overwritten will be preserved. This means that if you store a container,
-     * its child lists will be merged. Performing the following put operations:
+     * its child lists will be merged. Performing the following merge
+     * operations:
      *
+     * <pre>
      * 1) container { list [ a ] }
      * 2) container { list [ b ] }
+     * </pre>
      *
      * will result in the following data being present:
      *
+     * <pre>
      * container { list [ a, b ] }
+     * </pre>
      *
-     * This also means that storing the container will preserve any augmentations
-     * which have been attached to it.
-     *
-     * If you require an explicit replace operation, use {@link #put(LogicalDatastoreType, Path, Object)} instead.
+     * This also means that storing the container will preserve any
+     * augmentations which have been attached to it.
+     *<p>
+     * If you require an explicit replace operation, use
+     * {@link #put(LogicalDatastoreType, Path, Object)} instead.
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @param data Data object to be written to specified path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @param data
+     *            Data object to be written to specified path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void merge(LogicalDatastoreType store, P path, D data);
 
@@ -70,9 +132,12 @@ public interface AsyncWriteTransaction<P extends Path<P>, D>  extends AsyncTrans
      * Remove a piece of data from specified path. This operation does not fail
      * if the specified path does not exist.
      *
-     * @param store Logical data store which should be modified
-     * @param path Data object path
-     * @throws IllegalStateException if the transaction is no longer {@link TransactionStatus#NEW}
+     * @param store
+     *            Logical data store which should be modified
+     * @param path
+     *            Data object path
+     * @throws IllegalStateException
+     *             if the transaction is no longer {@link TransactionStatus#NEW}
      */
     public void delete(LogicalDatastoreType store, P path);
 
@@ -80,41 +145,169 @@ public interface AsyncWriteTransaction<P extends Path<P>, D>  extends AsyncTrans
      *
      * Closes transaction and resources allocated to the transaction.
      *
-     * This call does not change Transaction status. Client SHOULD
-     * explicitly {@link #commit()} or {@link #cancel()} transaction.
+     * This call does not change Transaction status. Client SHOULD explicitly
+     * {@link #commit()} or {@link #cancel()} transaction.
      *
-     * @throws IllegalStateException if the transaction has not been
-     *         updated by invoking {@link #commit()} or {@link #cancel()}.
+     * @throws IllegalStateException
+     *             if the transaction has not been updated by invoking
+     *             {@link #commit()} or {@link #cancel()}.
      */
     @Override
     public void close();
 
     /**
-     * Initiates a commit of modification. This call logically seals the
-     * transaction, preventing any the client from interacting with the
-     * data stores. The transaction is marked as {@link TransactionStatus#SUBMITED}
-     * and enqueued into the data store backed for processing.
+     * Submits transaction to be applied to update logical data tree.
+     * <p>
+     * This call logically seals the transaction, which prevents the client from
+     * further changing data tree using this transaction. Any subsequent calls to
+     * {@link #put(LogicalDatastoreType, Path, Object)},
+     * {@link #merge(LogicalDatastoreType, Path, Object)} or
+     * {@link #delete(LogicalDatastoreType, Path)} will fail with
+     * {@link IllegalStateException}.
+     *
+     * The transaction is marked as {@link TransactionStatus#SUBMITED} and
+     * enqueued into the data store backed for processing.
      *
      * <p>
-     * The successful commit changes the state of the system and may affect
-     * several components.
+     * Whether or not the commit is successful is determined by versioning
+     * of data tree and validation of registered commit participants
+     * {@link AsyncConfigurationCommitHandler}
+     * if transaction changes {@link LogicalDatastoreType#CONFIGURATION} data tree.
+     *<p>
+     * The effects of successful commit of data depends on
+     * other data change listeners {@link AsyncDataChangeListener} and
+     * {@link AsyncConfigurationCommitHandler}, which was registered to the
+     * same {@link AsyncDataBroker}, to which this transaction belongs.
      *
+     * <h2>Failure scenarios</h2>
      * <p>
-     * The effects of successful commit of data are described in the
-     * specifications and YANG models describing the Provider components of
-     * controller. It is assumed that Consumer has an understanding of this
-     * changes.
-     *
-     * @see DataCommitHandler for further information how two-phase commit is
-     *      processed.
-     * @param store Identifier of the store, where commit should occur.
+     * Transaction may fail because of multiple reasons, such as
+     * <ul>
+     * <li>Another transaction finished earlier and modified the same node in
+     * non-compatible way (see below). In this case the returned future will fail with
+     * {@link OptimisticLockFailedException}. It is the responsibility of the
+     * caller to create a new transaction and submit the same modification again in
+     * order to update data tree.</li>
+     * <li>Data change introduced by this transaction did not pass validation by
+     * commit handlers or data was incorrectly structured. Returned future will
+     * fail with {@link DataValidationFailedException}. User should not retry to
+     * create new transaction with same data, since it probably will fail again.
+     * </li>
+     * </ul>
+     *
+     * <h3>Change compatibility</h3>
+     *
+     * There are several sets of changes which could be considered incompatible
+     * between two transactions which are derived from same initial state.
+     * Rules for conflict detection applies recursively for each subtree
+     * level.
+     *
+     * <h4>Change compatibility of leafs, leaf-list items</h4>
+     *
+     * Following table shows  state changes and failures between two concurrent transactions,
+     * which are based on same initial state, Tx 1 completes successfully
+     * before Tx 2 is submitted.
+     *
+     * <table>
+     * <tr><th>Initial state</th><th>Tx 1</th><th>Tx 2</th><th>Result</th></tr>
+     * <tr><td>Empty</td><td>put(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, state is A=1</td></tr>
+     * <tr><td>Empty</td><td>put(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     * <tr><td>Empty</td><td>merge(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, state is A=1</td></tr>
+     * <tr><td>Empty</td><td>merge(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     *
+     * <tr><td>A=0</td><td>put(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, A=1</td></tr>
+     * <tr><td>A=0</td><td>put(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     * <tr><td>A=0</td><td>merge(A,1)</td><td>put(A,2)</td><td>Tx 2 will fail, A=1</td></tr>
+     * <tr><td>A=0</td><td>merge(A,1)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     *
+     * <tr><td>A=0</td><td>delete(A)</td><td>put(A,2)</td><td>Tx 2 will fail, A does not exists</td></tr>
+     * <tr><td>A=0</td><td>delete(A)</td><td>merge(A,2)</td><td>A=2</td></tr>
+     * </table>
+     *
+     * <h4>Change compatibility of subtrees</h4>
+     *
+     * Following table shows  state changes and failures between two concurrent transactions,
+     * which are based on same initial state, Tx 1 completes successfully
+     * before Tx 2 is submitted.
+     *
+     * <table>
+     * <tr><th>Initial state</th><th>Tx 1</th><th>Tx 2</th><th>Result</th></tr>
+     *
+     * <tr><td>Empty</td><td>put(TOP,[])</td><td>put(TOP,[])</td><td>Tx 2 will fail, state is TOP=[]</td></tr>
+     * <tr><td>Empty</td><td>put(TOP,[])</td><td>merge(TOP,[])</td><td>TOP=[]</td></tr>
+     *
+     * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>Empty</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
+     *
+     * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>Empty</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>TOP=[FOO=1,BAR=1]</td></tr>
+     *
+     * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>put(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is TOP=[FOO=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP,[FOO=1])</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP,[BAR=1])</td><td>Tx 2 will fail, state is empty store</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP,[BAR=1])</td><td>state is TOP=[BAR=1]</td></tr>
+     *
+     * <tr><td>TOP=[]</td><td>put(TOP/FOO,1)</td><td>put(TOP/BAR,1])</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>put(TOP/FOO,1)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>merge(TOP/FOO,1)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=1,BAR=1]</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>put(TOP/BAR,1)</td><td>Tx 2 will fail, state is empty store</td></tr>
+     * <tr><td>TOP=[]</td><td>delete(TOP)</td><td>merge(TOP/BAR,1]</td><td>Tx 2 will fail, state is empty store</td></tr>
+     *
+     * <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>put(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>merge(TOP/FOO,2)</td><td>merge(TOP/BAR,1)</td><td>state is TOP=[FOO=2,BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>put(TOP/BAR,1)</td><td>state is TOP=[BAR=1]</td></tr>
+     * <tr><td>TOP=[FOO=1]</td><td>delete(TOP/FOO)</td><td>merge(TOP/BAR,1]</td><td>state is TOP=[BAR=1]</td></tr>
+     * </table>
+     *
+     *
+     * <h3>Examples of failure scenarios</h3>
+     *
+     * <h4>Conflict of two transactions</h4>
+     *
+     * This example illustrates two concurrent transactions, which derived from
+     * same initial state of data tree and proposes conflicting modifications.
+     *
+     * <pre>
+     * txA = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
+     * txB = broker.newWriteTransaction(); // allocates new transaction, data tree is empty
+     *
+     * txA.put(CONFIGURATION, PATH, A);    // writes to PATH value A
+     * txB.put(CONFIGURATION, PATH, B)     // writes to PATH value B
+     *
+     * ListenableFuture futureA = txA.commit(); // transaction A is sealed and committed
+     * ListenebleFuture futureB = txB.commit(); // transaction B is sealed and committed
+     * </pre>
+     *
+     * Commit of transaction A will be processed asynchronously and data tree
+     * will be updated to contain value <code>A</code> for <code>PATH</code>.
+     * Returned {@link ListenableFuture} will successfully complete once
+     * state is applied to data tree.
+     *
+     * Commit of Transaction B will fail, because previous transaction also
+     * modified path in a concurrent way. The state introduced by transaction B
+     * will not be applied. Returned {@link ListenableFuture} object will fail
+     * with {@link OptimisticLockFailedException} exception, which indicates to
+     * client that concurrent transaction prevented the submitted transaction from being
+     * applied.
+     *
      * @return Result of the Commit, containing success information or list of
      *         encountered errors, if commit was not successful. The Future
      *         blocks until {@link TransactionStatus#COMMITED} is reached.
-     *         Future will fail with {@link TransactionCommitFailedException}
-     *         if Commit of this transaction failed.
+     *         Future will fail with {@link TransactionCommitFailedException} if
+     *         Commit of this transaction failed. TODO: Usability: Consider
+     *         change from ListenableFuture to
+     *         {@link com.google.common.util.concurrent.CheckedFuture} which
+     *         will throw {@link TransactionCommitFailedException}.
      *
-     * @throws IllegalStateException if the transaction is not {@link TransactionStatus#NEW}
+     * @throws IllegalStateException
+     *             if the transaction is not {@link TransactionStatus#NEW}
      */
     public ListenableFuture<RpcResult<TransactionStatus>> commit();
 
index cf28d067ab541da548abb71d39aa54d96ce4e34e..ea686d966ffa63b60e1cf3cb839db2f2eb034f1e 100644 (file)
       <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>
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ListenerRegistration.java
new file mode 100644 (file)
index 0000000..fda429f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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());
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java
new file mode 100644 (file)
index 0000000..8365328
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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());
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java
new file mode 100644 (file)
index 0000000..b316b9d
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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());
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChain.java
new file mode 100644 (file)
index 0000000..83913fe
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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);
+      }
+    });
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ThreePhaseCommitCohort.java
new file mode 100644 (file)
index 0000000..8e21cb2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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);
+      }
+    });
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistration.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistration.java
new file mode 100644 (file)
index 0000000..d55ad28
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistrationReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseListenerRegistrationReply.java
new file mode 100644 (file)
index 0000000..e195e4b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransaction.java
new file mode 100644 (file)
index 0000000..6809f4b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChain.java
new file mode 100644 (file)
index 0000000..04c422b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionChainReply.java
new file mode 100644 (file)
index 0000000..89fa93b
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CloseTransactionReply.java
new file mode 100644 (file)
index 0000000..4910a3e
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransaction.java
new file mode 100644 (file)
index 0000000..e0cdd3c
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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 {
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChain.java
new file mode 100644 (file)
index 0000000..cdad332
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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 {
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionChainReply.java
new file mode 100644 (file)
index 0000000..49dd9b6
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/CreateTransactionReply.java
new file mode 100644 (file)
index 0000000..4faf9d3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteData.java
new file mode 100644 (file)
index 0000000..384e75a
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DeleteDataReply.java
new file mode 100644 (file)
index 0000000..a3c7305
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeData.java
new file mode 100644 (file)
index 0000000..75d1e95
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/MergeDataReply.java
new file mode 100644 (file)
index 0000000..8e90972
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ModifyData.java
new file mode 100644 (file)
index 0000000..da86088
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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;
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadData.java
new file mode 100644 (file)
index 0000000..2f56a97
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadDataReply.java
new file mode 100644 (file)
index 0000000..52e2c29
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransaction.java
new file mode 100644 (file)
index 0000000..58eef66
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/ReadyTransactionReply.java
new file mode 100644 (file)
index 0000000..48565d4
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListener.java
new file mode 100644 (file)
index 0000000..0123a70
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/RegisterChangeListenerReply.java
new file mode 100644 (file)
index 0000000..ae8bbbd
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/UpdateSchemaContext.java
new file mode 100644 (file)
index 0000000..47f9ea8
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteData.java
new file mode 100644 (file)
index 0000000..1348e65
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/WriteDataReply.java
new file mode 100644 (file)
index 0000000..2a2b4ed
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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 {
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategy.java
new file mode 100644 (file)
index 0000000..a8ab5c4
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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;
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategy.java
new file mode 100644 (file)
index 0000000..f75eb2d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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);
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactory.java
new file mode 100644 (file)
index 0000000..2105379
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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");
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/AbstractActorTest.java
new file mode 100644 (file)
index 0000000..2fe7b69
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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;
+  }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ListenerRegistrationTest.java
new file mode 100644 (file)
index 0000000..0f155ef
--- /dev/null
@@ -0,0 +1,72 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java
new file mode 100644 (file)
index 0000000..b5a341d
--- /dev/null
@@ -0,0 +1,98 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionChainTest.java
new file mode 100644 (file)
index 0000000..bc3a104
--- /dev/null
@@ -0,0 +1,91 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
new file mode 100644 (file)
index 0000000..36633c5
--- /dev/null
@@ -0,0 +1,236 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/DefaultShardStrategyTest.java
new file mode 100644 (file)
index 0000000..d3ba9b1
--- /dev/null
@@ -0,0 +1,14 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/shardstrategy/ShardStrategyFactoryTest.java
new file mode 100644 (file)
index 0000000..2cff981
--- /dev/null
@@ -0,0 +1,29 @@
+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
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/md/cluster/datastore/model/TestModel.java
new file mode 100644 (file)
index 0000000..7a1def9
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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);
+  }
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang b/opendaylight/md-sal/sal-distributed-datastore/src/test/resources/odl-datastore-test.yang
new file mode 100644 (file)
index 0000000..f6d0202
--- /dev/null
@@ -0,0 +1,42 @@
+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
index 2a163d8dbc7334c95a24481d1a1835ffa8496586..5021d070e14a8ce7b45030e9a604092e3c5257eb 100644 (file)
@@ -290,9 +290,8 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
             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();
@@ -421,9 +420,6 @@ final class ResolveDataChangeEventsTask implements Callable<Iterable<ChangeListe
                 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);
index 4ffa6f91b03be92e18e09a6b1c01d5689c338584..803105f2645deec2f61dc11af8e77c3636526c7c 100644 (file)
@@ -7,13 +7,12 @@
  */
 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;
@@ -22,8 +21,8 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 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.
index 0dd25292c2b3810e78fbaf3009f9b3a212f8675a..0bf4b3238dd5f78a3e7b95626bd0d04a2ca8591a 100644 (file)
@@ -25,7 +25,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
index 89695c124a86e57f4ba5c8a8137551d3a7cbbd07..8435884e7b0b1042073eb0397bec07a6007b7932 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager</artifactId>
-      <version>0.5.2-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.8.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
index bd0e43bada99c229fc5041029f7db5a46af2ef5a..2b9dc0cf259ecbb67f01048e030c40ee2ea1a5f2 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-binding-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
 
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager</artifactId>
-      <version>0.5.2-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.8.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-common-util</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remoterpc-connector</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
   </dependencies>
index 84e9d29c72ab80bba8d36e971c45d82ee932f99b..0ffc330f902fe5c402bcfb4762a283c235d890a5 100644 (file)
         <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
     </scm>
 
-    <properties>
-        <jackson.version>2.3.0</jackson.version>
-        <exam.version>3.0.0</exam.version>
-        <url.version>1.5.0</url.version>
-    </properties>
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>commons-codec</groupId>
-                <artifactId>commons-codec</artifactId>
-                <version>1.7</version>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-
 
     <build>
         <plugins>
             <plugin>
                 <groupId>org.ops4j.pax.exam</groupId>
                 <artifactId>maven-paxexam-plugin</artifactId>
-                <version>1.2.4</version>
                 <executions>
                     <execution>
                         <id>generate-config</id>
@@ -53,7 +36,7 @@
                 <plugin>
                     <groupId>org.eclipse.m2e</groupId>
                     <artifactId>lifecycle-mapping</artifactId>
-                    <version>1.0.0</version>
+                    <version>${lifecycle.mapping.version}</version>
                     <configuration>
                         <lifecycleMappingMetadata>
                             <pluginExecutions>
         <dependency>
             <groupId>org.opendaylight.yangtools.thirdparty</groupId>
             <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.tests</groupId>
             <artifactId>sal-remoterpc-connector-test-provider</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.tests</groupId>
             <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-broker-impl</artifactId>
-            <version>1.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.ops4j.pax.exam</groupId>
         <dependency>
             <groupId>org.ops4j.pax.url</groupId>
             <artifactId>pax-url-aether</artifactId>
-            <version>1.5.2</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>equinoxSDK381</groupId>
             <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-core-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-remoterpc-connector</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>containermanager</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.osgi</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools.thirdparty</groupId>
             <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
         </dependency>
 
         <!-- routing table dependencies -->
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>zeromq-routingtable.implementation</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>clustering.services</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.osgi</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal.implementation</artifactId>
-            <version>0.4.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <artifactId>commons-io</artifactId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>containermanager</artifactId>
-            <version>0.5.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.osgi</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>containermanager.it.implementation</artifactId>
-            <version>0.5.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <artifactId>commons-io</artifactId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>clustering.stub</artifactId>
-            <version>0.4.0-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <artifactId>commons-io</artifactId>
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.dependencymanager.shell</artifactId>
-            <version>3.0.1</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.osgi</groupId>
         <dependency>
             <groupId>eclipselink</groupId>
             <artifactId>javax.resource</artifactId>
-            <version>1.5.0.v200906010428</version>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal</artifactId>
-            <version>0.5.1-SNAPSHOT</version>
         </dependency>
         <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>ietf-netconf-monitoring</artifactId>
-          <version>0.2.5-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>yang-ext</artifactId>
-            <version>2013.09.07.3</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools.model</groupId>
             <artifactId>opendaylight-l2-types</artifactId>
-            <version>2013.08.27.3</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-it</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-config</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
 
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-inventory</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-connector-api</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-common-util</artifactId>
-            <version>1.0-SNAPSHOT</version>
         </dependency>
 
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>clustering.services</artifactId>
-            <version>0.4.1-SNAPSHOT</version>
         </dependency>
 
         <dependency>
             <groupId>equinoxSDK381</groupId>
             <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
         </dependency>
 
         <dependency>
         <dependency>
             <groupId>org.zeromq</groupId>
             <artifactId>jeromq</artifactId>
-            <version>0.3.1</version>
         </dependency>
 
         <dependency>
             <groupId>org.opendaylight.yangtools.thirdparty</groupId>
             <artifactId>xtend-lib-osgi</artifactId>
-            <version>2.4.3</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>sal-binding-broker-impl</artifactId>
-            <version>1.0-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
         <dependency>
             <groupId>equinoxSDK381</groupId>
             <artifactId>org.eclipse.osgi</artifactId>
-            <version>3.8.1.v20120830-144521</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>log4j-over-slf4j</artifactId>
-            <version>1.7.2</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-core</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.0.9</version>
         </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-service</artifactId>
-            <version>1.0-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.controller</groupId>
             <artifactId>config-manager</artifactId>
-            <version>0.2.3-SNAPSHOT</version>
             <exclusions>
                 <exclusion>
                     <artifactId>commons-io</artifactId>
         <dependency>
             <groupId>org.opendaylight.controller.model</groupId>
             <artifactId>model-flow-management</artifactId>
-            <version>1.0-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools.thirdparty</groupId>
             <artifactId>antlr4-runtime-osgi-nohead</artifactId>
-            <version>4.0</version>
         </dependency>
     </dependencies>
 </project>
index b041cb430a6eff183ff7ab5a29e4cd0a42bbe838..b681db27fb4df9f53d0364aa30dc422e36f4dae7 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>containermanager</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>commons.northbound</artifactId>
-      <version>0.4.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal</artifactId>
-      <version>0.5.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.tests</groupId>
       <artifactId>sal-remoterpc-connector-test-provider</artifactId>
-      <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.tests</groupId>
       <artifactId>sal-remoterpc-connector-test-consumer</artifactId>
-      <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>sal-remoterpc-connector</artifactId>
-      <version>1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
       <artifactId>org.osgi.core</artifactId>
-      <version>5.0.0</version>
     </dependency>
     <dependency>
       <groupId>junit</groupId>
@@ -98,7 +91,6 @@
       <dependency>
           <groupId>org.opendaylight.controller</groupId>
           <artifactId>remoterpc-routingtable.implementation</artifactId>
-          <version>0.4.1-SNAPSHOT</version>
       </dependency>
       <dependency>
           <groupId>com.google.guava</groupId>
index c2d245badbca059dfbff3d7bdbf2b50ba30efa1d..46f4a2366a29e444623a0dfe525f8914add2a82f 100644 (file)
@@ -17,7 +17,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>sal-core-api</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>
@@ -62,7 +61,6 @@
     <dependency>
       <groupId>org.jboss.resteasy</groupId>
       <artifactId>jaxrs-api</artifactId>
-      <version>3.0.4.Final</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
@@ -80,7 +78,6 @@
     <dependency>
       <groupId>org.glassfish.jersey.test-framework.providers</groupId>
       <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
-      <version>2.4</version>
       <scope>test</scope>
     </dependency>
     <dependency>
index 79a3434c497e2e3773a75cdaf7238f4cbf0a3b97..0c8b4d5a2ada924025aa40ff805d9c4613606e66 100644 (file)
@@ -36,8 +36,6 @@
     <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
-      <version>3.3.2</version>
-      <!--$NO-MVN-MAN-VER$ -->
     </dependency>
 
     <!-- Jax rs -->
index 10a9d6ddadfe2995a310a71440cc6b526a33c85f..8824284785bccea43ca82615b45ba09b66bcc4b7 100644 (file)
@@ -32,7 +32,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.samples.l2switch.md</groupId>
index 2fcb2f6d63ad6805603d0725ce7801b754bbcede..56ed9a07a6481e046e9a39ea9b7bb799cd09faa7 100644 (file)
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster-consumer</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
 
     <dependency>
       <groupId>org.opendaylight.controller.samples</groupId>
       <artifactId>sample-toaster-provider</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.openexi</groupId>
@@ -50,7 +47,6 @@
     <dependency>
       <groupId>equinoxSDK381</groupId>
       <artifactId>org.eclipse.osgi</artifactId>
-      <version>3.8.1.v20120830-144521</version>
       <scope>test</scope>
     </dependency>
     <dependency>
@@ -72,7 +68,6 @@
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index 61c24c6b6413cae9012916bf93001af11fc77f92..57581d100d619064dcb5831c5ea8e590d7670872 100644 (file)
@@ -1,45 +1,92 @@
 <?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&amp;revision=2013-08-27</capability>-->
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:config?module=config&amp;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&amp;revision=2010-10-04</capability>
-                <capability>urn:ietf:params:xml:ns:yang:rpc-context?module=rpc-context&amp;revision=2013-06-17
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&amp;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&amp;revision=2010-09-24
-                </capability>
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28
-                </capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:logback:config?module=config-logging&amp;revision=2013-07-16</capability>
-                <!-- <capability>urn:opendaylight:yang:extension:yang-ext?module=yang-ext&amp;revision=2013-07-09</capability>-->
-                <capability>
-                    urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28
-                </capability>
-                <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
-                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;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&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom?module=opendaylight-md-sal-dom&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:impl?module=opendaylight-sal-dom-broker-impl&amp;revision=2013-10-28</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:common?module=opendaylight-md-sal-common&amp;revision=2013-10-28</capability>
 
+                <!-- Toaster capabilities -->
+                <capability>http://netconfcentral.org/ns/toaster?module=toaster&amp;revision=2009-11-20</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:kitchen-service:impl?module=kitchen-service-impl&amp;revision=2014-01-31</capability>
+                <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&amp;revision=2014-01-31</capability>
+
+            </required-capabilities>
+        </snapshot>
     </snapshots>
 </persisted-snapshots>
index a51f6c2f9f0eb6669ace2e8febe1404f8189df51..2c8571ca64369c80748ee5d1b157a39017c1db86 100644 (file)
@@ -28,7 +28,6 @@
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
-      <version>2.4</version>
     </dependency>
     <dependency>
       <groupId>equinoxSDK381</groupId>
index 55244d3c902015f0b5e6247a079bb34520459702..fe1813a19943dfe7f3446b55f9c49b1986df6729 100644 (file)
@@ -34,7 +34,6 @@
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
-      <version>1.1-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
index 815acec5e789cd7d491e5783886492713141405b..a15047224bfbd91d46bb91f731ef3eea34d61c47 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>ietf-netconf-monitoring-extension</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
index f46d14903323ff8f891da7ff025d5e50cc926c1b..bf27ed6f4dbadab127dc4e3e876676018df2a180 100644 (file)
@@ -72,7 +72,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index c60506ef447d821d5458dbb399c30a1ab0e94325..c6544466d4ea2ae49904ce1787adb4823070d166 100644 (file)
@@ -19,7 +19,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>ietf-netconf-monitoring-extension</artifactId>
-      <version>${project.version}</version>
     </dependency>
     <!-- compile dependencies -->
     <dependency>
@@ -81,7 +80,6 @@
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
-      <version>${project.version}</version>
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.impl.osgi.NetconfImplActivator</Bundle-Activator>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index c40dfe7fc32208c73251c9a483d7f5feaed48eaf..0e9589d2d21b0bde118440a1a0c683e1bedf3fd5 100644 (file)
@@ -10,9 +10,6 @@
 
   <artifactId>netconf-it</artifactId>
   <name>${project.artifactId}</name>
-  <properties>
-    <tinybundles.version>2.0.0</tinybundles.version>
-  </properties>
 
   <dependencies>
     <dependency>
       <plugin>
         <groupId>org.ops4j.pax.exam</groupId>
         <artifactId>maven-paxexam-plugin</artifactId>
-        <version>1.2.4</version>
         <executions>
           <execution>
             <id>generate-config</id>
index 87056db06c23aef8de11c2fe80d919fffbade208..cf4ec213c296bbd103dfe75f7650670b008aa041 100644 (file)
@@ -12,7 +12,6 @@ import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelPromise;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -20,6 +19,8 @@ import java.util.LinkedList;
 import java.util.Queue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -27,6 +28,8 @@ import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.V
  * pipeline.
  */
 public class SshClientAdapter implements Runnable {
+    private static final Logger logger = LoggerFactory.getLogger(SshClientAdapter.class);
+
     private static final int BUFFER_SIZE = 1024;
 
     private final SshClient sshClient;
@@ -49,8 +52,15 @@ public class SshClientAdapter implements Runnable {
     }
 
     public void run() {
+        SshSession session;
+        try {
+            session = sshClient.openSession();
+        } catch (IOException e) {
+            logger.error("Cannot establish session", e);
+            sshClient.close();
+            return;
+        }
         try {
-            SshSession session = sshClient.openSession();
             invoker.invoke(session);
             InputStream stdOut = session.getStdout();
             session.getStderr();
@@ -82,7 +92,7 @@ public class SshClientAdapter implements Runnable {
             // Netty closed connection prematurely.
             // Just pass and move on.
         } catch (Exception e) {
-            throw new IllegalStateException(e);
+            logger.error("Unexpected exception", e);
         } finally {
             sshClient.close();
 
index 2a3eeb21a8ced14c43565e1c3dd9443b9ef85292..ba65b9ef34cf597aedadf1f5fa5afe6bb5cc646a 100644 (file)
@@ -93,6 +93,7 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         synchronized(lock) {
             this.bb.discardReadBytes();
             this.bb.writeBytes((ByteBuf) o);
+            ((ByteBuf) o).release();
             lock.notifyAll();
         }
     }
index cbd3efc57f7bc0abfd27e77bec63334087265fab..8a2387d2c1d450df3e0a9bc964c435e84688844a 100644 (file)
@@ -56,7 +56,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.ssh.osgi.NetconfSSHActivator</Bundle-Activator>
@@ -81,7 +80,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>
index 65da6e987e1944aa6cac0d3f38c8de72af68d7f8..3c4ee4728d9f311664f2c04e1b7c1d4f2c278580 100644 (file)
@@ -47,7 +47,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Bundle-Activator>org.opendaylight.controller.netconf.tcp.osgi.NetconfTCPActivator</Bundle-Activator>
index f3b35ce3ceaee5b6b26aee7ebac6892e16ef47b6..df4d389705b29eda03cb3e88a553ba14902720f3 100644 (file)
@@ -53,7 +53,6 @@
       <plugin>
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
-        <version>2.3.7</version>
         <configuration>
           <instructions>
             <Import-Package>com.google.common.base, com.google.common.collect, io.netty.channel,
@@ -69,7 +68,6 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-jar-plugin</artifactId>
-        <version>2.4</version>
         <executions>
           <execution>
             <goals>