Add exists method on DOMStoreReadTransaction and DOMDataReadTransaction 43/9843/10
authorMoiz Raja <moraja@cisco.com>
Sun, 10 Aug 2014 23:18:33 +0000 (16:18 -0700)
committerMoiz Raja <moraja@cisco.com>
Tue, 12 Aug 2014 17:18:29 +0000 (10:18 -0700)
Introducing this API does not impact clients as it is mostly internal.

One reason for adding this API is because of ensureParentsByMerge used in a couple of places
which keeps checking if a parent node exists by reading a node to figure out if it exists. This is
fine for the InMemoryDataStore but it can be terrible in a distributed data store where the shard
which contains the data is remote. All sorts of overhead is associated with a remote read including
serialization which can actually be pretty expensive.

Change-Id: Ib5be5f6dc60be683d7a04c81dad08c56cd5681f4
Signed-off-by: Moiz Raja <moraja@cisco.com>
26 files changed:
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractReadWriteTransaction.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/test/DataBrokerTestCustomizer.java
opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/protobuff/messages/transaction/ShardTransactionMessages.java
opendaylight/md-sal/sal-clustering-commons/src/main/resources/ShardTransaction.proto
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardReadWriteTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/TransactionProxy.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionFailureTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTransactionTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/TransactionProxyTest.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMDataReadTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadOnlyTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/DOMForwardedReadWriteTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BackwardsCompatibleMountPoint.java
opendaylight/md-sal/sal-dom-spi/src/main/java/org/opendaylight/controller/sal/core/spi/data/DOMStoreReadTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedReadWriteTransaction.java
opendaylight/md-sal/sal-inmemory-datastore/src/test/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDataStoreTest.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadOnlyTx.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/NetconfDeviceReadWriteTx.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/BrokerFacade.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/BrokerFacadeTest.java

index 5ced7bae9fd3459b494a50013e297aacd8b3425f..8fbc118a16efcc59b74b4016743a8ff87ee24f7a 100644 (file)
@@ -7,22 +7,19 @@
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
 
 public class AbstractReadWriteTransaction extends AbstractWriteTransaction<DOMDataReadWriteTransaction> {
 
@@ -50,15 +47,15 @@ public class AbstractReadWriteTransaction extends AbstractWriteTransaction<DOMDa
             org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier currentPath = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(
                     currentArguments);
 
-            final Optional<NormalizedNode<?, ?>> d;
+            final Boolean exists;
             try {
-                d = getDelegate().read(store, currentPath).get();
-            } catch (InterruptedException | ExecutionException e) {
+                exists = getDelegate().exists(store, currentPath).checkedGet();
+            } catch (ReadFailedException e) {
                 LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
                 throw new IllegalStateException("Failed to read pre-existing data", e);
             }
 
-            if (!d.isPresent() && iterator.hasNext()) {
+            if (!exists && iterator.hasNext()) {
                 getDelegate().merge(store, currentPath, currentOp.createDefault(currentArg));
             }
         }
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/ForwardedBackwardsCompatibleDataBrokerTest.java
new file mode 100644 (file)
index 0000000..f91e356
--- /dev/null
@@ -0,0 +1,72 @@
+package org.opendaylight.controller.md.sal.binding.impl.test;
+
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
+import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
+import org.opendaylight.controller.md.sal.binding.test.DataBrokerTestCustomizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import java.util.concurrent.ExecutionException;
+
+import static junit.framework.TestCase.assertNotNull;
+
+public class ForwardedBackwardsCompatibleDataBrokerTest extends
+    AbstractSchemaAwareTest {
+
+    private DataBrokerTestCustomizer testCustomizer;
+    private ForwardedBackwardsCompatibleDataBroker dataBroker;
+    private DOMDataBroker domBroker;
+
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+    private static final TopLevelListKey TOP_LIST_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> NODE_PATH = TOP_PATH.child(TopLevelList.class, TOP_LIST_KEY);
+    private static final TopLevelList NODE = new TopLevelListBuilder().setKey(TOP_LIST_KEY).build();
+
+    protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() {
+        return new DataBrokerTestCustomizer();
+    }
+
+    @Override
+    protected void setupWithSchema(final SchemaContext context) {
+        testCustomizer = createDataBrokerTestCustomizer();
+
+        domBroker = testCustomizer.createDOMDataBroker();
+        dataBroker = testCustomizer.createBackwardsCompatibleDataBroker();
+        testCustomizer.updateSchema(context);
+    }
+
+
+    /**
+     * The purpose of this test is to exercise the backwards compatible broker
+     * <p>
+     * This test tries to execute the code which ensures that the parents
+     * for a given node get automatically created.
+     *
+     * @see org.opendaylight.controller.md.sal.binding.impl.AbstractReadWriteTransaction#ensureParentsByMerge(org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.binding.InstanceIdentifier)
+     */
+    @Test
+    public void test() throws InterruptedException, ExecutionException {
+        DataModificationTransaction writeTx =
+            dataBroker.beginTransaction();
+
+        writeTx.putOperationalData(NODE_PATH, NODE);
+
+        writeTx.commit();
+
+        // TOP_PATH should exist as it is the parent of NODE_PATH
+        DataObject object = dataBroker.readOperationalData(TOP_PATH);
+
+        assertNotNull(object);
+
+    }
+
+
+}
index 666c819c82ce45ad55e8bf4f3c83c6ad7da349cd..60eec55ca55df3df580318e5608ea08f1a319801 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.binding.test;
 import javassist.ClassPool;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.impl.ForwardedBackwardsCompatibleDataBroker;
 import org.opendaylight.controller.md.sal.binding.impl.ForwardedBindingDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
@@ -71,6 +72,11 @@ public class DataBrokerTestCustomizer {
         return new ForwardedBindingDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService());
     }
 
+    public ForwardedBackwardsCompatibleDataBroker createBackwardsCompatibleDataBroker() {
+        return new ForwardedBackwardsCompatibleDataBroker(getDOMDataBroker(), getMappingService(), getSchemaService(), MoreExecutors.sameThreadExecutor());
+    }
+
+
     private SchemaService getSchemaService() {
         return schemaService;
     }
index 33ac9f6ca1c7c8115071d07549999b848fab2d3e..bdd66d3aba25e4766960ed0611362cf813d5360c 100644 (file)
@@ -6579,6 +6579,933 @@ public final class ShardTransactionMessages {
     // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.MergeDataReply)
   }
 
