// 2 minutes keepalive delay by default
private static final long DEFAULT_DELAY = TimeUnit.MINUTES.toSeconds(2);
+ // 1 minute transaction timeout by default
+ private static final long DEFAULT_TRANSACTION_TIMEOUT_MILLI = TimeUnit.MILLISECONDS.toMillis(60000);
+
private final RemoteDeviceId id;
private final RemoteDeviceHandler<NetconfSessionPreferences> salFacade;
private final ScheduledExecutorService executor;
private final long keepaliveDelaySeconds;
private final ResetKeepalive resetKeepaliveTask;
+ private final long defaultRequestTimeoutMillis;
private volatile NetconfDeviceCommunicator listener;
private volatile ScheduledFuture<?> currentKeepalive;
private volatile DOMRpcService currentDeviceRpc;
public KeepaliveSalFacade(final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
- final ScheduledExecutorService executor, final long keepaliveDelaySeconds) {
+ final ScheduledExecutorService executor, final long keepaliveDelaySeconds, final long defaultRequestTimeoutMillis) {
this.id = id;
this.salFacade = salFacade;
this.executor = executor;
this.keepaliveDelaySeconds = keepaliveDelaySeconds;
+ this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis;
this.resetKeepaliveTask = new ResetKeepalive();
}
public KeepaliveSalFacade(final RemoteDeviceId id, final RemoteDeviceHandler<NetconfSessionPreferences> salFacade,
final ScheduledExecutorService executor) {
- this(id, salFacade, executor, DEFAULT_DELAY);
+ this(id, salFacade, executor, DEFAULT_DELAY, DEFAULT_TRANSACTION_TIMEOUT_MILLI);
}
/**
@Override
public void onDeviceConnected(final SchemaContext remoteSchemaContext, final NetconfSessionPreferences netconfSessionPreferences, final DOMRpcService deviceRpc) {
this.currentDeviceRpc = deviceRpc;
- final DOMRpcService deviceRpc1 = new KeepaliveDOMRpcService(deviceRpc, resetKeepaliveTask);
+ final DOMRpcService deviceRpc1 = new KeepaliveDOMRpcService(deviceRpc, resetKeepaliveTask, defaultRequestTimeoutMillis, executor);
salFacade.onDeviceConnected(remoteSchemaContext, netconfSessionPreferences, deviceRpc1);
LOG.debug("{}: Netconf session initiated, starting keepalives", id);
/**
* Reset keepalive after each RPC response received
*/
- private class ResetKeepalive implements com.google.common.util.concurrent.FutureCallback<DOMRpcResult> {
+ private class ResetKeepalive implements FutureCallback<DOMRpcResult> {
@Override
public void onSuccess(@Nullable final DOMRpcResult result) {
// No matter what response we got, rpc-reply or rpc-error, we got it from device so the netconf session is OK
}
}
+ /*
+ * Request timeout task is called once the defaultRequestTimeoutMillis is
+ * reached. At this moment, if the request is not yet finished, we cancel
+ * it.
+ */
+ private static final class RequestTimeoutTask implements Runnable {
+
+ private final CheckedFuture<DOMRpcResult, DOMRpcException> rpcResultFuture;
+
+ public RequestTimeoutTask(final CheckedFuture<DOMRpcResult, DOMRpcException> rpcResultFuture) {
+ this.rpcResultFuture = rpcResultFuture;
+ }
+
+ @Override
+ public void run() {
+ if (!rpcResultFuture.isDone()) {
+ rpcResultFuture.cancel(true);
+ }
+ }
+ }
+
/**
- * DOMRpcService proxy that attaches reset-keepalive-task to each RPC invocation.
+ * DOMRpcService proxy that attaches reset-keepalive-task and schedule
+ * request-timeout-task to each RPC invocation.
*/
private static final class KeepaliveDOMRpcService implements DOMRpcService {
private final DOMRpcService deviceRpc;
private ResetKeepalive resetKeepaliveTask;
+ private final long defaultRequestTimeoutMillis;
+ private final ScheduledExecutorService executor;
- public KeepaliveDOMRpcService(final DOMRpcService deviceRpc, final ResetKeepalive resetKeepaliveTask) {
+ public KeepaliveDOMRpcService(final DOMRpcService deviceRpc, final ResetKeepalive resetKeepaliveTask,
+ final long defaultRequestTimeoutMillis, final ScheduledExecutorService executor) {
this.deviceRpc = deviceRpc;
this.resetKeepaliveTask = resetKeepaliveTask;
+ this.defaultRequestTimeoutMillis = defaultRequestTimeoutMillis;
+ this.executor = executor;
}
@Nonnull
public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(@Nonnull final SchemaPath type, final NormalizedNode<?, ?> input) {
final CheckedFuture<DOMRpcResult, DOMRpcException> domRpcResultDOMRpcExceptionCheckedFuture = deviceRpc.invokeRpc(type, input);
Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask);
+
+ final RequestTimeoutTask timeoutTask = new RequestTimeoutTask(domRpcResultDOMRpcExceptionCheckedFuture);
+ executor.schedule(timeoutTask, defaultRequestTimeoutMillis, TimeUnit.MILLISECONDS);
+
return domRpcResultDOMRpcExceptionCheckedFuture;
}