Merge "NECONF-524 : Setting the netconf keepalive logic to be more proactive."
[netconf.git] / netconf / netconf-client / src / main / java / org / opendaylight / netconf / client / SimpleNetconfClientSessionListener.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.client;
10
11 import com.google.common.base.Preconditions;
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import io.netty.util.concurrent.Future;
14 import io.netty.util.concurrent.GlobalEventExecutor;
15 import io.netty.util.concurrent.Promise;
16 import java.util.ArrayDeque;
17 import java.util.Queue;
18 import javax.annotation.concurrent.GuardedBy;
19 import org.opendaylight.netconf.api.NetconfMessage;
20 import org.opendaylight.netconf.api.NetconfTerminationReason;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 public class SimpleNetconfClientSessionListener implements NetconfClientSessionListener {
25     private static final class RequestEntry {
26         private final Promise<NetconfMessage> promise;
27         private final NetconfMessage request;
28
29         RequestEntry(Promise<NetconfMessage> future, NetconfMessage request) {
30             this.promise = Preconditions.checkNotNull(future);
31             this.request = Preconditions.checkNotNull(request);
32         }
33     }
34
35     private static final Logger LOG = LoggerFactory.getLogger(SimpleNetconfClientSessionListener.class);
36
37     @GuardedBy("this")
38     private final Queue<RequestEntry> requests = new ArrayDeque<>();
39
40     @GuardedBy("this")
41     private NetconfClientSession clientSession;
42
43     @GuardedBy("this")
44     @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED")
45     private void dispatchRequest() {
46         while (!requests.isEmpty()) {
47             final RequestEntry e = requests.peek();
48             if (e.promise.setUncancellable()) {
49                 LOG.debug("Sending message {}", e.request);
50                 clientSession.sendMessage(e.request);
51                 break;
52             }
53
54             LOG.debug("Message {} has been cancelled, skipping it", e.request);
55             requests.poll();
56         }
57     }
58
59     @Override
60     @SuppressWarnings("checkstyle:hiddenField")
61     public final synchronized void onSessionUp(NetconfClientSession clientSession) {
62         this.clientSession = Preconditions.checkNotNull(clientSession);
63         LOG.debug("Client session {} went up", clientSession);
64         dispatchRequest();
65     }
66
67     private synchronized void tearDown(final Exception cause) {
68         final RequestEntry e = requests.poll();
69         if (e != null) {
70             e.promise.setFailure(cause);
71         }
72
73         this.clientSession = null;
74     }
75
76     @Override
77     @SuppressWarnings("checkstyle:hiddenField")
78     public final void onSessionDown(NetconfClientSession clientSession, Exception exception) {
79         LOG.debug("Client Session {} went down unexpectedly", clientSession, exception);
80         tearDown(exception);
81     }
82
83     @Override
84     @SuppressWarnings("checkstyle:hiddenField")
85     public final void onSessionTerminated(NetconfClientSession clientSession,
86                                           NetconfTerminationReason netconfTerminationReason) {
87         LOG.debug("Client Session {} terminated, reason: {}", clientSession,
88                 netconfTerminationReason.getErrorMessage());
89         tearDown(new RuntimeException(netconfTerminationReason.getErrorMessage()));
90     }
91
92     @Override
93     public synchronized void onMessage(NetconfClientSession session, NetconfMessage message) {
94         LOG.debug("New message arrived: {}", message);
95
96         final RequestEntry e = requests.poll();
97         if (e != null) {
98             e.promise.setSuccess(message);
99             dispatchRequest();
100         } else {
101             LOG.info("Ignoring unsolicited message {}", message);
102         }
103     }
104
105     public final synchronized Future<NetconfMessage> sendRequest(NetconfMessage message) {
106         final RequestEntry req = new RequestEntry(GlobalEventExecutor.INSTANCE.newPromise(), message);
107
108         requests.add(req);
109         if (clientSession != null) {
110             dispatchRequest();
111         }
112
113         return req.promise;
114     }
115 }