1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  package io.netty.resolver.dns;
18  
19  import io.netty.resolver.NameResolver;
20  import io.netty.util.concurrent.EventExecutor;
21  import io.netty.util.concurrent.Future;
22  import io.netty.util.concurrent.FutureListener;
23  import io.netty.util.concurrent.Promise;
24  import io.netty.util.internal.StringUtil;
25  
26  import java.util.List;
27  import java.util.concurrent.ConcurrentMap;
28  
29  import static io.netty.util.internal.ObjectUtil.checkNotNull;
30  
31  
32  final class InflightNameResolver<T> implements NameResolver<T> {
33  
34      private final EventExecutor executor;
35      private final NameResolver<T> delegate;
36      private final ConcurrentMap<String, Promise<T>> resolvesInProgress;
37      private final ConcurrentMap<String, Promise<List<T>>> resolveAllsInProgress;
38  
39      InflightNameResolver(EventExecutor executor, NameResolver<T> delegate,
40                           ConcurrentMap<String, Promise<T>> resolvesInProgress,
41                           ConcurrentMap<String, Promise<List<T>>> resolveAllsInProgress) {
42  
43          this.executor = checkNotNull(executor, "executor");
44          this.delegate = checkNotNull(delegate, "delegate");
45          this.resolvesInProgress = checkNotNull(resolvesInProgress, "resolvesInProgress");
46          this.resolveAllsInProgress = checkNotNull(resolveAllsInProgress, "resolveAllsInProgress");
47      }
48  
49      @Override
50      public Future<T> resolve(String inetHost) {
51          return resolve(inetHost, executor.<T>newPromise());
52      }
53  
54      @Override
55      public Future<List<T>> resolveAll(String inetHost) {
56          return resolveAll(inetHost, executor.<List<T>>newPromise());
57      }
58  
59      @Override
60      public void close() {
61          delegate.close();
62      }
63  
64      @Override
65      public Promise<T> resolve(String inetHost, Promise<T> promise) {
66          return resolve(resolvesInProgress, inetHost, promise, false);
67      }
68  
69      @Override
70      public Promise<List<T>> resolveAll(String inetHost, Promise<List<T>> promise) {
71          return resolve(resolveAllsInProgress, inetHost, promise, true);
72      }
73  
74      private <U> Promise<U> resolve(
75              final ConcurrentMap<String, Promise<U>> resolveMap,
76              final String inetHost, final Promise<U> promise, boolean resolveAll) {
77  
78          final Promise<U> earlyPromise = resolveMap.putIfAbsent(inetHost, promise);
79          if (earlyPromise != null) {
80              
81              if (earlyPromise.isDone()) {
82                  transferResult(earlyPromise, promise);
83              } else {
84                  earlyPromise.addListener(new FutureListener<U>() {
85                      @Override
86                      public void operationComplete(Future<U> f) throws Exception {
87                          transferResult(f, promise);
88                      }
89                  });
90              }
91          } else {
92              try {
93                  if (resolveAll) {
94                      @SuppressWarnings("unchecked")
95                      final Promise<List<T>> castPromise = (Promise<List<T>>) promise; 
96                      delegate.resolveAll(inetHost, castPromise);
97                  } else {
98                      @SuppressWarnings("unchecked")
99                      final Promise<T> castPromise = (Promise<T>) promise; 
100                     delegate.resolve(inetHost, castPromise);
101                 }
102             } finally {
103                 if (promise.isDone()) {
104                     resolveMap.remove(inetHost);
105                 } else {
106                     promise.addListener(new FutureListener<U>() {
107                         @Override
108                         public void operationComplete(Future<U> f) throws Exception {
109                             resolveMap.remove(inetHost);
110                         }
111                     });
112                 }
113             }
114         }
115 
116         return promise;
117     }
118 
119     private static <T> void transferResult(Future<T> src, Promise<T> dst) {
120         if (src.isSuccess()) {
121             dst.trySuccess(src.getNow());
122         } else {
123             dst.tryFailure(src.cause());
124         }
125     }
126 
127     @Override
128     public String toString() {
129         return StringUtil.simpleClassName(this) + '(' + delegate + ')';
130     }
131 }