BUG 2429 - not releasing dead connection threads
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / connection / listener / SystemNotificationsListenerImpl.java
index 8d754bfd5ed2492a80ecc064256c97f692b1c433..d37777e33cfd8ece1628148e7eb060af57346698 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.openflowplugin.impl.connection.listener;
 
+import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.JdkFutureAdapters;
@@ -14,10 +16,12 @@ import com.google.common.util.concurrent.ListenableFuture;
 import java.net.InetSocketAddress;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
@@ -32,20 +36,19 @@ import org.slf4j.LoggerFactory;
 public class SystemNotificationsListenerImpl implements SystemNotificationsListener {
 
     private ConnectionContext connectionContext;
+    HandshakeContext handshakeContext;
     private static final Logger LOG = LoggerFactory.getLogger(SystemNotificationsListenerImpl.class);
-    private static final long MAX_ECHO_REPLY_TIMEOUT = 2000;
+    @VisibleForTesting
+    static final long MAX_ECHO_REPLY_TIMEOUT = 2000;
 
-
-    /**
-     * @param connectionContext
-     */
-    public SystemNotificationsListenerImpl(ConnectionContext connectionContext) {
+    public SystemNotificationsListenerImpl(final ConnectionContext connectionContext, 
+            final HandshakeContext handshakeContext) {
         this.connectionContext = connectionContext;
+        this.handshakeContext = handshakeContext;
     }
 
     @Override
     public void onDisconnectEvent(DisconnectEvent notification) {
-        // TODO Auto-generated method stub
         disconnect();
     }
 
@@ -59,13 +62,13 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
                 final InetSocketAddress remoteAddress = connectionContext.getConnectionAdapter().getRemoteAddress();
 
                 if (ConnectionContext.CONNECTION_STATE.WORKING.equals(connectionContext.getConnectionState())) {
+                    FeaturesReply features = connectionContext.getFeatures();
                     LOG.debug(
                             "first idle state occured, node={}|auxId={}",
-                            connectionContext.getConnectionAdapter().getRemoteAddress(),
-                            connectionContext.getFeatures().getAuxiliaryId());
+                            remoteAddress, features.getAuxiliaryId());
                     connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
                     EchoInputBuilder builder = new EchoInputBuilder();
-                    builder.setVersion(connectionContext.getFeatures().getVersion());
+                    builder.setVersion(features.getVersion());
                     Xid xid = new Xid(0);
                     builder.setXid(xid.getValue());
 
@@ -100,15 +103,22 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
     }
 
     private void disconnect() {
+        final ConnectionAdapter connectionAdapter = connectionContext.getConnectionAdapter();
+        short auxId = -1;
+        if (null != connectionContext.getFeatures() && null != connectionContext.getFeatures().getAuxiliaryId()) {
+            auxId = connectionContext.getFeatures().getAuxiliaryId();
+        }
+        final Short auxiliaryId = auxId;
+        final InetSocketAddress remoteAddress = connectionAdapter.getRemoteAddress();
 
         LOG.trace("disconnecting: node={}|auxId={}|connection state = {}",
-                connectionContext.getConnectionAdapter().getRemoteAddress(),
-                connectionContext.getFeatures().getAuxiliaryId(),
+                remoteAddress,
+                auxiliaryId,
                 connectionContext.getConnectionState());
 
         ListenableFuture<Boolean> result = null;
-        if (connectionContext.getConnectionAdapter().isAlive()) {
-            result = JdkFutureAdapters.listenInPoolThread(connectionContext.getConnectionAdapter().disconnect());
+        if (connectionAdapter.isAlive()) {
+            result = JdkFutureAdapters.listenInPoolThread(connectionAdapter.disconnect());
         } else {
             LOG.debug("connection already disconnected");
             result = Futures.immediateFuture(true);
@@ -117,22 +127,27 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
         Futures.addCallback(result, new FutureCallback<Boolean>() {
             @Override
             public void onSuccess(final Boolean aBoolean) {
-                LOG.debug("Connection node={}|auxId={}|connection state = {} closed.",
-                        connectionContext.getConnectionAdapter().getRemoteAddress(),
-                        connectionContext.getFeatures().getAuxiliaryId(),
-                        connectionContext.getConnectionState());
+                LOG.debug("Connection node={}|auxId={}|connection state = {}, closed successfully:{}.",
+                        remoteAddress,
+                        auxiliaryId,
+                        connectionContext.getConnectionState(),
+                        aBoolean);
             }
 
             @Override
             public void onFailure(final Throwable throwable) {
                 LOG.debug("Connection node={}|auxId={}|connection state = {} close failed.",
-                        connectionContext.getConnectionAdapter().getRemoteAddress(),
-                        connectionContext.getFeatures().getAuxiliaryId(),
+                        remoteAddress,
+                        auxiliaryId,
                         connectionContext.getConnectionState());
             }
         });
 
         connectionContext.propagateClosingConnection();
+        try {
+            handshakeContext.close();
+        } catch (Exception e) {
+            LOG.debug("Closing of handshake context wasn't successfull. {}", e);
+        }
     }
-
 }