Bug 4940 - correctly implement default-request-timeout-millis
[controller.git] / opendaylight / md-sal / sal-netconf-connector / src / main / java / org / opendaylight / controller / sal / connect / netconf / sal / tx / ReadOnlyTx.java
index e08731ed407525735e15c4ba424d85847433d49d..4200c6c137cfdad58441dedec690cf9487f4db81 100644 (file)
@@ -14,7 +14,11 @@ import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
 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.dom.api.DOMDataReadOnlyTransaction;
@@ -40,9 +44,12 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction {
     private final RemoteDeviceId id;
     private final FutureCallback<DOMRpcResult> loggingCallback;
 
-    public ReadOnlyTx(final NetconfBaseOps netconfOps, final RemoteDeviceId id) {
+    private final long requestTimeoutMillis;
+
+    public ReadOnlyTx(final NetconfBaseOps netconfOps, final RemoteDeviceId id, final long requestTimeoutMillis) {
         this.netconfOps = netconfOps;
         this.id = id;
+        this.requestTimeoutMillis = requestTimeoutMillis;
 
         // Simple logging callback to log result of read operation
         loggingCallback = new FutureCallback<DOMRpcResult>() {
@@ -53,7 +60,6 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction {
                 } else {
                     LOG.warn("{}: Reading data unsuccessful: {}", id, result.getErrors());
                 }
-
             }
 
             @Override
@@ -77,6 +83,11 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction {
             }
         });
 
+
+        if(!readWithTimeout("readConfigurationData", configRunning)) {
+            return null;
+        }
+
         return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
     }
 
@@ -108,6 +119,10 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction {
             }
         });
 
+        if(!readWithTimeout("readOperationalData", configCandidate)) {
+            return null;
+        }
+
         return MappingCheckedFuture.create(transformedFuture, ReadFailedException.MAPPER);
     }
 
@@ -146,4 +161,18 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction {
     public Object getIdentifier() {
         return this;
     }
+
+    private boolean readWithTimeout(String operation, ListenableFuture<DOMRpcResult> future) {
+        try {
+            future.get(requestTimeoutMillis, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("{}: {} failed with error", id, operation, e);
+            throw new RuntimeException(id + ": readOperationalData failed");
+        } catch (TimeoutException e) {
+            LOG.warn("{}: Unable to {} after {} milliseconds", id, operation, requestTimeoutMillis, e);
+            future.cancel(true);
+            return false;
+        }
+        return true;
+    }
 }