1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty5.resolver;
18
19 import io.netty5.util.concurrent.EventExecutor;
20 import io.netty5.util.concurrent.FutureListener;
21 import io.netty5.util.internal.logging.InternalLogger;
22 import io.netty5.util.internal.logging.InternalLoggerFactory;
23
24 import java.io.Closeable;
25 import java.net.SocketAddress;
26 import java.util.IdentityHashMap;
27 import java.util.Map;
28 import java.util.concurrent.ConcurrentMap;
29
30 import static java.util.Objects.requireNonNull;
31
32
33
34
35 public abstract class AddressResolverGroup<T extends SocketAddress> implements Closeable {
36
37 private static final InternalLogger logger = InternalLoggerFactory.getInstance(AddressResolverGroup.class);
38
39
40
41
42 private final Map<EventExecutor, AddressResolver<T>> resolvers = new IdentityHashMap<>();
43
44 private final Map<EventExecutor, FutureListener<Object>> executorTerminationListeners =
45 new IdentityHashMap<>();
46
47 protected AddressResolverGroup() { }
48
49
50
51
52
53
54
55 public AddressResolver<T> getResolver(final EventExecutor executor) {
56 requireNonNull(executor, "executor");
57
58 if (executor.isShuttingDown()) {
59 throw new IllegalStateException("executor not accepting a task");
60 }
61
62 AddressResolver<T> r;
63 synchronized (resolvers) {
64 r = resolvers.get(executor);
65 if (r == null) {
66 final AddressResolver<T> newResolver;
67 try {
68 newResolver = newResolver(executor);
69 } catch (Exception e) {
70 throw new IllegalStateException("failed to create a new resolver", e);
71 }
72
73 resolvers.put(executor, newResolver);
74 FutureListener<Object> terminationListener = future -> {
75 synchronized (resolvers) {
76 resolvers.remove(executor);
77 executorTerminationListeners.remove(executor);
78 }
79 newResolver.close();
80 };
81 executorTerminationListeners.put(executor, terminationListener);
82 executor.terminationFuture().addListener(terminationListener);
83
84 r = newResolver;
85 }
86 }
87
88 return r;
89 }
90
91
92
93
94 protected abstract AddressResolver<T> newResolver(EventExecutor executor) throws Exception;
95
96
97
98
99 @Override
100 @SuppressWarnings({ "unchecked", "ZeroLengthArrayAllocation" })
101 public void close() {
102 final AddressResolver<T>[] rArray;
103
104 synchronized (resolvers) {
105 rArray = (AddressResolver<T>[]) resolvers.values().toArray(new AddressResolver[0]);
106 resolvers.clear();
107 executorTerminationListeners.clear();
108 }
109
110 for (final AddressResolver<T> r: rArray) {
111 try {
112 r.close();
113 } catch (Throwable t) {
114 logger.warn("Failed to close a resolver:", t);
115 }
116 }
117 }
118 }