1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.common.utility;
21
22 import io.netty.bootstrap.Bootstrap;
23 import io.netty.bootstrap.ServerBootstrap;
24 import io.netty.buffer.ByteBuf;
25 import io.netty.buffer.PooledByteBufAllocator;
26 import io.netty.buffer.Unpooled;
27 import io.netty.channel.ChannelOption;
28 import io.netty.channel.EventLoopGroup;
29 import io.netty.channel.WriteBufferWaterMark;
30 import io.netty.channel.socket.nio.NioServerSocketChannel;
31 import io.netty.channel.socket.nio.NioSocketChannel;
32 import io.netty.util.IllegalReferenceCountException;
33 import io.netty.util.concurrent.Future;
34 import org.waarp.common.logging.SysErrLogger;
35
36 import java.io.IOException;
37 import java.net.InetAddress;
38 import java.net.ServerSocket;
39
40
41
42
43 public final class WaarpNettyUtil {
44
45 private static final int TIMEOUT_MILLIS = 1000;
46
47
48
49 public static final int SIMPLE_DELAY_MS = 100;
50
51
52
53 public static final int MINIMAL_DELAY_MS = 10;
54
55 private static final int DEFAULT_LOW_WATER_MARK = 32 * 1024;
56 private static final int DEFAULT_HIGH_WATER_MARK = 64 * 1024 + 64;
57
58 private static final int BUFFER_SIZE_1MB = DEFAULT_HIGH_WATER_MARK * 16;
59
60 private WaarpNettyUtil() {
61 }
62
63 private static int getSoBufSize(final int maxBufSize) {
64 int soBuf = Math.min(maxBufSize * 16, BUFFER_SIZE_1MB);
65 if (soBuf < maxBufSize * 4) {
66 soBuf = maxBufSize * 4;
67 }
68 return soBuf;
69 }
70
71
72
73
74
75
76
77
78 public static void setBootstrap(final Bootstrap bootstrap,
79 final EventLoopGroup group,
80 final int timeout) {
81 setBootstrap(bootstrap, group, timeout, DEFAULT_LOW_WATER_MARK, true);
82 }
83
84
85
86
87
88
89
90
91
92
93 public static void setBootstrap(final Bootstrap bootstrap,
94 final EventLoopGroup group, final int timeout,
95 final int maxBufSize,
96 final boolean autoRead) {
97 bootstrap.channel(NioSocketChannel.class);
98 bootstrap.group(group);
99 bootstrap.option(ChannelOption.TCP_NODELAY, false);
100 bootstrap.option(ChannelOption.SO_REUSEADDR, true);
101 bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
102 bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout);
103 final int so_buf = getSoBufSize(maxBufSize);
104 final int lowWaterMark = Math.min(DEFAULT_LOW_WATER_MARK, maxBufSize / 2);
105 bootstrap.option(ChannelOption.SO_RCVBUF, so_buf);
106 bootstrap.option(ChannelOption.SO_SNDBUF, so_buf);
107 bootstrap.option(ChannelOption.WRITE_BUFFER_WATER_MARK,
108 new WriteBufferWaterMark(lowWaterMark, maxBufSize));
109 bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
110 if (!autoRead) {
111 bootstrap.option(ChannelOption.AUTO_READ, false);
112 }
113 }
114
115
116
117
118
119
120
121
122
123 public static void setServerBootstrap(final ServerBootstrap bootstrap,
124 final EventLoopGroup parentGroup,
125 final EventLoopGroup childGroup,
126 final int timeout) {
127 setServerBootstrap(bootstrap, parentGroup, childGroup, timeout,
128 DEFAULT_LOW_WATER_MARK, true);
129 }
130
131
132
133
134
135
136
137
138
139
140
141 public static void setServerBootstrap(final ServerBootstrap bootstrap,
142 final EventLoopGroup parentGroup,
143 final EventLoopGroup childGroup,
144 final int timeout, final int maxBufSize,
145 final boolean autoRead) {
146 bootstrap.channel(NioServerSocketChannel.class);
147 bootstrap.group(parentGroup, childGroup);
148
149 bootstrap.option(ChannelOption.SO_REUSEADDR, true);
150 bootstrap.childOption(ChannelOption.TCP_NODELAY, false);
151 bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
152 bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
153 bootstrap.childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeout);
154 final int so_buf = getSoBufSize(maxBufSize);
155 final int lowWaterMark = Math.min(DEFAULT_LOW_WATER_MARK, maxBufSize / 2);
156 bootstrap.childOption(ChannelOption.SO_RCVBUF, so_buf);
157 bootstrap.childOption(ChannelOption.SO_SNDBUF, so_buf);
158 bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
159 new WriteBufferWaterMark(lowWaterMark, maxBufSize));
160 bootstrap.childOption(ChannelOption.ALLOCATOR,
161 PooledByteBufAllocator.DEFAULT);
162 if (!autoRead) {
163 bootstrap.childOption(ChannelOption.AUTO_READ, false);
164 }
165 }
166
167
168
169
170
171
172 public static boolean availablePort(final int port) {
173 ServerSocket ss = null;
174 try {
175 ss = new ServerSocket(port);
176 ss.setReuseAddress(true);
177 return true;
178 } catch (final IOException e) {
179 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
180 } finally {
181 if (ss != null) {
182 try {
183 ss.close();
184 } catch (final Exception e) {
185 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
186 }
187 }
188 }
189 return false;
190 }
191
192
193
194
195
196
197
198 public static boolean availablePort(final int port,
199 final InetAddress localAddress) {
200 ServerSocket ss = null;
201 try {
202 ss = new ServerSocket(port, 0, localAddress);
203 ss.setReuseAddress(true);
204 return true;
205 } catch (final IOException e) {
206 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
207 } finally {
208 if (ss != null) {
209 try {
210 ss.close();
211 } catch (final Exception e) {
212 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
213 }
214 }
215 }
216 return false;
217 }
218
219
220
221
222
223
224 public static boolean awaitOrInterrupted(final Future<?> future) {
225 try {
226 while (!Thread.interrupted()) {
227 if (future.await(TIMEOUT_MILLIS)) {
228 return true;
229 }
230 }
231 } catch (final InterruptedException e) {
232 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
233 }
234 return false;
235 }
236
237
238
239
240
241
242
243 public static boolean awaitOrInterrupted(final Future<?> future,
244 final long timeMilliseconds) {
245 try {
246 if (future.await(timeMilliseconds)) {
247 return !Thread.interrupted();
248 }
249 } catch (final InterruptedException e) {
250 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
251 }
252 return false;
253 }
254
255
256
257
258
259
260
261 public static boolean awaitIsSuccessOfInterrupted(final Future<?> future) {
262 try {
263 while (!Thread.interrupted()) {
264 if (future.await(TIMEOUT_MILLIS)) {
265 return future.isSuccess();
266 }
267 }
268 } catch (final InterruptedException e) {
269 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
270 }
271 return false;
272 }
273
274
275
276
277
278
279
280
281 public static boolean release(final ByteBuf byteBuf) {
282 if (byteBuf == null || byteBuf.refCnt() <= 0) {
283 return true;
284 }
285 try {
286 return byteBuf.release();
287 } catch (final IllegalReferenceCountException e) {
288 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
289 return true;
290 }
291 }
292
293
294
295
296
297
298 public static void releaseCompletely(final ByteBuf byteBuf) {
299 if (byteBuf != null && byteBuf.refCnt() != 0) {
300 final int refCnt = byteBuf.refCnt();
301 try {
302 byteBuf.release(refCnt);
303 } catch (final IllegalReferenceCountException e) {
304 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
305 }
306 }
307 }
308
309
310
311
312
313
314 public static void retain(final ByteBuf byteBuf) {
315 if (byteBuf != null) {
316 try {
317 byteBuf.retain();
318 } catch (final IllegalReferenceCountException e) {
319 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
320 }
321 }
322 }
323
324
325
326
327
328
329
330
331
332
333
334 public static ByteBuf slice(final ByteBuf byteBuf, final int start,
335 final int size) {
336 final ByteBuf bufSliced = byteBuf.slice(start, size);
337 bufSliced.writerIndex(0);
338 return bufSliced;
339 }
340
341
342
343
344
345
346
347
348 public static ByteBuf wrappedBuffer(final byte[]... arrays) {
349 return Unpooled.wrappedBuffer(arrays);
350 }
351 }