|
15 | 15 | */ |
16 | 16 | package org.redisson.connection; |
17 | 17 |
|
| 18 | +import io.netty.bootstrap.Bootstrap; |
18 | 19 | import io.netty.buffer.ByteBuf; |
19 | 20 | import io.netty.buffer.ByteBufUtil; |
| 21 | +import io.netty.channel.Channel; |
| 22 | +import io.netty.channel.EventLoop; |
20 | 23 | import io.netty.channel.EventLoopGroup; |
21 | 24 | import io.netty.channel.MultiThreadIoEventLoopGroup; |
22 | 25 | import io.netty.channel.epoll.EpollDatagramChannel; |
|
52 | 55 | import org.redisson.RedissonShutdownException; |
53 | 56 | import org.redisson.api.*; |
54 | 57 | import org.redisson.cache.LRUCacheMap; |
| 58 | +import org.redisson.client.NettyHook; |
55 | 59 | import org.redisson.client.RedisNodeNotFoundException; |
56 | 60 | import org.redisson.client.codec.Codec; |
57 | 61 | import org.redisson.client.protocol.RedisCommand; |
@@ -152,6 +156,10 @@ public boolean cancel() { |
152 | 156 |
|
153 | 157 | private volatile boolean bitFieldRODisabled; |
154 | 158 |
|
| 159 | + private final Map<Thread, EventLoop> nettyThreads = new ConcurrentHashMap<>(); |
| 160 | + |
| 161 | + private final NettyHook nettyHook; |
| 162 | + |
155 | 163 | private static final Map<InetSocketAddress, Set<String>> SCRIPT_SHA_CACHE = new ConcurrentHashMap<>(); |
156 | 164 |
|
157 | 165 | private static final Map<String, String> SHA_CACHE = new LRUCacheMap<>(500, 0, 0); |
@@ -260,6 +268,28 @@ public ServiceManager(MasterSlaveServersConfig config, Config cfg) { |
260 | 268 | this.cfg = cfg; |
261 | 269 | this.config = config; |
262 | 270 |
|
| 271 | + if (cfg.getNettyExecutor() == null && cfg.getEventLoopGroup() == null) { |
| 272 | + this.nettyHook = cfg.getNettyHook(); |
| 273 | + } else { |
| 274 | + this.nettyHook = new NettyHook() { |
| 275 | + @Override |
| 276 | + public void afterBoostrapInitialization(Bootstrap bootstrap) { |
| 277 | + cfg.getNettyHook().afterBoostrapInitialization(bootstrap); |
| 278 | + } |
| 279 | + |
| 280 | + @Override |
| 281 | + public void afterChannelInitialization(Channel channel) { |
| 282 | + if (nettyThreads.put(Thread.currentThread(), channel.eventLoop()) == null) { |
| 283 | + // An event loop can stop its thread and use a new thread later. |
| 284 | + // Each new thread removes the threads that no longer run their event loop. |
| 285 | + // Thus the map cannot grow without limit. |
| 286 | + nettyThreads.entrySet().removeIf(entry -> !entry.getValue().inEventLoop(entry.getKey())); |
| 287 | + } |
| 288 | + cfg.getNettyHook().afterChannelInitialization(channel); |
| 289 | + } |
| 290 | + }; |
| 291 | + } |
| 292 | + |
263 | 293 | if (cfg.getConnectionListener() != null) { |
264 | 294 | this.connectionEventsHub.addListener(cfg.getConnectionListener()); |
265 | 295 | } |
@@ -385,6 +415,20 @@ public EventLoopGroup getGroup() { |
385 | 415 | return group; |
386 | 416 | } |
387 | 417 |
|
| 418 | + public NettyHook getNettyHook() { |
| 419 | + return nettyHook; |
| 420 | + } |
| 421 | + |
| 422 | + public boolean isNettyThread() { |
| 423 | + Thread thread = Thread.currentThread(); |
| 424 | + if (thread.getName().startsWith("redisson-netty")) { |
| 425 | + return true; |
| 426 | + } |
| 427 | + |
| 428 | + EventLoop eventLoop = nettyThreads.get(thread); |
| 429 | + return eventLoop != null && eventLoop.inEventLoop(thread); |
| 430 | + } |
| 431 | + |
388 | 432 | public CompletableFuture<List<RedisURI>> resolveAll(RedisURI uri) { |
389 | 433 | if (uri.isIP()) { |
390 | 434 | RedisURI mappedUri = toURI(uri.getScheme(), uri.getHost(), "" + uri.getPort()); |
|
0 commit comments