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((FutureListener<U>) f -> transferResult(f, promise));
85 }
86 } else {
87 try {
88 if (resolveAll) {
89 @SuppressWarnings("unchecked")
90 final Promise<List<T>> castPromise = (Promise<List<T>>) promise;
91 delegate.resolveAll(inetHost, castPromise);
92 } else {
93 @SuppressWarnings("unchecked")
94 final Promise<T> castPromise = (Promise<T>) promise;
95 delegate.resolve(inetHost, castPromise);
96 }
97 } finally {
98 if (promise.isDone()) {
99 resolveMap.remove(inetHost);
100 } else {
101 promise.addListener((FutureListener<U>) f -> resolveMap.remove(inetHost));
102 }
103 }
104 }
105
106 return promise;
107 }
108
109 private static <T> void transferResult(Future<T> src, Promise<T> dst) {
110 if (src.isSuccess()) {
111 dst.trySuccess(src.getNow());
112 } else {
113 dst.tryFailure(src.cause());
114 }
115 }
116
117 @Override
118 public String toString() {
119 return StringUtil.simpleClassName(this) + '(' + delegate + ')';
120 }
121 }