Convert NettyBootstrapFactory into a Component
[ovsdb.git] / library / impl / src / main / java / org / opendaylight / ovsdb / lib / impl / NettyBootstrapFactoryImpl.java
1 /*
2  * Copyright © 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.ovsdb.lib.impl;
9
10 import com.google.common.util.concurrent.ThreadFactoryBuilder;
11 import io.netty.bootstrap.Bootstrap;
12 import io.netty.bootstrap.ServerBootstrap;
13 import io.netty.channel.AdaptiveRecvByteBufAllocator;
14 import io.netty.channel.ChannelOption;
15 import io.netty.channel.EventLoopGroup;
16 import io.netty.channel.epoll.Epoll;
17 import io.netty.channel.epoll.EpollEventLoopGroup;
18 import io.netty.channel.epoll.EpollServerSocketChannel;
19 import io.netty.channel.epoll.EpollSocketChannel;
20 import io.netty.channel.nio.NioEventLoopGroup;
21 import io.netty.channel.socket.nio.NioServerSocketChannel;
22 import io.netty.channel.socket.nio.NioSocketChannel;
23 import java.util.concurrent.ThreadFactory;
24 import javax.annotation.PreDestroy;
25 import javax.inject.Inject;
26 import javax.inject.Singleton;
27 import org.osgi.service.component.annotations.Activate;
28 import org.osgi.service.component.annotations.Component;
29 import org.osgi.service.component.annotations.Deactivate;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * A globally-instantiated context for use with OvsdbConnectionService.
35  */
36 @Singleton
37 @Component(service = NettyBootstrapFactory.class)
38 public final class NettyBootstrapFactoryImpl implements NettyBootstrapFactory, AutoCloseable {
39     private abstract static class Provider {
40         /**
41          * Return user friendly name, suitable for system operators.
42          *
43          * @return An admin-friendly name.
44          */
45         abstract String name();
46
47         abstract EventLoopGroup createGroup(ThreadFactory threadFactory);
48
49         abstract Bootstrap createBootstrap();
50
51         abstract ServerBootstrap createServerBootstrap();
52     }
53
54     private static final class EpollProvider extends Provider {
55         @Override
56         String name() {
57             return "epoll(7)";
58         }
59
60         @Override
61         EventLoopGroup createGroup(final ThreadFactory threadFactory) {
62             return new EpollEventLoopGroup(0, threadFactory);
63         }
64
65         @Override
66         Bootstrap createBootstrap() {
67             return new Bootstrap()
68                     .channel(EpollSocketChannel.class);
69         }
70
71         @Override
72         ServerBootstrap createServerBootstrap() {
73             return new ServerBootstrap()
74                     .channel(EpollServerSocketChannel.class);
75         }
76     }
77
78     private static final class NioProvider extends Provider {
79         @Override
80         String name() {
81             return "java.nio";
82         }
83
84         @Override
85         EventLoopGroup createGroup(final ThreadFactory threadFactory) {
86             return new NioEventLoopGroup(0, threadFactory);
87         }
88
89         @Override
90         Bootstrap createBootstrap() {
91             return new Bootstrap()
92                     .channel(NioSocketChannel.class);
93         }
94
95         @Override
96         ServerBootstrap createServerBootstrap() {
97             return new ServerBootstrap()
98                     .channel(NioServerSocketChannel.class);
99         }
100     }
101
102     private static final Logger LOG = LoggerFactory.getLogger(NettyBootstrapFactoryImpl.class);
103
104     // Minimum footprint runtime-constant
105     private static final Provider PROVIDER = Epoll.isAvailable() ? new EpollProvider() : new NioProvider();
106
107     private final EventLoopGroup bossGroup;
108     private final EventLoopGroup workerGroup;
109
110     @Inject
111     @Activate
112     public NettyBootstrapFactoryImpl() {
113         bossGroup = PROVIDER.createGroup(new ThreadFactoryBuilder().setNameFormat("OVSDB listener-%d").build());
114         workerGroup = PROVIDER.createGroup(new ThreadFactoryBuilder().setNameFormat("OVSDB connection-%d").build());
115         LOG.info("OVSDB global Netty context started with {}", PROVIDER.name());
116     }
117
118     @PreDestroy
119     @Deactivate
120     @Override
121     public void close() {
122         LOG.info("OVSDB global Netty context terminating");
123         bossGroup.shutdownGracefully().addListener(ignore -> {
124             LOG.info("OVSDB global server group terminated");
125         });
126         workerGroup.shutdownGracefully().addListener(ignore -> {
127             LOG.info("OVSDB global channel group terminated");
128         });
129     }
130
131     @Override
132     public Bootstrap newClient() {
133         return PROVIDER.createBootstrap()
134                 .group(workerGroup)
135                 .option(ChannelOption.TCP_NODELAY, true)
136                 .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(65535, 65535, 65535));
137     }
138
139     @Override
140     public ServerBootstrap newServer() {
141         return PROVIDER.createServerBootstrap()
142                 .group(bossGroup, workerGroup)
143                 .option(ChannelOption.TCP_NODELAY, true)
144                 .option(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(65535, 65535, 65535))
145                 .option(ChannelOption.SO_BACKLOG, 100);
146     }
147 }