+  public interface DataExistsOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    boolean hasInstanceIdentifierPathArguments();
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments();
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.DataExists}
+   */
+  public static final class DataExists extends
+      com.google.protobuf.GeneratedMessage
+      implements DataExistsOrBuilder {
+    // Use DataExists.newBuilder() to construct.
+    private DataExists(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private DataExists(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final DataExists defaultInstance;
+    public static DataExists getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public DataExists getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private DataExists(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = instanceIdentifierPathArguments_.toBuilder();
+              }
+              instanceIdentifierPathArguments_ = input.readMessage(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(instanceIdentifierPathArguments_);
+                instanceIdentifierPathArguments_ = subBuilder.buildPartial();
+              }
+              bitField0_ |= 0x00000001;
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<DataExists> PARSER =
+        new com.google.protobuf.AbstractParser<DataExists>() {
+      public DataExists parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new DataExists(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<DataExists> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
+    public static final int INSTANCEIDENTIFIERPATHARGUMENTS_FIELD_NUMBER = 1;
+    private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierPathArguments_;
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    public boolean hasInstanceIdentifierPathArguments() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments() {
+      return instanceIdentifierPathArguments_;
+    }
+    /**
+     * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+     */
+    public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder() {
+      return instanceIdentifierPathArguments_;
+    }
+
+    private void initFields() {
+      instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasInstanceIdentifierPathArguments()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!getInstanceIdentifierPathArguments().isInitialized()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeMessage(1, instanceIdentifierPathArguments_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(1, instanceIdentifierPathArguments_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.DataExists}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getInstanceIdentifierPathArgumentsFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+        } else {
+          instanceIdentifierPathArgumentsBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists getDefaultInstanceForType() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists build() {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists buildPartial() {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists result = new org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          result.instanceIdentifierPathArguments_ = instanceIdentifierPathArguments_;
+        } else {
+          result.instanceIdentifierPathArguments_ = instanceIdentifierPathArgumentsBuilder_.build();
+        }
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists) {
+          return mergeFrom((org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists other) {
+        if (other == org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists.getDefaultInstance()) return this;
+        if (other.hasInstanceIdentifierPathArguments()) {
+          mergeInstanceIdentifierPathArguments(other.getInstanceIdentifierPathArguments());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasInstanceIdentifierPathArguments()) {
+          
+          return false;
+        }
+        if (!getInstanceIdentifierPathArguments().isInitialized()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExists) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;
+      private org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> instanceIdentifierPathArgumentsBuilder_;
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public boolean hasInstanceIdentifierPathArguments() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier getInstanceIdentifierPathArguments() {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          return instanceIdentifierPathArguments_;
+        } else {
+          return instanceIdentifierPathArgumentsBuilder_.getMessage();
+        }
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public Builder setInstanceIdentifierPathArguments(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          instanceIdentifierPathArguments_ = value;
+          onChanged();
+        } else {
+          instanceIdentifierPathArgumentsBuilder_.setMessage(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public Builder setInstanceIdentifierPathArguments(
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder builderForValue) {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          instanceIdentifierPathArguments_ = builderForValue.build();
+          onChanged();
+        } else {
+          instanceIdentifierPathArgumentsBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public Builder mergeInstanceIdentifierPathArguments(org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier value) {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001) &&
+              instanceIdentifierPathArguments_ != org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance()) {
+            instanceIdentifierPathArguments_ =
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.newBuilder(instanceIdentifierPathArguments_).mergeFrom(value).buildPartial();
+          } else {
+            instanceIdentifierPathArguments_ = value;
+          }
+          onChanged();
+        } else {
+          instanceIdentifierPathArgumentsBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000001;
+        return this;
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public Builder clearInstanceIdentifierPathArguments() {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          instanceIdentifierPathArguments_ = org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.getDefaultInstance();
+          onChanged();
+        } else {
+          instanceIdentifierPathArgumentsBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder getInstanceIdentifierPathArgumentsBuilder() {
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return getInstanceIdentifierPathArgumentsFieldBuilder().getBuilder();
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      public org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder getInstanceIdentifierPathArgumentsOrBuilder() {
+        if (instanceIdentifierPathArgumentsBuilder_ != null) {
+          return instanceIdentifierPathArgumentsBuilder_.getMessageOrBuilder();
+        } else {
+          return instanceIdentifierPathArguments_;
+        }
+      }
+      /**
+       * <code>required .org.opendaylight.controller.mdsal.InstanceIdentifier instanceIdentifierPathArguments = 1;</code>
+       */
+      private com.google.protobuf.SingleFieldBuilder<
+          org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder> 
+          getInstanceIdentifierPathArgumentsFieldBuilder() {
+        if (instanceIdentifierPathArgumentsBuilder_ == null) {
+          instanceIdentifierPathArgumentsBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifier.Builder, org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages.InstanceIdentifierOrBuilder>(
+                  instanceIdentifierPathArguments_,
+                  getParentForChildren(),
+                  isClean());
+          instanceIdentifierPathArguments_ = null;
+        }
+        return instanceIdentifierPathArgumentsBuilder_;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DataExists)
+    }
+
+    static {
+      defaultInstance = new DataExists(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DataExists)
+  }
+
+  public interface DataExistsReplyOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required bool exists = 1;
+    /**
+     * <code>required bool exists = 1;</code>
+     */
+    boolean hasExists();
+    /**
+     * <code>required bool exists = 1;</code>
+     */
+    boolean getExists();
+  }
+  /**
+   * Protobuf type {@code org.opendaylight.controller.mdsal.DataExistsReply}
+   */
+  public static final class DataExistsReply extends
+      com.google.protobuf.GeneratedMessage
+      implements DataExistsReplyOrBuilder {
+    // Use DataExistsReply.newBuilder() to construct.
+    private DataExistsReply(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private DataExistsReply(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final DataExistsReply defaultInstance;
+    public static DataExistsReply getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public DataExistsReply getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private DataExistsReply(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              exists_ = input.readBool();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<DataExistsReply> PARSER =
+        new com.google.protobuf.AbstractParser<DataExistsReply>() {
+      public DataExistsReply parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new DataExistsReply(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<DataExistsReply> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required bool exists = 1;
+    public static final int EXISTS_FIELD_NUMBER = 1;
+    private boolean exists_;
+    /**
+     * <code>required bool exists = 1;</code>
+     */
+    public boolean hasExists() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required bool exists = 1;</code>
+     */
+    public boolean getExists() {
+      return exists_;
+    }
+
+    private void initFields() {
+      exists_ = false;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasExists()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeBool(1, exists_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBoolSize(1, exists_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code org.opendaylight.controller.mdsal.DataExistsReply}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReplyOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.class, org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.Builder.class);
+      }
+
+      // Construct using org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        exists_ = false;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply getDefaultInstanceForType() {
+        return org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.getDefaultInstance();
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply build() {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply buildPartial() {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply result = new org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.exists_ = exists_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply) {
+          return mergeFrom((org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply other) {
+        if (other == org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply.getDefaultInstance()) return this;
+        if (other.hasExists()) {
+          setExists(other.getExists());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasExists()) {
+          
+          return false;
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.DataExistsReply) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required bool exists = 1;
+      private boolean exists_ ;
+      /**
+       * <code>required bool exists = 1;</code>
+       */
+      public boolean hasExists() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required bool exists = 1;</code>
+       */
+      public boolean getExists() {
+        return exists_;
+      }
+      /**
+       * <code>required bool exists = 1;</code>
+       */
+      public Builder setExists(boolean value) {
+        bitField0_ |= 0x00000001;
+        exists_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required bool exists = 1;</code>
+       */
+      public Builder clearExists() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        exists_ = false;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:org.opendaylight.controller.mdsal.DataExistsReply)
+    }
+
+    static {
+      defaultInstance = new DataExistsReply(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:org.opendaylight.controller.mdsal.DataExistsReply)
+  }
+
   private static com.google.protobuf.Descriptors.Descriptor
     internal_static_org_opendaylight_controller_mdsal_CloseTransaction_descriptor;
   private static
@@ -6649,6 +7576,16 @@ public final class ShardTransactionMessages {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_org_opendaylight_controller_mdsal_MergeDataReply_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -6683,10 +7620,13 @@ public final class ShardTransactionMessages {
       "thArguments\030\001 \002(\01325.org.opendaylight.con" +
       "troller.mdsal.InstanceIdentifier\022?\n\016norm" +
       "alizedNode\030\002 \002(\0132\'.org.opendaylight.cont" +
-      "roller.mdsal.Node\"\020\n\016MergeDataReplyBV\n:o" +
-      "rg.opendaylight.controller.protobuff.mes" +
-      "sages.transactionB\030ShardTransactionMessa" +
-      "ges"
+      "roller.mdsal.Node\"\020\n\016MergeDataReply\"l\n\nD" +
+      "ataExists\022^\n\037instanceIdentifierPathArgum" +
+      "ents\030\001 \002(\01325.org.opendaylight.controller" +
+      ".mdsal.InstanceIdentifier\"!\n\017DataExistsR" +
+      "eply\022\016\n\006exists\030\001 \002(\010BV\n:org.opendaylight",
+      ".controller.protobuff.messages.transacti" +
+      "onB\030ShardTransactionMessages"
     };
     com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
       new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@@ -6777,6 +7717,18 @@ public final class ShardTransactionMessages {
             com.google.protobuf.GeneratedMessage.FieldAccessorTable(
               internal_static_org_opendaylight_controller_mdsal_MergeDataReply_descriptor,
               new java.lang.String[] { });
+          internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor =
+            getDescriptor().getMessageTypes().get(14);
+          internal_static_org_opendaylight_controller_mdsal_DataExists_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_DataExists_descriptor,
+              new java.lang.String[] { "InstanceIdentifierPathArguments", });
+          internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor =
+            getDescriptor().getMessageTypes().get(15);
+          internal_static_org_opendaylight_controller_mdsal_DataExistsReply_fieldAccessorTable = new
+            com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+              internal_static_org_opendaylight_controller_mdsal_DataExistsReply_descriptor,
+              new java.lang.String[] { "Exists", });
           return null;
         }
       };
index 4177bd7a052c244385e75df38dcf0fa31523b67c..63b75ac430f9bbbaca2ad8d1ecb7c63f0cff37d2 100644 (file)
@@ -65,3 +65,11 @@ required Node normalizedNode =2;
 message MergeDataReply{
 
 }
+
+message DataExists {
+  required InstanceIdentifier instanceIdentifierPathArguments = 1;
+}
+
+message DataExistsReply {
+  required bool exists = 1;
+}
index 7a18fca100f027b2bfad23b0433eeb91eab06484..1328d466f34b6fff82a91b98379cd815b488155c 100644 (file)
@@ -16,6 +16,7 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
@@ -44,7 +45,9 @@ public class ShardReadTransaction extends ShardTransaction {
   @Override
   public void handleReceive(Object message) throws Exception {
     if (ReadData.SERIALIZABLE_CLASS.equals(message.getClass())) {
-      readData(transaction,ReadData.fromSerializable(message));
+        readData(transaction, ReadData.fromSerializable(message));
+    } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
+        dataExists(transaction, DataExists.fromSerializable(message));
     } else {
       super.handleReceive(message);
     }
index 92fb39308357cd63acf2d7810a321b1081b3ace1..97bb196f9fc36b9635e906bb654fafc68b2538c4 100644 (file)
@@ -16,6 +16,7 @@ import akka.event.Logging;
 import akka.event.LoggingAdapter;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
@@ -55,6 +56,8 @@ public class ShardReadWriteTransaction extends ShardTransaction {
       deleteData(transaction,DeleteData.fromSerizalizable(message));
     } else if (ReadyTransaction.SERIALIZABLE_CLASS.equals(message.getClass())) {
       readyTransaction(transaction,new ReadyTransaction());
+    } else if(DataExists.SERIALIZABLE_CLASS.equals(message.getClass())) {
+        dataExists(transaction, DataExists.fromSerializable(message));
     }else {
       super.handleReceive(message);
     }
index 1ffe5ca40262ef630a247dca0ce8e46e126f3c34..360a10722c06df2c3e357631b43d89eac801a3d3 100644 (file)
@@ -14,9 +14,11 @@ 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 com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
+import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
@@ -183,28 +185,38 @@ public abstract class ShardTransaction extends AbstractUntypedActor {
     final ActorRef sender = getSender();
     final ActorRef self = getSelf();
     final YangInstanceIdentifier path = message.getPath();
-    final ListenableFuture<Optional<NormalizedNode<?, ?>>> future =
-        transaction.read(path);
+    final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> future =
+          transaction.read(path);
 
-    future.addListener(new Runnable() {
+      future.addListener(new Runnable() {
       @Override
       public void run() {
         try {
-          Optional<NormalizedNode<?, ?>> optional = future.get();
+          Optional<NormalizedNode<?, ?>> optional = future.checkedGet();
           if (optional.isPresent()) {
             sender.tell(new ReadDataReply(schemaContext,optional.get()).toSerializable(), self);
           } else {
             sender.tell(new ReadDataReply(schemaContext,null).toSerializable(), self);
           }
         } catch (Exception e) {
-            sender.tell(new akka.actor.Status.Failure(new ReadFailedException( "An Exception occurred  when reading data from path : "
-                + path.toString(),e)),self);
+            sender.tell(new akka.actor.Status.Failure(e),self);
         }
 
       }
     }, getContext().dispatcher());
   }
 
+    protected void dataExists(DOMStoreReadTransaction transaction, DataExists message) {
+        final YangInstanceIdentifier path = message.getPath();
+
+        try {
+            Boolean exists = transaction.exists(path).checkedGet();
+            getSender().tell(new DataExistsReply(exists).toSerializable(), getSelf());
+        } catch (ReadFailedException e) {
+            getSender().tell(new akka.actor.Status.Failure(e),getSelf());
+        }
+
+    }
 
   protected void writeData(DOMStoreWriteTransaction transaction, WriteData message) {
     modification.addModification(
index 5f9f1f83c4dbf15b38ea5a3d13d534354b4527e2..95862ae9d93670de67dbdd8bd99074a9ba49e8b8 100644 (file)
@@ -23,6 +23,8 @@ import org.opendaylight.controller.cluster.datastore.identifiers.TransactionIden
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CreateTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
+import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
@@ -113,6 +115,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
         return transactionContext(path).readData(path);
     }
 
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        YangInstanceIdentifier path) {
+        LOG.debug("txn {} exists {}", identifier, path);
+
+        createTransactionIfMissing(actorContext, path);
+
+        return transactionContext(path).dataExists(path);
+    }
+
     @Override
     public void write(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
 
@@ -243,13 +254,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
                 final YangInstanceIdentifier path);
 
         void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data);
+
+        CheckedFuture<Boolean, ReadFailedException> dataExists(YangInstanceIdentifier path);
     }
 
 
-    private class TransactionContextImpl implements TransactionContext{
+    private class TransactionContextImpl implements TransactionContext {
         private final String shardName;
         private final String actorPath;
-        private final ActorSelection  actor;
+        private final ActorSelection actor;
 
 
         private TransactionContextImpl(String shardName, String actorPath,
@@ -267,7 +280,7 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             return actor;
         }
 
-        @Override public String getResolvedCohortPath(String cohortPath){
+        @Override public String getResolvedCohortPath(String cohortPath) {
             return actorContext.resolvePath(actorPath, cohortPath);
         }
 
@@ -288,38 +301,76 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             getActor().tell(new DeleteData(path).toSerializable(), null);
         }
 
-        @Override public void mergeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data){
-            getActor().tell(new MergeData(path, data, schemaContext).toSerializable(), null);
+        @Override public void mergeData(YangInstanceIdentifier path,
+            NormalizedNode<?, ?> data) {
+            getActor()
+                .tell(new MergeData(path, data, schemaContext).toSerializable(),
+                    null);
         }
 
-        @Override public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
-                final YangInstanceIdentifier path) {
-
-            Callable<Optional<NormalizedNode<?,?>>> call = new Callable<Optional<NormalizedNode<?,?>>>() {
+        @Override
+        public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> readData(
+            final YangInstanceIdentifier path) {
 
-                @Override public Optional<NormalizedNode<?,?>> call() throws Exception {
-                    Object response = actorContext
-                        .executeRemoteOperation(getActor(), new ReadData(path).toSerializable(),
-                            ActorContext.ASK_DURATION);
-                    if(response.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)){
-                        ReadDataReply reply = ReadDataReply.fromSerializable(schemaContext,path, response);
-                        if(reply.getNormalizedNode() == null){
-                            return Optional.absent();
+            Callable<Optional<NormalizedNode<?, ?>>> call =
+                new Callable<Optional<NormalizedNode<?, ?>>>() {
+
+                    @Override public Optional<NormalizedNode<?, ?>> call()
+                        throws Exception {
+                        Object response = actorContext
+                            .executeRemoteOperation(getActor(),
+                                new ReadData(path).toSerializable(),
+                                ActorContext.ASK_DURATION);
+                        if (response.getClass()
+                            .equals(ReadDataReply.SERIALIZABLE_CLASS)) {
+                            ReadDataReply reply = ReadDataReply
+                                .fromSerializable(schemaContext, path,
+                                    response);
+                            if (reply.getNormalizedNode() == null) {
+                                return Optional.absent();
+                            }
+                            return Optional.<NormalizedNode<?, ?>>of(
+                                reply.getNormalizedNode());
                         }
-                        return Optional.<NormalizedNode<?,?>>of(reply.getNormalizedNode());
-                    }
 
-                    return Optional.absent();
-                }
-            };
+                        throw new ReadFailedException("Read Failed " + path);
+                    }
+                };
 
-            return MappingCheckedFuture.create(executor.submit(call), ReadFailedException.MAPPER);
+            return MappingCheckedFuture
+                .create(executor.submit(call), ReadFailedException.MAPPER);
         }
 
-        @Override public void writeData(YangInstanceIdentifier path, NormalizedNode<?, ?> data) {
-            getActor().tell(new WriteData(path, data, schemaContext).toSerializable(), null);
+        @Override public void writeData(YangInstanceIdentifier path,
+            NormalizedNode<?, ?> data) {
+            getActor()
+                .tell(new WriteData(path, data, schemaContext).toSerializable(),
+                    null);
         }
 
+        @Override public CheckedFuture<Boolean, ReadFailedException> dataExists(
+            final YangInstanceIdentifier path) {
+
+            Callable<Boolean> call = new Callable<Boolean>() {
+
+                @Override public Boolean call() throws Exception {
+                    Object o = actorContext.executeRemoteOperation(getActor(),
+                        new DataExists(path).toSerializable(),
+                        ActorContext.ASK_DURATION
+                    );
+
+
+                    if (DataExistsReply.SERIALIZABLE_CLASS
+                        .equals(o.getClass())) {
+                        return DataExistsReply.fromSerializable(o).exists();
+                    }
+
+                    throw new ReadFailedException("Exists Failed " + path);
+                }
+            };
+            return MappingCheckedFuture
+                .create(executor.submit(call), ReadFailedException.MAPPER);
+        }
     }
 
     private class NoOpTransactionContext implements TransactionContext {
@@ -374,6 +425,15 @@ public class TransactionProxy implements DOMStoreReadWriteTransaction {
             NormalizedNode<?, ?> data) {
             LOG.warn("txn {} writeData called path = {}", identifier, path);
         }
+
+        @Override public CheckedFuture<Boolean, ReadFailedException> dataExists(
+            YangInstanceIdentifier path) {
+            LOG.warn("txn {} dataExists called path = {}", identifier, path);
+
+            // Returning false instead of an exception to keep this aligned with
+            // read
+            return Futures.immediateCheckedFuture(false);
+        }
     }
 
 
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExists.java
new file mode 100644 (file)
index 0000000..d52daab
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.cluster.datastore.util.InstanceIdentifierUtils;
+import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class DataExists implements SerializableMessage{
+
+    public static final Class SERIALIZABLE_CLASS = ShardTransactionMessages.DataExists.class;
+
+    private final YangInstanceIdentifier path;
+
+    public DataExists(YangInstanceIdentifier path) {
+        this.path = path;
+    }
+
+    public YangInstanceIdentifier getPath() {
+        return path;
+    }
+
+    @Override public Object toSerializable() {
+        return ShardTransactionMessages.DataExists.newBuilder()
+            .setInstanceIdentifierPathArguments(
+                InstanceIdentifierUtils.toSerializable(path)).build();
+    }
+
+    public static DataExists fromSerializable(Object serializable){
+        ShardTransactionMessages.DataExists o = (ShardTransactionMessages.DataExists) serializable;
+        return new DataExists(InstanceIdentifierUtils.fromSerializable(o.getInstanceIdentifierPathArguments()));
+    }
+
+}
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/messages/DataExistsReply.java
new file mode 100644 (file)
index 0000000..04fafa1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.protobuff.messages.transaction.ShardTransactionMessages;
+
+public class DataExistsReply implements SerializableMessage{
+
+
+    public static final Class SERIALIZABLE_CLASS = ShardTransactionMessages.DataExistsReply.class;
+
+    private final boolean exists;
+
+    public DataExistsReply(boolean exists) {
+        this.exists = exists;
+    }
+
+    public boolean exists() {
+        return exists;
+    }
+
+    @Override public Object toSerializable() {
+        return ShardTransactionMessages.DataExistsReply.newBuilder()
+            .setExists(exists).build();
+    }
+
+    public static DataExistsReply fromSerializable(Object serializable){
+        ShardTransactionMessages.DataExistsReply o = (ShardTransactionMessages.DataExistsReply) serializable;
+        return new DataExistsReply(o.getExists());
+    }
+
+}
index 0f9e771ab4d13781c99a52ee293981dbd82699af..02ceee82e05d2f78981bb89f3e1c6e9a3b4e1f61 100644 (file)
@@ -122,6 +122,41 @@ public class ShardTransactionFailureTest extends AbstractActorTest {
         Await.result(future, Duration.Zero());
 
 
+    }
+
+    @Test(expected = ReadFailedException.class)
+    public void testNegativeExistsWithReadWriteOnlyTransactionClosed()
+        throws Throwable {
+
+        final ActorRef shard =
+            getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+        final Props props =
+            ShardTransaction.props(store.newReadWriteTransaction(), shard,
+                TestModel.createTestContext());
+
+        final TestActorRef<ShardTransaction> subject = TestActorRef
+            .create(getSystem(), props,
+                "testNegativeExistsWithReadWriteOnlyTransactionClosed");
+
+        ShardTransactionMessages.DataExists dataExists =
+            ShardTransactionMessages.DataExists.newBuilder()
+                .setInstanceIdentifierPathArguments(
+                    NormalizedNodeMessages.InstanceIdentifier.newBuilder()
+                        .build()
+                ).build();
+
+        Future<Object> future =
+            akka.pattern.Patterns.ask(subject, dataExists, 3000);
+        assertTrue(future.isCompleted());
+        Await.result(future, Duration.Zero());
+
+        ((ShardReadWriteTransaction) subject.underlyingActor())
+            .forUnitTestOnlyExplicitTransactionClose();
+
+        future = akka.pattern.Patterns.ask(subject, dataExists, 3000);
+        Await.result(future, Duration.Zero());
+
+
     }
 
     @Test(expected = IllegalStateException.class)
index a2273f61f8e488d0992dd582f441edb137d0b39a..78895b2366a96aa7e2c85aaa97f2b7a6218a92a2 100644 (file)
@@ -13,6 +13,8 @@ import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageEx
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
+import org.opendaylight.controller.cluster.datastore.messages.DataExists;
+import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
@@ -142,6 +144,90 @@ public class ShardTransactionTest extends AbstractActorTest {
         }};
     }
 
+    @Test
+    public void testOnReceiveDataExistsPositive() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            final Props props =
+                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
+            final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive");
+
+            new Within(duration("1 seconds")) {
+                @Override
+                protected void run() {
+
+                    subject.tell(
+                        new DataExists(YangInstanceIdentifier.builder().build()).toSerializable(),
+                        getRef());
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                        // do not put code outside this method, will run afterwards
+                        @Override
+                        protected String match(Object in) {
+                            if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
+                                if (DataExistsReply.fromSerializable(in)
+                                    .exists()) {
+                                    return "match";
+                                }
+                                return null;
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertEquals("match", out);
+
+                    expectNoMsg();
+                }
+
+
+            };
+        }};
+    }
+
+    @Test
+    public void testOnReceiveDataExistsNegative() throws Exception {
+        new JavaTestKit(getSystem()) {{
+            final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
+            final Props props =
+                ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
+            final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
+
+            new Within(duration("1 seconds")) {
+                @Override
+                protected void run() {
+
+                    subject.tell(
+                        new DataExists(TestModel.TEST_PATH).toSerializable(),
+                        getRef());
+
+                    final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
+                        // do not put code outside this method, will run afterwards
+                        @Override
+                        protected String match(Object in) {
+                            if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
+                                if (!DataExistsReply.fromSerializable(in)
+                                    .exists()) {
+                                    return "match";
+                                }
+                                return null;
+                            } else {
+                                throw noMatch();
+                            }
+                        }
+                    }.get(); // this extracts the received message
+
+                    assertEquals("match", out);
+
+                    expectNoMsg();
+                }
+
+
+            };
+        }};
+    }
+
     private void assertModification(final ActorRef subject,
         final Class<? extends Modification> modificationType) {
         new JavaTestKit(getSystem()) {{
index 0cd029c2ffb2da4c093ede214ca037d5a5a345dc..62052f38ab89b6962dc31622332f85113492c924 100644 (file)
@@ -2,20 +2,19 @@ package org.opendaylight.controller.cluster.datastore;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
-
 import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-
 import junit.framework.Assert;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.exceptions.PrimaryNotFoundException;
 import org.opendaylight.controller.cluster.datastore.exceptions.TimeoutException;
 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
+import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
 import org.opendaylight.controller.cluster.datastore.messages.PrimaryFound;
@@ -30,6 +29,7 @@ import org.opendaylight.controller.cluster.datastore.utils.MockActorContext;
 import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
 import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages.CreateTransactionReply;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -81,6 +81,10 @@ public class TransactionProxyTest extends AbstractActorTest {
                 TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
 
 
+        actorContext.setExecuteRemoteOperationResponse(
+            new ReadDataReply(TestModel.createTestContext(), null)
+                .toSerializable());
+
         ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
             transactionProxy.read(TestModel.TEST_PATH);
 
@@ -99,7 +103,7 @@ public class TransactionProxyTest extends AbstractActorTest {
     }
 
     @Test
-    public void testReadWhenANullIsReturned() throws Exception {
+    public void testExists() throws Exception {
         final Props props = Props.create(DoNothingActor.class);
         final ActorRef actorRef = getSystem().actorOf(props);
 
@@ -108,26 +112,57 @@ public class TransactionProxyTest extends AbstractActorTest {
         actorContext.setExecuteShardOperationResponse(createTransactionReply(actorRef));
         actorContext.setExecuteRemoteOperationResponse("message");
 
+
         TransactionProxy transactionProxy =
             new TransactionProxy(actorContext,
                 TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
 
 
-        ListenableFuture<Optional<NormalizedNode<?, ?>>> read =
-            transactionProxy.read(TestModel.TEST_PATH);
+        actorContext.setExecuteRemoteOperationResponse(new DataExistsReply(false).toSerializable());
 
-        Optional<NormalizedNode<?, ?>> normalizedNodeOptional = read.get();
+        CheckedFuture<Boolean, ReadFailedException> exists =
+            transactionProxy.exists(TestModel.TEST_PATH);
 
-        Assert.assertFalse(normalizedNodeOptional.isPresent());
+        Assert.assertFalse(exists.checkedGet());
 
-        actorContext.setExecuteRemoteOperationResponse(new ReadDataReply(
-           TestModel.createTestContext(), null).toSerializable());
+        actorContext.setExecuteRemoteOperationResponse(new DataExistsReply(true).toSerializable());
 
-        read = transactionProxy.read(TestModel.TEST_PATH);
+        exists = transactionProxy.exists(TestModel.TEST_PATH);
 
-        normalizedNodeOptional = read.get();
+        Assert.assertTrue(exists.checkedGet());
 
-        Assert.assertFalse(normalizedNodeOptional.isPresent());
+        actorContext.setExecuteRemoteOperationResponse("bad message");
+
+        exists = transactionProxy.exists(TestModel.TEST_PATH);
+
+        try {
+            exists.checkedGet();
+            fail();
+        } catch(ReadFailedException e){
+        }
+
+    }
+
+    @Test(expected = ReadFailedException.class)
+    public void testReadWhenAnInvalidMessageIsSentInReply() throws Exception {
+        final Props props = Props.create(DoNothingActor.class);
+        final ActorRef actorRef = getSystem().actorOf(props);
+
+        final MockActorContext actorContext = new MockActorContext(this.getSystem());
+        actorContext.setExecuteLocalOperationResponse(createPrimaryFound(actorRef));
+        actorContext.setExecuteShardOperationResponse(createTransactionReply(actorRef));
+        actorContext.setExecuteRemoteOperationResponse("message");
+
+        TransactionProxy transactionProxy =
+            new TransactionProxy(actorContext,
+                TransactionProxy.TransactionType.READ_ONLY, transactionExecutor, TestModel.createTestContext());
+
+
+
+        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException>
+            read = transactionProxy.read(TestModel.TEST_PATH);
+
+        read.checkedGet();
     }
 
     @Test
index fc251c8445a77d1485a2dffc4880afa9b3907f95..9b70f0c4d708d63b1544d05dd1948df35e209912 100644 (file)
@@ -47,4 +47,22 @@ public interface DOMDataReadTransaction extends AsyncReadTransaction<YangInstanc
      */
     CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(
             LogicalDatastoreType store, YangInstanceIdentifier path);
+
+    /**
+     * Checks if data is available in the logical data store located at provided path
+     *
+     * @param path
+     *            Path which uniquely identifies subtree which client want to
+     *            check existence of
+     * @return a CheckFuture containing the result of the check.
+     *         <ul>
+     *         <li>If the data at the supplied path exists, the Future returns a Boolean
+     *         whose value is true, false otherwise</li>
+     *         <li>If checking for the data fails, the Future will fail with a
+     *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
+     *         </ul>
+     */
+    CheckedFuture<Boolean, ReadFailedException> exists(
+        LogicalDatastoreType store, YangInstanceIdentifier path);
+
 }
index b4562cf2eccd2c8b6560552c510fe1bfeb8d9989..5e2a417d28ce22acc6a19a1f556f7ea2c95a4382 100644 (file)
@@ -40,6 +40,12 @@ class DOMForwardedReadOnlyTransaction extends
         return getSubtransaction(store).read(path);
     }
 
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        LogicalDatastoreType store,
+        YangInstanceIdentifier path) {
+        return getSubtransaction(store).exists(path);
+    }
+
     @Override
     public void close() {
         closeSubtransactions();
index 74a4c52e36ff33883754b0ef5543706054134967..67351ec94583cda374f5b0948eafd1089fd98510 100644 (file)
@@ -50,4 +50,10 @@ class DOMForwardedReadWriteTransaction extends DOMForwardedWriteTransaction<DOMS
             final LogicalDatastoreType store, final YangInstanceIdentifier path) {
         return getSubtransaction(store).read(path);
     }
-}
\ No newline at end of file
+
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        LogicalDatastoreType store,
+        YangInstanceIdentifier path) {
+        return getSubtransaction(store).exists(path);
+    }
+}
index 5bd8a7bc021f935fd20251892101f861e2c2db39..fb72b5a99a130efbcfcd0ea04056ef61978f2e06 100644 (file)
@@ -15,13 +15,6 @@ import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
 import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.Nullable;
-
 import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
@@ -78,6 +71,12 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 
+import javax.annotation.Nullable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
 public class BackwardsCompatibleMountPoint implements MountProvisionInstance, SchemaContextProvider, SchemaService {
 
     private final DataProviderService dataReader;
@@ -405,6 +404,16 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
                 final Optional<NormalizedNode<?, ?>> normalizedNodeOptional = Optional.<NormalizedNode<?, ?>>fromNullable(normalized.getValue());
                 return Futures.immediateCheckedFuture(normalizedNodeOptional);
             }
+
+            @Override public CheckedFuture<Boolean, ReadFailedException> exists(LogicalDatastoreType store,
+                YangInstanceIdentifier path) {
+
+                try {
+                    return Futures.immediateCheckedFuture(read(store, path).get().isPresent());
+                } catch (InterruptedException | ExecutionException e) {
+                    return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
+                }
+            }
         }
 
         @VisibleForTesting
@@ -518,6 +527,16 @@ public class BackwardsCompatibleMountPoint implements MountProvisionInstance, Sc
                 return new BackwardsCompatibleReadTransaction(dataReader, dataNormalizer).read(store, path);
             }
 
+            @Override public CheckedFuture<Boolean, ReadFailedException> exists(LogicalDatastoreType store,
+                YangInstanceIdentifier path) {
+
+                try {
+                    return Futures.immediateCheckedFuture(read(store, path).get().isPresent());
+                } catch (InterruptedException | ExecutionException e) {
+                    return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
+                }
+            }
+
             @Override
             public boolean cancel() {
                 return delegateWriteTx.cancel();
index 84d09c7cb024a275ebfdfa6edd8a75af00abc3af..719a6f0499d4423040e5547b82a3bc957c30abbe 100644 (file)
@@ -34,4 +34,20 @@ public interface DOMStoreReadTransaction extends DOMStoreTransaction {
      *         </ul>
      */
     CheckedFuture<Optional<NormalizedNode<?,?>>, ReadFailedException> read(YangInstanceIdentifier path);
+
+    /**
+     * Checks if data is available in the logical data store located at provided path
+     *
+     * @param path
+     *            Path which uniquely identifies subtree which client want to
+     *            check existence of
+     * @return a CheckFuture containing the result of the check.
+     *         <ul>
+     *         <li>If the data at the supplied path exists, the Future returns a Boolean
+     *         whose value is true, false otherwise</li>
+     *         <li>If checking for the data fails, the Future will fail with a
+     *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
+     *         </ul>
+     */
+    CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path);
 }
index 2a9840634381efea5c76cfd220530a11a83d80f0..44ee61c116a9a4c5f8f336890827fcfceea68075 100644 (file)
@@ -7,19 +7,19 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.Futures;
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  *
@@ -63,4 +63,16 @@ final class SnapshotBackedReadTransaction extends AbstractDOMStoreTransaction
             return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
         }
     }
-}
\ No newline at end of file
+
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(YangInstanceIdentifier path) {
+        LOG.debug("Tx: {} Exists: {}", getIdentifier(), path);
+        checkNotNull(path, "Path must not be null.");
+
+        try {
+            return Futures.immediateCheckedFuture(
+                read(path).checkedGet().isPresent());
+        } catch (ReadFailedException e) {
+            return Futures.immediateFailedCheckedFuture(e);
+        }
+    }
+}
index 5c5e9c6b6d82f4263959c6f8e137cc0bf1af25ad..ce7043fd4747542a98802a893d0d49c3c12b3de5 100644 (file)
@@ -61,4 +61,14 @@ class SnapshotBackedReadWriteTransaction extends SnapshotBackedWriteTransaction
             return Futures.immediateFailedCheckedFuture(new ReadFailedException("Read failed",e));
         }
     }
-}
\ No newline at end of file
+
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        YangInstanceIdentifier path) {
+        try {
+            return Futures.immediateCheckedFuture(
+                read(path).checkedGet().isPresent());
+        } catch (ReadFailedException e) {
+            return Futures.immediateFailedCheckedFuture(e);
+        }
+    }
+}
index 4d38858667173df23ed112fa5e13c139914bdb73..c609e13e791c375979ad99bce62ed27df9d321f8 100644 (file)
@@ -7,13 +7,10 @@
  */
 package org.opendaylight.controller.md.sal.dom.store.impl;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.concurrent.ExecutionException;
-
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -35,9 +32,12 @@ import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 
 public class InMemoryDataStoreTest {
@@ -185,6 +185,74 @@ public class InMemoryDataStoreTest {
         assertEquals( "After commit read: data", containerNode, afterCommitRead.get() );
     }
 
+
+    @Test
+    public void testExistsForExistingData() throws Exception {
+
+        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+        assertNotNull( writeTx );
+
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+            .withNodeIdentifier( new NodeIdentifier( TestModel.TEST_QNAME ) )
+            .addChild( ImmutableNodes.mapNodeBuilder( TestModel.OUTER_LIST_QNAME )
+                .addChild( ImmutableNodes.mapEntry( TestModel.OUTER_LIST_QNAME,
+                    TestModel.ID_QNAME, 1 ) ).build() ).build();
+
+        writeTx.merge( TestModel.TEST_PATH, containerNode );
+
+        CheckedFuture<Boolean, ReadFailedException> exists =
+            writeTx.exists(TestModel.TEST_PATH);
+
+        assertEquals(true, exists.checkedGet());
+
+        DOMStoreThreePhaseCommitCohort ready = writeTx.ready();
+
+        ready.preCommit().get();
+
+        ready.commit().get();
+
+        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+        assertNotNull( readTx );
+
+        exists =
+            readTx.exists(TestModel.TEST_PATH);
+
+        assertEquals(true, exists.checkedGet());
+    }
+
+    @Test
+    public void testExistsForNonExistingData() throws Exception {
+
+        DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
+        assertNotNull( writeTx );
+
+        CheckedFuture<Boolean, ReadFailedException> exists =
+            writeTx.exists(TestModel.TEST_PATH);
+
+        assertEquals(false, exists.checkedGet());
+
+        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+        assertNotNull( readTx );
+
+        exists =
+            readTx.exists(TestModel.TEST_PATH);
+
+        assertEquals(false, exists.checkedGet());
+    }
+
+    @Test(expected=ReadFailedException.class)
+    public void testExistsThrowsReadFailedException() throws Exception {
+
+        DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
+        assertNotNull( readTx );
+
+        readTx.close();
+
+        readTx.exists(TestModel.TEST_PATH).checkedGet();
+    }
+
+
+
     @Test(expected=ReadFailedException.class)
     public void testReadWithReadOnlyTransactionClosed() throws Throwable {
 
index 04a99511a1dfaa6154a9894e47906d859de0c199..70d4f4336558d8d5897df9db297154f62d76cf09 100644 (file)
@@ -7,12 +7,6 @@
  */
 package org.opendaylight.controller.sal.connect.netconf.sal.tx;
 
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.CONFIG_SOURCE_RUNNING;
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME;
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME;
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
-import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure;
-
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -35,6 +29,14 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.ExecutionException;
+
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.CONFIG_SOURCE_RUNNING;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME;
+import static org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil.toFilterStructure;
+
 
 public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction {
 
@@ -136,6 +138,19 @@ public final class NetconfDeviceReadOnlyTx implements DOMDataReadOnlyTransaction
         throw new IllegalArgumentException(String.format("%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store));
     }
 
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        LogicalDatastoreType store,
+        YangInstanceIdentifier path) {
+        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException>
+            data = read(store, path);
+
+        try {
+            return Futures.immediateCheckedFuture(data.get().isPresent());
+        } catch (InterruptedException | ExecutionException e) {
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
+        }
+    }
+
     static YangInstanceIdentifier toLegacyPath(final DataNormalizer normalizer, final YangInstanceIdentifier path, final RemoteDeviceId id) {
         try {
             return normalizer.toLegacy(path);
index 3d2c3b9d44b95fc90355ba7ce1085b1749520b9f..11362a2f9b84d5fe71013a505aad94dce4ed98ec 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.sal.connect.netconf.sal.tx;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
@@ -23,6 +24,8 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
+import java.util.concurrent.ExecutionException;
+
 public class NetconfDeviceReadWriteTx implements DOMDataReadWriteTransaction {
 
     private final DOMDataReadTransaction delegateReadTx;
@@ -69,6 +72,19 @@ public class NetconfDeviceReadWriteTx implements DOMDataReadWriteTransaction {
         return delegateReadTx.read(store, path);
     }
 
+    @Override public CheckedFuture<Boolean, ReadFailedException> exists(
+        LogicalDatastoreType store,
+        YangInstanceIdentifier path) {
+        CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException>
+            data = read(store, path);
+
+        try {
+            return Futures.immediateCheckedFuture(data.get().isPresent());
+        } catch (InterruptedException | ExecutionException e) {
+            return Futures.immediateFailedCheckedFuture(new ReadFailedException("Exists failed",e));
+        }
+    }
+
     @Override
     public Object getIdentifier() {
         return this;
index e8701f37e5846e72e9c177ca2188969c7fb9a9da..8dbc5b50ee5dbd8ac374ef7d1452384442923085 100644 (file)
@@ -7,20 +7,12 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
-import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
-import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
-
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import javax.ws.rs.core.Response.Status;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
@@ -45,6 +37,16 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.ws.rs.core.Response.Status;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
+
 public class BrokerFacade {
     private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
 
@@ -255,15 +257,20 @@ public class BrokerFacade {
             currentArguments.add(currentArg);
             YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(currentArguments);
 
-            final Optional<NormalizedNode<?, ?>> datastoreData;
+            final Boolean exists;
+
             try {
-                datastoreData = rwTx.read(store, currentPath).get();
-            } catch (InterruptedException | ExecutionException e) {
+
+                CheckedFuture<Boolean, ReadFailedException> future =
+                    rwTx.exists(store, currentPath);
+                exists = future.checkedGet();
+            } catch (ReadFailedException e) {
                 LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
                 throw new IllegalStateException("Failed to read pre-existing data", e);
             }
 
-            if (!datastoreData.isPresent() && iterator.hasNext()) {
+
+            if (!exists && iterator.hasNext()) {
                 rwTx.merge(store, currentPath, currentOp.createDefault(currentArg));
             }
         }
index 146e88299ac6133e71fbf240cea3953956dbbd78..6b2583024036b6b7ef39863f64f3fa9069d19e94 100644 (file)
@@ -8,21 +8,9 @@
 
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.Futures;
-import java.util.concurrent.Future;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -55,6 +43,19 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdent
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 
+import java.util.concurrent.Future;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
 /**
  * Unit tests for BrokerFacade.
  *
@@ -111,6 +112,11 @@ public class BrokerFacadeTest {
         return  Futures.immediateCheckedFuture(Optional.<NormalizedNode<?, ?>> of(dummyNode));
     }
 
+    private CheckedFuture<Boolean,ReadFailedException> wrapExistence(Boolean exists) {
+        return  Futures.immediateCheckedFuture(exists);
+    }
+
+
     /**
      * Value of this node shouldn't be important for testing purposes
      */
@@ -189,8 +195,14 @@ public class BrokerFacadeTest {
         CheckedFuture<Void, TransactionCommitFailedException> expFuture = mock(CheckedFuture.class);
 
         NormalizedNode<?, ?> dummyNode2 = createDummyNode("dummy:namespace2", "2014-07-01", "dummy local name2");
+
         when(rwTransaction.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
                 wrapDummyNode(dummyNode2));
+
+        when(rwTransaction.exists(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+            wrapExistence(true));
+
+
         when(rwTransaction.submit()).thenReturn(expFuture);
 
         CheckedFuture<Void, TransactionCommitFailedException> actualFuture = brokerFacade.commitConfigurationDataPost(