BUG-3579: device disconnection cleanup 81/22181/1
authorMartin Bobak <mbobak@cisco.com>
Thu, 4 Jun 2015 07:19:33 +0000 (09:19 +0200)
committermichal rehak <mirehak@cisco.com>
Tue, 9 Jun 2015 10:52:39 +0000 (10:52 +0000)
 - connection + handshake revisited
 - device, rpc, statistics contexts/managers revisited
 - cleaned up logging
 - adapted tests
 - added propagating to connectionCtx close for timeout

Change-Id: I990012ecb34fd3a229c1988cbd1c2b71af6ec98e
Signed-off-by: Michal Rehak <mirehak@cisco.com>
Signed-off-by: Martin Bobak <mbobak@cisco.com>
(cherry picked from commit d54deb3112a9ee9cf71571cffd9fb40806d5bed2)

16 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/connection/ConnectionContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcContext.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/ConnectionReadyListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/OpenflowProtocolListenerInitialImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/SystemNotificationsListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceTransactionChainManagerProvider.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java [deleted file]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/listener/SystemNotificationsListenerImplTest.java

index bbbffdc0f2d196a70b4778661af7f13942edc59d..695a206caed662ce27d09b95f50b146a56916fa4 100644 (file)
@@ -22,7 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731
  * </p>
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 25.2.2015.
  */
-public interface ConnectionContext extends AutoCloseable {
+public interface ConnectionContext {
 
     /**
      * distinguished connection states
@@ -71,11 +71,11 @@ public interface ConnectionContext extends AutoCloseable {
      * @return
      */
     OutboundQueue getOutboundQueueProvider();
+
     /**
      * Method sets reference to OFJava outbound queue provider.
-     *
      */
-    void setOutboundQueueProvider(OutboundQueueProvider  outboundQueueProvider);
+    void setOutboundQueueProvider(OutboundQueueProvider outboundQueueProvider);
 
     /**
      * Method returns current connection state.
@@ -84,13 +84,6 @@ public interface ConnectionContext extends AutoCloseable {
      */
     CONNECTION_STATE getConnectionState();
 
-    /**
-     * Method sets connection state of current context.
-     *
-     * @param connectionState
-     */
-    void setConnectionState(CONNECTION_STATE connectionState);
-
     /**
      * @param featuresReply as received from device during handshake
      */
@@ -108,13 +101,34 @@ public interface ConnectionContext extends AutoCloseable {
      */
     void setDeviceDisconnectedHandler(DeviceDisconnectedHandler deviceDisconnectedHandler);
 
+    void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration);
+
     /**
-     * Method provides propagates info about closed connection to handler for handling closing connections.
+     * actively drop associated connection
+     *
+     * @param propagate true if event need to be propagated to higher contexts (device, stats, rpc..)
+     *                  or false if invoked from higher context
+     * @see ConnectionAdapter#disconnect()
      */
-    void propagateClosingConnection();
+    void closeConnection(boolean propagate);
 
-    void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration);
+    /**
+     * cleanup context upon connection closed event (by device)
+     */
+    void onConnectionClosed();
+
+    /**
+     * change internal state to {@link ConnectionContext.CONNECTION_STATE#HANDSHAKING}
+     */
+    void changeStateToHandshaking();
 
-    @Override
-    void close();
+    /**
+     * change internal state to {@link ConnectionContext.CONNECTION_STATE#TIMEOUTING}
+     */
+    void changeStateToTimeouting();
+
+    /**
+     * change internal state to {@link ConnectionContext.CONNECTION_STATE#WORKING}
+     */
+    void changeStateToWorking();
 }
index 423af6865f619973069dae27041a74a9989d612e..6c3e4e5521b645e48fabf030eacbfed1ecfab36f 100644 (file)
@@ -164,8 +164,6 @@ public interface DeviceContext extends AutoCloseable,
 
     MessageSpy getMessageSpy();
 
-    void setDeviceDisconnectedHandler(DeviceDisconnectedHandler deviceDisconnectedHandler);
-
     /**
      * Method sets reference to handler used for cleanup after device context about to be closed.
      */
index cb14a136691a7a31826f50df9b3e25f3bdcae3cb..ec8c7e7bcf65713755fef35d998f48cda21c688a 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.openflowplugin.api.openflow.rpc;
 
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceContextClosedHandler;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 
 /**
@@ -18,6 +18,6 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
  * <p>
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 25.2.2015.
  */
