|
@@ -39,12 +39,16 @@ import java.net.ConnectException;
|
|
|
import java.nio.channels.SocketChannel;
|
|
|
import java.nio.channels.UnresolvedAddressException;
|
|
|
import java.util.Map.Entry;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.regex.Pattern;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
|
import javax.net.SocketFactory;
|
|
|
|
|
|
+import com.google.common.cache.Cache;
|
|
|
+import com.google.common.cache.CacheBuilder;
|
|
|
+
|
|
|
import org.apache.commons.net.util.SubnetUtils;
|
|
|
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
|
|
|
import org.apache.hadoop.classification.InterfaceAudience;
|
|
@@ -177,11 +181,33 @@ public class NetUtils {
|
|
|
* include a port number
|
|
|
* @param configName the name of the configuration from which
|
|
|
* <code>target</code> was loaded. This is used in the
|
|
|
- * exception message in the case that parsing fails.
|
|
|
+ * exception message in the case that parsing fails.
|
|
|
*/
|
|
|
public static InetSocketAddress createSocketAddr(String target,
|
|
|
int defaultPort,
|
|
|
String configName) {
|
|
|
+ return createSocketAddr(target, defaultPort, configName, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Create an InetSocketAddress from the given target string and
|
|
|
+ * default port. If the string cannot be parsed correctly, the
|
|
|
+ * <code>configName</code> parameter is used as part of the
|
|
|
+ * exception message, allowing the user to better diagnose
|
|
|
+ * the misconfiguration.
|
|
|
+ *
|
|
|
+ * @param target a string of either "host" or "host:port"
|
|
|
+ * @param defaultPort the default port if <code>target</code> does not
|
|
|
+ * include a port number
|
|
|
+ * @param configName the name of the configuration from which
|
|
|
+ * <code>target</code> was loaded. This is used in the
|
|
|
+ * exception message in the case that parsing fails.
|
|
|
+ * @param useCacheIfPresent Whether use cache when create URI
|
|
|
+ */
|
|
|
+ public static InetSocketAddress createSocketAddr(String target,
|
|
|
+ int defaultPort,
|
|
|
+ String configName,
|
|
|
+ boolean useCacheIfPresent) {
|
|
|
String helpText = "";
|
|
|
if (configName != null) {
|
|
|
helpText = " (configuration property '" + configName + "')";
|
|
@@ -191,15 +217,8 @@ public class NetUtils {
|
|
|
helpText);
|
|
|
}
|
|
|
target = target.trim();
|
|
|
- boolean hasScheme = target.contains("://");
|
|
|
- URI uri = null;
|
|
|
- try {
|
|
|
- uri = hasScheme ? URI.create(target) : URI.create("dummyscheme://"+target);
|
|
|
- } catch (IllegalArgumentException e) {
|
|
|
- throw new IllegalArgumentException(
|
|
|
- "Does not contain a valid host:port authority: " + target + helpText
|
|
|
- );
|
|
|
- }
|
|
|
+ boolean hasScheme = target.contains("://");
|
|
|
+ URI uri = createURI(target, hasScheme, helpText, useCacheIfPresent);
|
|
|
|
|
|
String host = uri.getHost();
|
|
|
int port = uri.getPort();
|
|
@@ -207,10 +226,9 @@ public class NetUtils {
|
|
|
port = defaultPort;
|
|
|
}
|
|
|
String path = uri.getPath();
|
|
|
-
|
|
|
+
|
|
|
if ((host == null) || (port < 0) ||
|
|
|
- (!hasScheme && path != null && !path.isEmpty()))
|
|
|
- {
|
|
|
+ (!hasScheme && path != null && !path.isEmpty())) {
|
|
|
throw new IllegalArgumentException(
|
|
|
"Does not contain a valid host:port authority: " + target + helpText
|
|
|
);
|
|
@@ -218,6 +236,40 @@ public class NetUtils {
|
|
|
return createSocketAddrForHost(host, port);
|
|
|
}
|
|
|
|
|
|
+ private static final long URI_CACHE_SIZE_DEFAULT = 1000;
|
|
|
+ private static final long URI_CACHE_EXPIRE_TIME_DEFAULT = 12;
|
|
|
+ private static final Cache<String, URI> URI_CACHE = CacheBuilder.newBuilder()
|
|
|
+ .maximumSize(URI_CACHE_SIZE_DEFAULT)
|
|
|
+ .expireAfterWrite(URI_CACHE_EXPIRE_TIME_DEFAULT, TimeUnit.HOURS)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ private static URI createURI(String target,
|
|
|
+ boolean hasScheme,
|
|
|
+ String helpText,
|
|
|
+ boolean useCacheIfPresent) {
|
|
|
+ URI uri;
|
|
|
+ if (useCacheIfPresent) {
|
|
|
+ uri = URI_CACHE.getIfPresent(target);
|
|
|
+ if (uri != null) {
|
|
|
+ return uri;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ uri = hasScheme ? URI.create(target) :
|
|
|
+ URI.create("dummyscheme://" + target);
|
|
|
+ } catch (IllegalArgumentException e) {
|
|
|
+ throw new IllegalArgumentException(
|
|
|
+ "Does not contain a valid host:port authority: " + target + helpText
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (useCacheIfPresent) {
|
|
|
+ URI_CACHE.put(target, uri);
|
|
|
+ }
|
|
|
+ return uri;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Create a socket address with the given host and port. The hostname
|
|
|
* might be replaced with another host that was set via
|