2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
21 import java.net.InetSocketAddress;
22 import java.net.SocketAddress;
23 import java.nio.channels.UnresolvedAddressException;
24 import java.util.concurrent.Executor;
25 import java.util.concurrent.TimeUnit;
26 import java.util.concurrent.TimeoutException;
27 import java.util.concurrent.atomic.AtomicBoolean;
29 import org.eclipse.jetty.util.log.Log;
30 import org.eclipse.jetty.util.log.Logger;
31 import org.eclipse.jetty.util.thread.Scheduler;
34 * <p>Creates {@link SocketAddress} instances, returning them through a {@link Promise}.</p>
36 public interface SocketAddressResolver
39 * Resolves the given host and port, returning a {@link SocketAddress} through the given {@link Promise}
40 * with the default timeout.
42 * @param host the host to resolve
43 * @param port the port of the resulting socket address
44 * @param promise the callback invoked when the resolution succeeds or fails
46 public void resolve(String host, int port, Promise<SocketAddress> promise);
49 * <p>Creates {@link SocketAddress} instances synchronously in the caller thread.</p>
51 public static class Sync implements SocketAddressResolver
54 public void resolve(String host, int port, Promise<SocketAddress> promise)
58 InetSocketAddress result = new InetSocketAddress(host, port);
59 if (result.isUnresolved())
60 promise.failed(new UnresolvedAddressException());
62 promise.succeeded(result);
72 * <p>Creates {@link SocketAddress} instances asynchronously in a different thread.</p>
73 * <p>{@link InetSocketAddress#InetSocketAddress(String, int)} attempts to perform a DNS
74 * resolution of the host name, and this may block for several seconds.
75 * This class creates the {@link InetSocketAddress} in a separate thread and provides the result
76 * through a {@link Promise}, with the possibility to specify a timeout for the operation.</p>
77 * <p>Example usage:</p>
79 * SocketAddressResolver resolver = new SocketAddressResolver.Async(executor, scheduler, timeout);
80 * resolver.resolve("www.google.com", 80, new Promise<SocketAddress>()
82 * public void succeeded(SocketAddress result)
84 * // The address was resolved
87 * public void failed(Throwable failure)
89 * // The address resolution failed
94 public static class Async implements SocketAddressResolver
96 private static final Logger LOG = Log.getLogger(SocketAddressResolver.class);
98 private final Executor executor;
99 private final Scheduler scheduler;
100 private final long timeout;
103 * Creates a new instance with the given executor (to perform DNS resolution in a separate thread),
104 * the given scheduler (to cancel the operation if it takes too long) and the given timeout, in milliseconds.
106 * @param executor the thread pool to use to perform DNS resolution in pooled threads
107 * @param scheduler the scheduler to schedule tasks to cancel DNS resolution if it takes too long
108 * @param timeout the timeout, in milliseconds, for the DNS resolution to complete
110 public Async(Executor executor, Scheduler scheduler, long timeout)
112 this.executor = executor;
113 this.scheduler = scheduler;
114 this.timeout = timeout;
117 public Executor getExecutor()
122 public Scheduler getScheduler()
127 public long getTimeout()
133 public void resolve(final String host, final int port, final Promise<SocketAddress> promise)
135 executor.execute(new Runnable()
140 Scheduler.Task task = null;
141 final AtomicBoolean complete = new AtomicBoolean();
144 final Thread thread = Thread.currentThread();
145 task = scheduler.schedule(new Runnable()
150 if (complete.compareAndSet(false, true))
152 promise.failed(new TimeoutException());
156 }, timeout, TimeUnit.MILLISECONDS);
161 long start = System.nanoTime();
162 InetSocketAddress result = new InetSocketAddress(host, port);
163 long elapsed = System.nanoTime() - start;
164 if (LOG.isDebugEnabled())
165 LOG.debug("Resolved {} in {} ms", host, TimeUnit.NANOSECONDS.toMillis(elapsed));
166 if (complete.compareAndSet(false, true))
168 if (result.isUnresolved())
169 promise.failed(new UnresolvedAddressException());
171 promise.succeeded(result);
176 if (complete.compareAndSet(false, true))
183 // Reset the interrupted status before releasing the thread to the pool
184 Thread.interrupted();