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