Bug 6185 - southbound system tests failing when
[ovsdb.git] / library / impl / src / main / java / org / opendaylight / ovsdb / lib / jsonrpc / ExceptionHandler.java
index 8a932d3ddcc76060f4f5d8227086d153d368d301..6cf9e0e33c56b8432c70cf2cea85f6639e0d3642 100644 (file)
@@ -8,26 +8,62 @@
 
 package org.opendaylight.ovsdb.lib.jsonrpc;
 
-import io.netty.channel.ChannelHandlerAdapter;
+import io.netty.channel.ChannelDuplexHandler;
 import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.DecoderException;
 import io.netty.handler.codec.TooLongFrameException;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.handler.timeout.ReadTimeoutException;
+import java.io.IOException;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.error.InvalidEncodingException;
+import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
+public class ExceptionHandler extends ChannelDuplexHandler {
 
-public class ExceptionHandler extends ChannelHandlerAdapter {
+    private static final Logger LOG = LoggerFactory.getLogger(ExceptionHandler.class);
 
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        if ((cause instanceof InvalidEncodingException)
-                || (cause instanceof TooLongFrameException)) {
-            ctx.channel().disconnect();
-        }
+        if (ctx.channel().isActive()) {
+            LOG.error("Exception occurred while processing connection pipeline", cause);
+            if ((cause instanceof InvalidEncodingException)
+                    || (cause instanceof TooLongFrameException || (cause instanceof DecoderException))) {
+                LOG.info("Disconnecting channel to ovsdb {}", ctx.channel());
+                ctx.channel().disconnect();
+                return;
+            }
+
         /* In cases where a connection is quickly established and the closed
-        Catch the IOException and close the channel
+        Catch the IOException and close the channel. Similarly if the peer is
+        powered off, Catch the read time out exception and close the channel
          */
-        if (cause instanceof IOException) {
-            ctx.channel().close();
+            if ((cause instanceof IOException ) || (cause instanceof ReadTimeoutException)) {
+                LOG.info("Closing channel to ovsdb {}", ctx.channel());
+                ctx.channel().close();
+                return;
+            }
+
+            LOG.error("Exception was not handled by the exception handler, re-throwing it for next handler");
+            ctx.fireExceptionCaught(cause);
+        }
+    }
+
+    @Override
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        if (evt instanceof IdleStateEvent) {
+            LOG.debug("Get idle state event");
+            IdleStateEvent event = (IdleStateEvent) evt;
+            if (event.state() == IdleState.READER_IDLE) {
+                LOG.debug("Reader idle state. Send echo message to peer");
+                //Send echo message to peer
+                OvsdbClient client =
+                             OvsdbConnectionService.getService().getClient(ctx.channel());
+                client.echo();
+            }
         }
     }
 }