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 }