Introduce ReadTransaction.exists() 45/77845/1
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 14 Nov 2018 09:11:44 +0000 (10:11 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 15 Nov 2018 09:27:39 +0000 (10:27 +0100)
This method exists in the DOM API, but for some reason it was left
out if the Binding API. Introduce it as default methods riding on
the read() method and override them in all known implementations,
so the request is efficiently routed.

JIRA: MDSAL-389
Change-Id: Id56332d6f720396305ac68e40554e62fd17c34fb
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
(cherry picked from commit a6bdbfafe60b9aeac056187f27229e476fbf88bf)

opendaylight/md-sal/sal-binding-api/pom.xml
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ForwardingReadOnlyTransaction.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ForwardingReadWriteTransaction.java
opendaylight/md-sal/sal-binding-api/src/main/java/org/opendaylight/controller/md/sal/binding/api/ReadTransaction.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDOMReadTransactionAdapter.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingDOMReadWriteTransactionAdapter.java

index 497921d5abc677d6220b7cda5b496d5589791b3a..db782235da3d5701d5a1cecd9db23fc1ae5f77cf 100644 (file)
       <artifactId>guava</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>sal-common-api</artifactId>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>concepts</artifactId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>concepts</artifactId>
+      <artifactId>yang-common</artifactId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.mdsal</groupId>
       <artifactId>yang-binding</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-common</artifactId>
+      <groupId>org.opendaylight.mdsal</groupId>
+      <artifactId>mdsal-common-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-api</artifactId>
     </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
index a8fad515607fb00d99dbb32760dbe2c7bbef67f4..a71c08a1c0c59316dae123b8662327eb20a0d6e6 100644 (file)
@@ -24,7 +24,7 @@ public class ForwardingReadOnlyTransaction extends ForwardingObject implements R
 
     private final ReadOnlyTransaction delegate;
 
-    protected ForwardingReadOnlyTransaction(ReadOnlyTransaction delegate) {
+    protected ForwardingReadOnlyTransaction(final ReadOnlyTransaction delegate) {
         this.delegate = delegate;
     }
 
@@ -34,11 +34,17 @@ public class ForwardingReadOnlyTransaction extends ForwardingObject implements R
     }
 
     @Override
-    public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(LogicalDatastoreType store,
-            InstanceIdentifier<T> path) {
+    public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path) {
         return delegate.read(store, path);
     }
 
+    @Override
+    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return delegate.exists(store, path);
+    }
+
     @Override
     public Object getIdentifier() {
         return delegate.getIdentifier();
index 97a6db64195454f997d34c6cb55079472f35c477..c2cca55239dff7dbe8d4faeca5295f84007b8dd7 100644 (file)
@@ -28,7 +28,7 @@ public class ForwardingReadWriteTransaction extends ForwardingObject implements
 
     private final ReadWriteTransaction delegate;
 
-    protected ForwardingReadWriteTransaction(ReadWriteTransaction delegate) {
+    protected ForwardingReadWriteTransaction(final ReadWriteTransaction delegate) {
         this.delegate = delegate;
     }
 
@@ -38,22 +38,29 @@ public class ForwardingReadWriteTransaction extends ForwardingObject implements
     }
 
     @Override
-    public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
+    public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data) {
         delegate.put(store, path, data);
     }
 
     @Override
-    public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
-            boolean createMissingParents) {
+    public <T extends DataObject> void put(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data, final boolean createMissingParents) {
         delegate.put(store, path, data, createMissingParents);
     }
 
     @Override
-    public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(LogicalDatastoreType store,
-            InstanceIdentifier<T> path) {
+    public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(final LogicalDatastoreType store,
+            final InstanceIdentifier<T> path) {
         return delegate.read(store, path);
     }
 
+    @Override
+    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return delegate.exists(store, path);
+    }
+
     @Override
     public Object getIdentifier() {
         return delegate.getIdentifier();
@@ -65,13 +72,14 @@ public class ForwardingReadWriteTransaction extends ForwardingObject implements
     }
 
     @Override
-    public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
+    public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data) {
         delegate.merge(store, path, data);
     }
 
     @Override
-    public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
-            boolean createMissingParents) {
+    public <T extends DataObject> void merge(final LogicalDatastoreType store, final InstanceIdentifier<T> path,
+            final T data, final boolean createMissingParents) {
         delegate.merge(store, path, data, createMissingParents);
     }
 
@@ -81,7 +89,7 @@ public class ForwardingReadWriteTransaction extends ForwardingObject implements
     }
 
     @Override
