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 }