-public interface RpcContext extends RequestContextStack, AutoCloseable, DeviceDisconnectedHandler {
+public interface RpcContext extends RequestContextStack, AutoCloseable, DeviceContextClosedHandler {
     <S extends RpcService> void registerRpcServiceImplementation(Class<S> serviceClass, S serviceInstance);
 }
index 0453c23eef920b9e0ad7f62d2e7a1e12024f2127..dea0ecb187f0eac894481fc986ec7ec9ead353f5 100644 (file)
@@ -1,12 +1,14 @@
 /**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * <p/>
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 package org.opendaylight.openflowplugin.impl.connection;
 
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
@@ -69,11 +71,6 @@ public class ConnectionContextImpl implements ConnectionContext {
         this.nodeId = nodeId;
     }
 
-    @Override
-    public void setConnectionState(final CONNECTION_STATE connectionState) {
-        this.connectionState = connectionState;
-    }
-
     @Override
     public FeaturesReply getFeatures() {
         return featuresReply;
@@ -84,25 +81,65 @@ public class ConnectionContextImpl implements ConnectionContext {
         this.deviceDisconnectedHandler = deviceDisconnectedHandler;
     }
 
-    @Override
-    public void propagateClosingConnection() {
-        if (null != deviceDisconnectedHandler) {
-            LOG.trace("Populating connection closed event.");
-            this.deviceDisconnectedHandler.onDeviceDisconnected(this);
-        }
-    }
-
     @Override
     public void setFeatures(final FeaturesReply featuresReply) {
         this.featuresReply = featuresReply;
     }
 
     @Override
-    public void close() {
+    public void closeConnection(boolean propagate) {
+        final BigInteger datapathId = featuresReply != null ? featuresReply.getDatapathId() : BigInteger.ZERO;
+        LOG.debug("Actively closing connection: {}, datapathId:{}.",
+                connectionAdapter.getRemoteAddress(), datapathId);
+        connectionState = ConnectionContext.CONNECTION_STATE.RIP;
+
+        unregisterOutboundQueue();
         if (getConnectionAdapter().isAlive()) {
-            setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
             getConnectionAdapter().disconnect();
         }
+
+        if (propagate) {
+            propagateDeviceDisconnectedEvent();
+        }
+    }
+
+    @Override
+    public void onConnectionClosed() {
+        connectionState = ConnectionContext.CONNECTION_STATE.RIP;
+
+        final InetSocketAddress remoteAddress = connectionAdapter.getRemoteAddress();
+        final Short auxiliaryId;
+        if (null != getFeatures() && null != getFeatures().getAuxiliaryId()) {
+            auxiliaryId = getFeatures().getAuxiliaryId();
+        } else {
+            auxiliaryId = 0;
+        }
+
+        LOG.debug("disconnecting: node={}|auxId={}|connection state = {}",
+                remoteAddress,
+                auxiliaryId,
+                getConnectionState());
+
+        unregisterOutboundQueue();
+
+        propagateDeviceDisconnectedEvent();
+    }
+
+    private void propagateDeviceDisconnectedEvent() {
+        if (null != deviceDisconnectedHandler) {
+            final BigInteger datapathId = featuresReply != null ? featuresReply.getDatapathId() : BigInteger.ZERO;
+            LOG.debug("Propagating connection closed event: {}, datapathId:{}.",
+                    connectionAdapter.getRemoteAddress(), datapathId);
+            deviceDisconnectedHandler.onDeviceDisconnected(this);
+        }
+    }
+
+    @Override
+    public void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration) {
+        this.outboundQueueHandlerRegistration = outboundQueueHandlerRegistration;
+    }
+
+    private void unregisterOutboundQueue() {
         if (outboundQueueHandlerRegistration != null) {
             outboundQueueHandlerRegistration.close();
             outboundQueueHandlerRegistration = null;
@@ -110,7 +147,17 @@ public class ConnectionContextImpl implements ConnectionContext {
     }
 
     @Override
-    public void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration) {
-        this.outboundQueueHandlerRegistration = outboundQueueHandlerRegistration;
+    public void changeStateToHandshaking() {
+        connectionState = CONNECTION_STATE.HANDSHAKING;
+    }
+
+    @Override
+    public void changeStateToTimeouting() {
+        connectionState = CONNECTION_STATE.TIMEOUTING;
+    }
+
+    @Override
+    public void changeStateToWorking() {
+        connectionState = CONNECTION_STATE.WORKING;
     }
 }
index 7f16e813b80fcde8cb4cb119e586fa1a7d67c252..5cc50feef05da6bc798156191c41025b1fa6f4cc 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * <p/>
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -70,7 +70,7 @@ public class ConnectionManagerImpl implements ConnectionManager {
                 new OpenflowProtocolListenerInitialImpl(connectionContext, handshakeContext);
         connectionAdapter.setMessageListener(ofMessageListener);
 
-        final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext, handshakeContext);
+        final SystemNotificationsListener systemListener = new SystemNotificationsListenerImpl(connectionContext);
         connectionAdapter.setSystemListener(systemListener);
 
         LOG.trace("connection ballet finished");
@@ -94,7 +94,7 @@ public class ConnectionManagerImpl implements ConnectionManager {
      * @return
      */
     private HandshakeManager createHandshakeManager(final ConnectionAdapter connectionAdapter,
-            final HandshakeListener handshakeListener) {
+                                                    final HandshakeListener handshakeListener) {
         HandshakeManagerImpl handshakeManager = new HandshakeManagerImpl(connectionAdapter,
                 ConnectionConductor.versionOrder.get(0),
                 ConnectionConductor.versionOrder);
@@ -109,7 +109,7 @@ public class ConnectionManagerImpl implements ConnectionManager {
      * @return parameter dedicated to hello message content
      */
     public boolean isBitmapNegotiationEnabled() {
-        return bitmapNegotiationEnabled ;
+        return bitmapNegotiationEnabled;
     }
 
 
index 38dab4305a43e30bb61247b69dd01f5694807c38..7c9f0eb6f22225e720e4cd26e375261f71a94bf9 100644 (file)
@@ -43,7 +43,7 @@ public class ConnectionReadyListenerImpl implements ConnectionReadyListener {
             HandshakeStepWrapper handshakeStepWrapper = new HandshakeStepWrapper(
                     null, handshakeContext.getHandshakeManager(), connectionContext.getConnectionAdapter());
             handshakeContext.getHandshakePool().execute(handshakeStepWrapper);
-            connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.HANDSHAKING);
+            connectionContext.changeStateToHandshaking();
         } else {
             LOG.debug("already touched by hello message");
         }
index fdb1c27f267663a20b4c9071a8bccb6fcb0c70ef..2f1261e79952e7c3596f53bc48b2ef2264b4cf81 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * <p/>
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -38,7 +38,9 @@ public class HandshakeListenerImpl implements HandshakeListener {
 
     @Override
     public void onHandshakeSuccessfull(GetFeaturesOutput featureOutput, Short version) {
-        connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
+        LOG.debug("handshake succeeded: {}", connectionContext.getConnectionAdapter().getRemoteAddress());
+        closeHandshakeContext();
+        connectionContext.changeStateToWorking();
         connectionContext.setFeatures(featureOutput);
         connectionContext.setNodeId(InventoryDataServiceUtil.nodeIdFromDatapathId(featureOutput.getDatapathId()));
         deviceConnectedHandler.deviceConnected(connectionContext);
@@ -46,8 +48,12 @@ public class HandshakeListenerImpl implements HandshakeListener {
 
     @Override
     public void onHandshakeFailure() {
-        LOG.info("handshake failed: {}", connectionContext.getConnectionAdapter().getRemoteAddress());
-        connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
+        LOG.debug("handshake failed: {}", connectionContext.getConnectionAdapter().getRemoteAddress());
+        closeHandshakeContext();
+        connectionContext.closeConnection(false);
+    }
+
+    private void closeHandshakeContext() {
         try {
             handshakeContext.close();
         } catch (Exception e) {
index a69696a6734d0d06753aa2c8ed2055af1fefa231..e93cc70ae0088ec862b5e3be0cac7d0a307e92b4 100644 (file)
@@ -75,7 +75,7 @@ public class OpenflowProtocolListenerInitialImpl implements OpenflowProtocolList
     public void onHelloMessage(final HelloMessage hello) {
         LOG.debug("processing HELLO.xid: {}", hello.getXid());
         if (connectionContext.getConnectionState() == null) {
-            connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.HANDSHAKING);
+            connectionContext.changeStateToHandshaking();
         }
 
         if (checkState(ConnectionContext.CONNECTION_STATE.HANDSHAKING)) {
index 91a69e335e4cabb85c1d536b5b7d47fc3ed7a7a0..de1619895ef44294731546f57ef42ce6d2aca66b 100644 (file)
@@ -8,16 +8,12 @@
 package org.opendaylight.openflowplugin.impl.connection.listener;
 
 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;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.base.Preconditions;
 import java.net.InetSocketAddress;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
-import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
 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;
@@ -36,20 +32,17 @@ import org.slf4j.LoggerFactory;
 public class SystemNotificationsListenerImpl implements SystemNotificationsListener {
 
     private final ConnectionContext connectionContext;
-    HandshakeContext handshakeContext;
     private static final Logger LOG = LoggerFactory.getLogger(SystemNotificationsListenerImpl.class);
     @VisibleForTesting
     static final long MAX_ECHO_REPLY_TIMEOUT = 2000;
 
-    public SystemNotificationsListenerImpl(final ConnectionContext connectionContext,
-            final HandshakeContext handshakeContext) {
-        this.connectionContext = connectionContext;
-        this.handshakeContext = handshakeContext;
+    public SystemNotificationsListenerImpl(@Nonnull final ConnectionContext connectionContext) {
+        this.connectionContext = Preconditions.checkNotNull(connectionContext);
     }
 
     @Override
     public void onDisconnectEvent(final DisconnectEvent notification) {
-        disconnect();
+        connectionContext.onConnectionClosed();
     }
 
     @Override
@@ -66,7 +59,7 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
                     LOG.debug(
                             "first idle state occured, node={}|auxId={}",
                             remoteAddress, features.getAuxiliaryId());
-                    connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
+                    connectionContext.changeStateToTimeouting();
                     EchoInputBuilder builder = new EchoInputBuilder();
                     builder.setVersion(features.getVersion());
                     Xid xid = new Xid(0L);
@@ -78,7 +71,7 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
                     try {
                         RpcResult<EchoOutput> echoReplyValue = echoReplyFuture.get(MAX_ECHO_REPLY_TIMEOUT, TimeUnit.MILLISECONDS);
                         if (echoReplyValue.isSuccessful()) {
-                            connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
+                            connectionContext.changeStateToWorking();
                             shouldBeDisconnected = false;
                         } else {
                             for (RpcError replyError : echoReplyValue
@@ -96,58 +89,9 @@ public class SystemNotificationsListenerImpl implements SystemNotificationsListe
                     }
                 }
                 if (shouldBeDisconnected) {
-                    disconnect();
+                    connectionContext.closeConnection(true);
                 }
             }
         }).start();
     }
-
-    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 = {}",
-                remoteAddress,
-                auxiliaryId,
-                connectionContext.getConnectionState());
-
-        ListenableFuture<Boolean> result = null;
-        if (connectionAdapter.isAlive()) {
-            result = JdkFutureAdapters.listenInPoolThread(connectionAdapter.disconnect());
-        } else {
-            LOG.debug("connection already disconnected");
-            result = Futures.immediateFuture(true);
-        }
-        connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-        Futures.addCallback(result, new FutureCallback<Boolean>() {
-            @Override
-            public void onSuccess(final Boolean aBoolean) {
-                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.",
-                        remoteAddress,
-                        auxiliaryId,
-                        connectionContext.getConnectionState());
-            }
-        });
-
-        connectionContext.propagateClosingConnection();
-        try {
-            handshakeContext.close();
-        } catch (Exception e) {
-            LOG.debug("Closing of handshake context wasn't successfull. {}", e);
-        }
-    }
 }
index 9b06829957177129aceca6491f4c64741614f65a..0f70c7ac1e06c65102ceca7f13df3d198db97ea1 100644 (file)
@@ -38,7 +38,6 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceContextClosedHandler;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
@@ -104,7 +103,6 @@ public class DeviceContextImpl implements DeviceContext {
     private final PacketInRateLimiter packetInLimiter;
     private final MessageSpy messageSpy;
     private NotificationPublishService notificationPublishService;
-    private DeviceDisconnectedHandler deviceDisconnectedHandler;
     private NotificationService notificationService;
     private final OutboundQueue outboundQueueProvider;
     private Timeout barrierTaskTimeout;
@@ -333,16 +331,26 @@ public class DeviceContextImpl implements DeviceContext {
 
     @Override
     public void close() {
+        LOG.debug("closing deviceContext: {}, nodeId:{}",
+                getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress(),
+                getDeviceState().getNodeId());
+
+        tearDown();
+
+        primaryConnectionContext.closeConnection(false);
+    }
+
+    private void tearDown() {
         deviceState.setValid(false);
 
+        for (final ConnectionContext connectionContext : auxiliaryConnectionContexts.values()) {
+            connectionContext.closeConnection(false);
+        }
+
         deviceGroupRegistry.close();
         deviceFlowRegistry.close();
         deviceMeterRegistry.close();
 
-        primaryConnectionContext.close();
-        for (final ConnectionContext connectionContext : auxiliaryConnectionContexts.values()) {
-            connectionContext.close();
-        }
 
         for (final DeviceContextClosedHandler deviceContextClosedHandler : closeHandlers) {
             deviceContextClosedHandler.onDeviceContextClosed(this);
@@ -355,14 +363,14 @@ public class DeviceContextImpl implements DeviceContext {
     public void onDeviceDisconnected(final ConnectionContext connectionContext) {
         if (getPrimaryConnectionContext().equals(connectionContext)) {
             try {
-                close();
+                tearDown();
             } catch (final Exception e) {
                 LOG.trace("Error closing device context.");
             }
-            if (null != deviceDisconnectedHandler) {
-                deviceDisconnectedHandler.onDeviceDisconnected(connectionContext);
-            }
         } else {
+            LOG.debug("auxiliary connection dropped: {}, nodeId:{}",
+                    connectionContext.getConnectionAdapter().getRemoteAddress(),
+                    getDeviceState().getNodeId());
             final SwitchConnectionDistinguisher connectionDistinguisher = createConnectionDistinguisher(connectionContext);
             auxiliaryConnectionContexts.remove(connectionDistinguisher);
         }
@@ -393,11 +401,6 @@ public class DeviceContextImpl implements DeviceContext {
         return messageSpy;
     }
 
-    @Override
-    public void setDeviceDisconnectedHandler(final DeviceDisconnectedHandler deviceDisconnectedHandler) {
-        this.deviceDisconnectedHandler = deviceDisconnectedHandler;
-    }
-
     @Override
     public void addDeviceContextClosedHandler(final DeviceContextClosedHandler deviceContextClosedHandler) {
         closeHandlers.add(deviceContextClosedHandler);
index 281ba53df91a7b4ad318188bcd2dd0d1521eb9c1..d889bd066b3372ea0e42cc28a0d49f611385abb9 100644 (file)
@@ -443,7 +443,7 @@ public class DeviceManagerImpl implements DeviceManager, AutoCloseable, ReadyFor
             public void onSuccess(final RpcResult<List<MultipartReply>> rpcResult) {
                 final List<MultipartReply> result = rpcResult.getResult();
                 if (result != null) {
-                    LOG.info("Static node {} info: {} collected", nodeII.toString(), type);
+                    LOG.info("Static node {} info: {} collected", deviceContext.getDeviceState().getNodeId(), type);
                     translateAndWriteReply(type, deviceContext, nodeII, result);
                 } else {
                     final Iterator<RpcError> rpcErrorIterator = rpcResult.getErrors().iterator();
index 2f1d4cda4f1f783d55a799ca970e606680e4e063..703fdf583d76e3cab61935afe0d09b087cf071eb 100644 (file)
@@ -48,7 +48,7 @@ public class DeviceTransactionChainManagerProvider {
                     if (!transactionChainManager.attemptToRegisterHandler(readyForNewTransactionChainHandler)) {
                         if (TransactionChainManager.TransactionChainManagerStatus.WORKING.equals(transactionChainManager.getTransactionChainManagerStatus())) {
                             LOG.info("There already exists one handler for connection described as {}. Connection is working will not try again.", nodeId);
-                            connectionContext.close();
+                            connectionContext.closeConnection(false);
                         } else {
                             LOG.info("There already exists one handler for connection described as {}. Transaction chain manager is in state {}. Will try again.",
                                     nodeId,
index 528fde155cbd7e900ff2fede791b4310561d995d..7c39f128f1203307aa6d6870a990e98ed50aa7f8 100644 (file)
@@ -13,7 +13,6 @@ import java.util.HashSet;
 import java.util.concurrent.Semaphore;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
@@ -84,7 +83,7 @@ public class RpcContextImpl implements RpcContext {
     }
 
     @Override
-    public void onDeviceDisconnected(final ConnectionContext connectionContext) {
+    public void onDeviceContextClosed(DeviceContext deviceContext) {
         for (RoutedRpcRegistration<?> registration : rpcRegistrations) {
             registration.close();
         }
index 975fcdd5566ae175ce61b2d49ea142a52d2aa448..1b8e5f76b1928febc0537f5f70112d7f97e40f8d 100644 (file)
@@ -34,7 +34,7 @@ public class RpcManagerImpl implements RpcManager {
     @Override
     public void onDeviceContextLevelUp(final DeviceContext deviceContext) {
         final RpcContext rpcContext = new RpcContextImpl(deviceContext.getMessageSpy(), rpcProviderRegistry, deviceContext, maxRequestsQuota);
-        deviceContext.setDeviceDisconnectedHandler(rpcContext);
+        deviceContext.addDeviceContextClosedHandler(rpcContext);
         MdSalRegistratorUtils.registerServices(rpcContext, deviceContext);
         // finish device initialization cycle back to DeviceManager
         deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImplTest.java
deleted file mode 100644 (file)
index b2257cf..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.openflowplugin.impl.connection;
-
-import static org.junit.Assert.fail;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
-
-/**
- * openflowplugin-impl
- * org.opendaylight.openflowplugin.impl.connection
- * <p/>
- * test of {@link ConnectionContextImpl} - lightweight version, using basic ways (TDD)
- *
- * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
- *         <p/>
- *         Created: Mar 26, 2015
- */
-@RunWith(MockitoJUnitRunner.class)
-public class ConnectionContextImplTest {
-
-
-    @Mock
-    private ConnectionAdapter conAdapter;
-
-    @Before
-    public void initialization() {
-        // place for mocking method's general behavior for ConnectorAdapter
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#ConnectionContextImpl(org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter)}.
-     */
-    @Test
-    @Ignore
-    public void testConnectionContextImpl() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getConnectionAdapter()}.
-     */
-    @Test
-    @Ignore
-    public void testGetConnectionAdapter() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getConnectionState()}.
-     */
-    @Test
-    @Ignore
-    public void testGetConnectionState() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getNodeId()}.
-     */
-    @Test
-    @Ignore
-    public void testGetNodeId() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#setConnectionState(org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext.CONNECTION_STATE)}.
-     */
-    @Test
-    @Ignore
-    public void testSetConnectionState() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#getFeatures()}.
-     */
-    @Test
-    @Ignore
-    public void testGetFeatures() {
-        fail("Not yet implemented");
-    }
-
-    /**
-     * Test method for {@link org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl#setFeatures(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply)}.
-     */
-    @Test
-    @Ignore
-    public void testSetFeatures() {
-        fail("Not yet implemented");
-    }
-}
index 118d6dfa1e41ae3fb47080eef579c16850a2aee6..8c24fcc80686073d90d2aa01c0b1c57301012dab 100644 (file)
@@ -8,24 +8,13 @@
 
 package org.opendaylight.openflowplugin.impl.connection.listener;
 
-import static org.junit.Assert.*;
-
-import org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl;
-
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.SettableFuture;
 import java.net.InetSocketAddress;
-import java.util.List;
 import org.junit.After;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -55,8 +44,6 @@ public class SystemNotificationsListenerImplTest {
     @Mock
     private FeaturesReply features;
     private ConnectionContext connectionContext;
-    @Captor
-    private ArgumentCaptor<ConnectionContext.CONNECTION_STATE> connectionStateArgumentCaptor;
 
     private SystemNotificationsListenerImpl systemNotificationsListener;
     private ConnectionContextImpl connectionContextGolem;
@@ -64,7 +51,7 @@ public class SystemNotificationsListenerImplTest {
     @Before
     public void setUp() {
         connectionContextGolem = new ConnectionContextImpl(connectionAdapter);
-        connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
+        connectionContextGolem.changeStateToWorking();
 
         Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(
                 InetSocketAddress.createUnresolved("unit-odl.example.org", 4242));
@@ -74,11 +61,7 @@ public class SystemNotificationsListenerImplTest {
         Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
         Mockito.when(connectionContext.getFeatures()).thenReturn(features);
 
-        ThreadPoolLoggingExecutor threadPoolLoggingExecutor = new ThreadPoolLoggingExecutor(2000, 2000, 0L, TimeUnit.MILLISECONDS,
-                new ArrayBlockingQueue<Runnable>(20), "OFHandshake-test identifier");
-
-        systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext,
-               new HandshakeContextImpl(threadPoolLoggingExecutor, null));
+        systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext);
     }
 
     @After
@@ -99,11 +82,8 @@ public class SystemNotificationsListenerImplTest {
         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
 
-        verifyCommonInvocations();
-        Mockito.verify(connectionAdapter).disconnect();
-        Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-        Mockito.verify(connectionContext).propagateClosingConnection();
-        assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        verifyCommonInvocationsSubSet();
+        Mockito.verify(connectionContext).onConnectionClosed();
     }
 
     /**
@@ -119,11 +99,8 @@ public class SystemNotificationsListenerImplTest {
         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
 
-        verifyCommonInvocations();
-        Mockito.verify(connectionAdapter).disconnect();
-        Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-        Mockito.verify(connectionContext).propagateClosingConnection();
-        assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        verifyCommonInvocationsSubSet();
+        Mockito.verify(connectionContext).onConnectionClosed();
     }
 
     /**
@@ -133,7 +110,7 @@ public class SystemNotificationsListenerImplTest {
      */
     @Test
     public void testOnDisconnectEvent3() throws Exception {
-        connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
+        connectionContextGolem.changeStateToTimeouting();
 
         Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
         Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
@@ -141,11 +118,8 @@ public class SystemNotificationsListenerImplTest {
         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
 
-        verifyCommonInvocations();
-        Mockito.verify(connectionAdapter).disconnect();
-        Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-        Mockito.verify(connectionContext).propagateClosingConnection();
-        assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        verifyCommonInvocationsSubSet();
+        Mockito.verify(connectionContext).onConnectionClosed();
     }
 
     /**
@@ -155,18 +129,15 @@ public class SystemNotificationsListenerImplTest {
      */
     @Test
     public void testOnDisconnectEvent4() throws Exception {
-        connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
+//    TODO: solve    connectionContextGolem.chansetConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
 
         Mockito.when(connectionAdapter.isAlive()).thenReturn(false);
 
         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
 
-        verifyCommonInvocations();
-        Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
-        Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-        Mockito.verify(connectionContext).propagateClosingConnection();
-        assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        verifyCommonInvocationsSubSet();
+        Mockito.verify(connectionContext).onConnectionClosed();
     }
 
     /**
@@ -187,18 +158,11 @@ public class SystemNotificationsListenerImplTest {
         EchoOutput echoReplyVal = new EchoOutputBuilder().build();
         echoReply.set(RpcResultBuilder.success(echoReplyVal).build());
 
-        Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
-                .setConnectionState(connectionStateArgumentCaptor.capture());
-        List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
-        Assert.assertEquals(2, allStates.size());
-        Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
-        Assert.assertEquals(ConnectionContext.CONNECTION_STATE.WORKING, allStates.get(1));
-
         verifyCommonInvocations();
         Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
-        Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT)).setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
         Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
-        assertFalse(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        Mockito.verify(connectionContext).changeStateToTimeouting();
+        Mockito.verify(connectionContext).changeStateToWorking();
     }
 
     /**
@@ -220,21 +184,18 @@ public class SystemNotificationsListenerImplTest {
 
         verifyCommonInvocations();
         Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
-        Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
-                .setConnectionState(connectionStateArgumentCaptor.capture());
-        List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
-        Assert.assertEquals(2, allStates.size());
-        Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
-        Assert.assertEquals(ConnectionContext.CONNECTION_STATE.RIP, allStates.get(1));
-
         Mockito.verify(connectionAdapter).disconnect();
-        Mockito.verify(connectionContext).propagateClosingConnection();
-        assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+        Mockito.verify(connectionContext).changeStateToTimeouting();
+        Mockito.verify(connectionContext).closeConnection(true);
     }
 
     private void verifyCommonInvocations() {
+        verifyCommonInvocationsSubSet();
+        Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionAdapter();
+    }
+
+    private void verifyCommonInvocationsSubSet() {
         Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionState();
         Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getFeatures();
-        Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionAdapter();
     }
 }
\ No newline at end of file