Merge "Fix channelInactive event handling in the netty pipeline for netconf."
[controller.git] / opendaylight / commons / protocol-framework / src / main / java / org / opendaylight / protocol / framework / ReconnectPromise.java
index fe1012f443fc7824b1e2b8b3d3c4ed15ecbfb30d..aaec95a74b5886150c8d0bc4bb7d11a1a1570dbf 100644 (file)
@@ -48,9 +48,11 @@ final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionList
             @Override
             public void initializeChannel(final SocketChannel channel, final Promise<S> promise) {
                 initializer.initializeChannel(channel, promise);
-
                 // add closed channel handler
-                channel.pipeline().addFirst(new ClosedChannelHandler(ReconnectPromise.this));
+                // This handler has to be added as last channel handler and the channel inactive event has to be caught by it
+                // Handlers in front of it can react to channelInactive event, but have to forward the event or the reconnect will not work
+                // This handler is last so all handlers in front of it can handle channel inactive (to e.g. resource cleanup) before a new connection is started
+                channel.pipeline().addLast(new ClosedChannelHandler(ReconnectPromise.this));
             }
         });
     }
@@ -77,7 +79,7 @@ final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionList
 
     /**
      * Channel handler that responds to channelInactive event and reconnects the session.
-     * Only if the initial connection was successfully established and promise was not canceled.
+     * Only if the promise was not canceled.
      */
     private static final class ClosedChannelHandler extends ChannelInboundHandlerAdapter {
         private final ReconnectPromise<?, ?> promise;
@@ -88,14 +90,13 @@ final class ReconnectPromise<S extends ProtocolSession<?>, L extends SessionList
 
         @Override
         public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
+            // This is the ultimate channel inactive handler, not forwarding
             if (promise.isCancelled()) {
                 return;
             }
 
-            // Check if initial connection was fully finished. If the session was dropped during negotiation, reconnect will not happen.
-            // Session can be dropped during negotiation on purpose by the client side and would make no sense to initiate reconnect
             if (promise.isInitialConnectFinished() == false) {
-                return;
+                LOG.debug("Connection to {} was dropped during negotiation, reattempting", promise.address);
             }
 
             LOG.debug("Reconnecting after connection to {} was dropped", promise.address);