-    public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
+    public void delete(final LogicalDatastoreType store, final InstanceIdentifier<?> path) {
         delegate.delete(store, path);
     }
 
index b0c93734e09dba7f964701f4875f10a6f69d297f..9bd54054174f4a61141d8f964a2b4351e35e5ac3 100644 (file)
@@ -7,15 +7,17 @@
  */
 package org.opendaylight.controller.md.sal.binding.api;
 
+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.MoreExecutors;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncReadTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.mdsal.common.api.MappingCheckedFuture;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
 /**
  * A transaction that provides read access to a logical data store.
  * <p>
@@ -45,6 +47,38 @@ public interface ReadTransaction extends AsyncReadTransaction<InstanceIdentifier
      *         {@link ReadFailedException} or an exception derived from ReadFailedException.</li>
      *         </ul>
      */
-    <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> read(
+    <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(
             LogicalDatastoreType store, InstanceIdentifier<T> path);
+
+    /**
+     * Checks if data is available in the logical data store located at provided path.
+     *
+     * <p>
+     * Note: a successful result from this method makes no guarantee that a subsequent call to {@link #read}
+     * will succeed. It is possible that the data resides in a data store on a remote node and, if that
+     * node goes down or a network failure occurs, a subsequent read would fail. Another scenario is if
+     * the data is deleted in between the calls to <code>exists</code> and <code>read</code>
+     *
+     * <p>
+     * Default implementation delegates to {@link #read(LogicalDatastoreType, InstanceIdentifier)}, implementations
+     * are advised to provide a more efficient override.
+     *
+     * @param store
+     *            Logical data store from which read should occur.
+     * @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>
+     */
+    default CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return MappingCheckedFuture.create(Futures.transform(read(store, path), Optional::isPresent,
+            MoreExecutors.directExecutor()), ReadFailedException.MAPPER);
+    }
 }
index 1184d395828dee8abd2fd23353257245897f6c79..61a909cb345fbb37794610acb20438b35515757f 100644 (file)
@@ -55,7 +55,7 @@ abstract class AbstractForwardedTransaction<T extends AsyncTransaction<YangInsta
         return codec;
     }
 
-    protected final <D extends DataObject> CheckedFuture<Optional<D>,ReadFailedException> doRead(
+    protected final <D extends DataObject> CheckedFuture<Optional<D>, ReadFailedException> doRead(
             final DOMDataReadTransaction readTx, final LogicalDatastoreType store,
             final InstanceIdentifier<D> path) {
         Preconditions.checkArgument(!path.isWildcarded(), "Invalid read of wildcarded path %s", path);
@@ -65,4 +65,13 @@ abstract class AbstractForwardedTransaction<T extends AsyncTransaction<YangInsta
                                       codec.deserializeFunction(path)),
                     ReadFailedException.MAPPER);
     }
+
+    protected final CheckedFuture<Boolean, ReadFailedException> doExists(
+            final DOMDataReadTransaction readTx, final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        Preconditions.checkArgument(!path.isWildcarded(), "Invalid read of wildcarded path %s", path);
+
+        return MappingCheckedFuture.create(readTx.exists(store, codec.toYangInstanceIdentifierBlocking(path)),
+            ReadFailedException.MAPPER);
+    }
 }
index 0e8a043cccb47f78bf6fa024841755946d9307d2..10d1438860480fe82e61407efb43eef8dd3159c0 100644 (file)
@@ -26,11 +26,17 @@ class BindingDOMReadTransactionAdapter extends AbstractForwardedTransaction<DOMD
     }
 
     @Override
-    public <T extends DataObject> CheckedFuture<Optional<T>,ReadFailedException> read(
+    public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(
             final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
         return doRead(getDelegate(),store, path);
     }
 
+    @Override
+    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return doExists(getDelegate(), store, path);
+    }
+
     @Override
     public void close() {
         getDelegate().close();
index e9c4efac531b0677945ae67547d035f5b54c0eb0..d3764fbce6f76639342090678ac4c08aa09a0e0e 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.md.sal.binding.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
@@ -14,9 +16,6 @@ import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
 class BindingDOMReadWriteTransactionAdapter extends
         BindingDOMWriteTransactionAdapter<DOMDataReadWriteTransaction> implements ReadWriteTransaction {
 
@@ -30,4 +29,10 @@ class BindingDOMReadWriteTransactionAdapter extends
             final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
         return doRead(getDelegate(), store, path);
     }
-}
\ No newline at end of file
+
+    @Override
+    public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
+            final InstanceIdentifier<?> path) {
+        return doExists(getDelegate(), store, path);
+    }
+}