Add support for using epoll Netty transport 62/86162/12
authorRobert Varga <robert.varga@pantheon.tech>
Tue, 3 Dec 2019 15:54:47 +0000 (16:54 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 5 Dec 2019 22:32:37 +0000 (23:32 +0100)
Since we have GlobalNettyContext, we can easily provide the necessary
glue to select either epoll(7) or java.nio backend based on availability.

JIRA: OVSDB-331
Change-Id: Id79e13e21dd5bc2358b7a9567bd145a4ca166a39
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
library/impl/pom.xml
library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/NettyBootstrapFactory.java

index 970f9196c20739ac7a5b171c77bd73164a8b66cc..0a7f3d2b5098b7b8d355fe29b0573ea9803f6216 100644 (file)
@@ -67,6 +67,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <groupId>io.netty</groupId>
       <artifactId>netty-transport</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-transport-native-epoll</artifactId>
+      <classifier>linux-x86_64</classifier>
+    </dependency>
+
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
index 0449cf0952ccb6dcbb8d4bce131fc45079f781b7..1d2195787ffc111120ce5d0ef367f4933e103c64 100644 (file)
@@ -13,9 +13,14 @@ import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.AdaptiveRecvByteBufAllocator;
 import io.netty.channel.ChannelOption;
 import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.epoll.EpollSocketChannel;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
 import io.netty.channel.socket.nio.NioSocketChannel;
+import java.util.concurrent.ThreadFactory;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -27,30 +32,94 @@ import org.slf4j.LoggerFactory;
  */
 @Singleton
 public class NettyBootstrapFactory implements AutoCloseable {
+    private abstract static class Provider {
+        /**
+         * Return user friendly name, suitable for system operators.
+         *
+         * @return An admin-friendly name.
+         */
+        abstract String name();
+
+        abstract EventLoopGroup createGroup(ThreadFactory threadFactory);
+
+        abstract Bootstrap createBootstrap();
+
+        abstract ServerBootstrap createServerBootstrap();
+    }
+
+    private static final class EpollProvider extends Provider {
+        @Override
+        String name() {
+            return "epoll(7)";
+        }
+
+        @Override
+        EventLoopGroup createGroup(final ThreadFactory threadFactory) {
+            return new EpollEventLoopGroup(0, threadFactory);
+        }
+
+        @Override
+        Bootstrap createBootstrap() {
+            return new Bootstrap()
+                    .channel(EpollSocketChannel.class);
+        }
+
+        @Override
+        ServerBootstrap createServerBootstrap() {
+            return new ServerBootstrap()
+                    .channel(EpollServerSocketChannel.class);
+        }
+    }
+
+    private static final class NioProvider extends Provider {
+        @Override
+        String name() {
+            return "java.nio";
+        }
+
+        @Override
+        EventLoopGroup createGroup(final ThreadFactory threadFactory) {
+            return new NioEventLoopGroup(0, threadFactory);
+        }
+
+        @Override
+        Bootstrap createBootstrap() {
+            return new Bootstrap()
+                    .channel(NioSocketChannel.class);
+        }
+
+        @Override
+        ServerBootstrap createServerBootstrap() {
+            return new ServerBootstrap()
+                    .channel(NioServerSocketChannel.class);
+        }
+    }
+
     private static final Logger LOG = LoggerFactory.getLogger(NettyBootstrapFactory.class);
 
-    private final EventLoopGroup bossGroup = new NioEventLoopGroup(0,
-        new ThreadFactoryBuilder().setNameFormat("OVSDB listener-%d").build());
-    private final EventLoopGroup workerGroup = new NioEventLoopGroup(0,
-        new ThreadFactoryBuilder().setNameFormat("OVSDB connection-%d").build());
+    // Minimum footprint runtime-constant
+    private static final Provider PROVIDER = Epoll.isAvailable() ? new EpollProvider() : new NioProvider();
+
+    private final EventLoopGroup bossGroup;
+    private final EventLoopGroup workerGroup;
 
     @Inject
     public NettyBootstrapFactory() {
-        LOG.info("OVSDB global Netty context instantiated");
+        bossGroup = PROVIDER.createGroup(new ThreadFactoryBuilder().setNameFormat("OVSDB listener-%d").build());
+        workerGroup = PROVIDER.createGroup(new ThreadFactoryBuilder().setNameFormat("OVSDB connection-%d").build());
+        LOG.info("OVSDB global Netty context started with {}", PROVIDER.name());
     }
 
     Bootstrap newClient() {
-        return new Bootstrap()
+        return PROVIDER.createBootstrap()
                 .group(workerGroup)
-                .channel(NioSocketChannel.class)
                 .option(ChannelOption.TCP_NODELAY, true)
                 .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(65535, 65535, 65535));
     }
 
     ServerBootstrap newServer() {
-        return new ServerBootstrap()
+        return PROVIDER.createServerBootstrap()
                 .group(bossGroup, workerGroup)
-                .channel(NioServerSocketChannel.class)
                 .option(ChannelOption.TCP_NODELAY, true)
                 .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(65535, 65535, 65535))
                 .option(ChannelOption.SO_BACKLOG, 100);