X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Fconnect%2Fnetconf%2Fsal%2FKeepaliveSalFacade.java;h=82cf4b23379dfced7e83256447c09c72071d86d6;hb=4e39e49ef541d25099afc4c2ff80d89b04b24103;hp=dc2b5dff427f3b40c12ebd5624b1a33151cabff3;hpb=63abf8472cfb70f4e2729585dc9ff95b41d068f8;p=netconf.git diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java index dc2b5dff42..82cf4b2337 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/sal/KeepaliveSalFacade.java @@ -16,6 +16,8 @@ import com.google.common.base.Preconditions; 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.MoreExecutors; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -51,32 +53,38 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler 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 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 salFacade, final ScheduledExecutorService executor) { - this(id, salFacade, executor, DEFAULT_DELAY); + this(id, salFacade, executor, DEFAULT_DELAY, DEFAULT_TRANSACTION_TIMEOUT_MILLI); } /** - * Set the netconf session listener whenever ready + * Set the netconf session listener whenever ready. * * @param listener netconf session listener */ @@ -88,27 +96,28 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler * Then schedule next keepalive. */ - private void resetKeepalive() { + void resetKeepalive() { LOG.trace("{}: Resetting netconf keepalive timer", id); - if(currentKeepalive != null) { + if (currentKeepalive != null) { currentKeepalive.cancel(false); } scheduleKeepalive(); } /** - * Cancel current keepalive and also reset current deviceRpc + * Cancel current keepalive and also reset current deviceRpc. */ private void stopKeepalives() { - if(currentKeepalive != null) { + if (currentKeepalive != null) { currentKeepalive.cancel(false); } currentDeviceRpc = null; } - private void reconnect() { + void reconnect() { Preconditions.checkState(listener != null, "%s: Unable to reconnect, session listener is missing", id); stopKeepalives(); LOG.info("{}: Reconnecting inactive netconf session", id); @@ -116,9 +125,11 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler previousKeepalive; - public Keepalive(final ScheduledFuture previousKeepalive) { + Keepalive(final ScheduledFuture previousKeepalive) { this.previousKeepalive = previousKeepalive; } @@ -179,10 +190,11 @@ public final class KeepaliveSalFacade implements RemoteDeviceHandler { + private class ResetKeepalive implements FutureCallback { @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 + // No matter what response we got, + // rpc-reply or rpc-error, we got it from device so the netconf session is OK. resetKeepalive(); } @Override - public void onFailure(@Nonnull final Throwable t) { - // User/Application RPC failed (The RPC did not reach the remote device. + public void onFailure(@Nonnull final Throwable throwable) { + // User/Application RPC failed (The RPC did not reach the remote device or .. + // TODO what other reasons could cause this ?) // There is no point in keeping this session. Reconnect. - LOG.warn("{}: Rpc failure detected. Reconnecting netconf session", id, t); + LOG.warn("{}: Rpc failure detected. Reconnecting netconf session", id, throwable); reconnect(); } } + /* + * 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 rpcResultFuture; + + RequestTimeoutTask(final CheckedFuture 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 { + public static final class KeepaliveDOMRpcService implements DOMRpcService { private final DOMRpcService deviceRpc; - private ResetKeepalive resetKeepaliveTask; + private final ResetKeepalive resetKeepaliveTask; + private final long defaultRequestTimeoutMillis; + private final ScheduledExecutorService executor; - public KeepaliveDOMRpcService(final DOMRpcService deviceRpc, final ResetKeepalive resetKeepaliveTask) { + 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; + } + + public DOMRpcService getDeviceRpc() { + return deviceRpc; } @Nonnull @Override - public CheckedFuture invokeRpc(@Nonnull final SchemaPath type, final NormalizedNode input) { - final CheckedFuture domRpcResultDOMRpcExceptionCheckedFuture = deviceRpc.invokeRpc(type, input); - Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask); + public CheckedFuture invokeRpc(@Nonnull final SchemaPath type, + final NormalizedNode input) { + final CheckedFuture domRpcResultDOMRpcExceptionCheckedFuture = + deviceRpc.invokeRpc(type, input); + Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask, + MoreExecutors.directExecutor()); + + final RequestTimeoutTask timeoutTask = new RequestTimeoutTask(domRpcResultDOMRpcExceptionCheckedFuture); + executor.schedule(timeoutTask, defaultRequestTimeoutMillis, TimeUnit.MILLISECONDS); + return domRpcResultDOMRpcExceptionCheckedFuture; } @Override - public ListenerRegistration registerRpcListener(@Nonnull final T listener) { + public ListenerRegistration registerRpcListener( + @Nonnull final T listener) { // There is no real communication with the device (yet), no reset here return deviceRpc.registerRpcListener(listener); }