HADOOP-15178. Generalize NetUtils#wrapException to handle other subclasses with String Constructor. Contributed by Ajay Kumar.
This commit is contained in:
parent
1e85a995d1
commit
28f644bf25
|
@ -715,9 +715,9 @@ public class NetUtils {
|
||||||
* return an IOException with the input exception as the cause and also
|
* return an IOException with the input exception as the cause and also
|
||||||
* include the host details. The new exception provides the stack trace of the
|
* include the host details. The new exception provides the stack trace of the
|
||||||
* place where the exception is thrown and some extra diagnostics information.
|
* place where the exception is thrown and some extra diagnostics information.
|
||||||
* If the exception is BindException or ConnectException or
|
* If the exception is of type BindException, ConnectException,
|
||||||
* UnknownHostException or SocketTimeoutException, return a new one of the
|
* UnknownHostException, SocketTimeoutException or has a String constructor,
|
||||||
* same type; Otherwise return an IOException.
|
* return a new one of the same type; Otherwise return an IOException.
|
||||||
*
|
*
|
||||||
* @param destHost target host (nullable)
|
* @param destHost target host (nullable)
|
||||||
* @param destPort target port
|
* @param destPort target port
|
||||||
|
@ -731,83 +731,90 @@ public class NetUtils {
|
||||||
final String localHost,
|
final String localHost,
|
||||||
final int localPort,
|
final int localPort,
|
||||||
final IOException exception) {
|
final IOException exception) {
|
||||||
if (exception instanceof BindException) {
|
try {
|
||||||
return wrapWithMessage(exception,
|
if (exception instanceof BindException) {
|
||||||
"Problem binding to ["
|
|
||||||
+ localHost
|
|
||||||
+ ":"
|
|
||||||
+ localPort
|
|
||||||
+ "] "
|
|
||||||
+ exception
|
|
||||||
+ ";"
|
|
||||||
+ see("BindException"));
|
|
||||||
} else if (exception instanceof ConnectException) {
|
|
||||||
// Check if client was trying to connect to an unspecified IPv4 address
|
|
||||||
// (0.0.0.0) or IPv6 address(0:0:0:0:0:0:0:0 or ::)
|
|
||||||
if ((destHost != null && (destHost.equals("0.0.0.0") ||
|
|
||||||
destHost.equals("0:0:0:0:0:0:0:0") || destHost.equals("::")))
|
|
||||||
|| destPort == 0) {
|
|
||||||
return wrapWithMessage(exception, "Your endpoint configuration" +
|
|
||||||
" is wrong;" + see("UnsetHostnameOrPort"));
|
|
||||||
} else {
|
|
||||||
// connection refused; include the host:port in the error
|
|
||||||
return wrapWithMessage(exception,
|
return wrapWithMessage(exception,
|
||||||
"Call From "
|
"Problem binding to ["
|
||||||
+ localHost
|
+ localHost
|
||||||
+ " to "
|
|
||||||
+ destHost
|
|
||||||
+ ":"
|
+ ":"
|
||||||
+ destPort
|
+ localPort
|
||||||
+ " failed on connection exception: "
|
+ "] "
|
||||||
+ exception
|
+ exception
|
||||||
+ ";"
|
+ ";"
|
||||||
+ see("ConnectionRefused"));
|
+ see("BindException"));
|
||||||
}
|
} else if (exception instanceof ConnectException) {
|
||||||
} else if (exception instanceof UnknownHostException) {
|
// Check if client was trying to connect to an unspecified IPv4 address
|
||||||
return wrapWithMessage(exception,
|
// (0.0.0.0) or IPv6 address(0:0:0:0:0:0:0:0 or ::)
|
||||||
"Invalid host name: "
|
if ((destHost != null && (destHost.equals("0.0.0.0") ||
|
||||||
+ getHostDetailsAsString(destHost, destPort, localHost)
|
destHost.equals("0:0:0:0:0:0:0:0") || destHost.equals("::")))
|
||||||
+ exception
|
|| destPort == 0) {
|
||||||
+ ";"
|
return wrapWithMessage(exception, "Your endpoint configuration" +
|
||||||
+ see("UnknownHost"));
|
" is wrong;" + see("UnsetHostnameOrPort"));
|
||||||
} else if (exception instanceof SocketTimeoutException) {
|
} else {
|
||||||
return wrapWithMessage(exception,
|
// connection refused; include the host:port in the error
|
||||||
"Call From "
|
return wrapWithMessage(exception,
|
||||||
+ localHost + " to " + destHost + ":" + destPort
|
"Call From "
|
||||||
+ " failed on socket timeout exception: " + exception
|
+ localHost
|
||||||
+ ";"
|
+ " to "
|
||||||
+ see("SocketTimeout"));
|
+ destHost
|
||||||
} else if (exception instanceof NoRouteToHostException) {
|
+ ":"
|
||||||
return wrapWithMessage(exception,
|
+ destPort
|
||||||
"No Route to Host from "
|
+ " failed on connection exception: "
|
||||||
+ localHost + " to " + destHost + ":" + destPort
|
+ exception
|
||||||
+ " failed on socket timeout exception: " + exception
|
+ ";"
|
||||||
+ ";"
|
+ see("ConnectionRefused"));
|
||||||
+ see("NoRouteToHost"));
|
}
|
||||||
} else if (exception instanceof EOFException) {
|
} else if (exception instanceof UnknownHostException) {
|
||||||
return wrapWithMessage(exception,
|
return wrapWithMessage(exception,
|
||||||
"End of File Exception between "
|
"Invalid host name: "
|
||||||
+ getHostDetailsAsString(destHost, destPort, localHost)
|
+ getHostDetailsAsString(destHost, destPort, localHost)
|
||||||
+ ": " + exception
|
+ exception
|
||||||
+ ";"
|
+ ";"
|
||||||
+ see("EOFException"));
|
+ see("UnknownHost"));
|
||||||
} else if (exception instanceof SocketException) {
|
} else if (exception instanceof SocketTimeoutException) {
|
||||||
// Many of the predecessor exceptions are subclasses of SocketException,
|
return wrapWithMessage(exception,
|
||||||
// so must be handled before this
|
"Call From "
|
||||||
return wrapWithMessage(exception,
|
+ localHost + " to " + destHost + ":" + destPort
|
||||||
"Call From "
|
+ " failed on socket timeout exception: " + exception
|
||||||
+ localHost + " to " + destHost + ":" + destPort
|
+ ";"
|
||||||
+ " failed on socket exception: " + exception
|
+ see("SocketTimeout"));
|
||||||
+ ";"
|
} else if (exception instanceof NoRouteToHostException) {
|
||||||
+ see("SocketException"));
|
return wrapWithMessage(exception,
|
||||||
}
|
"No Route to Host from "
|
||||||
else {
|
+ localHost + " to " + destHost + ":" + destPort
|
||||||
return (IOException) new IOException("Failed on local exception: "
|
+ " failed on socket timeout exception: " + exception
|
||||||
+ exception
|
+ ";"
|
||||||
+ "; Host Details : "
|
+ see("NoRouteToHost"));
|
||||||
+ getHostDetailsAsString(destHost, destPort, localHost))
|
} else if (exception instanceof EOFException) {
|
||||||
.initCause(exception);
|
return wrapWithMessage(exception,
|
||||||
|
"End of File Exception between "
|
||||||
|
+ getHostDetailsAsString(destHost, destPort, localHost)
|
||||||
|
+ ": " + exception
|
||||||
|
+ ";"
|
||||||
|
+ see("EOFException"));
|
||||||
|
} else if (exception instanceof SocketException) {
|
||||||
|
// Many of the predecessor exceptions are subclasses of SocketException,
|
||||||
|
// so must be handled before this
|
||||||
|
return wrapWithMessage(exception,
|
||||||
|
"Call From "
|
||||||
|
+ localHost + " to " + destHost + ":" + destPort
|
||||||
|
+ " failed on socket exception: " + exception
|
||||||
|
+ ";"
|
||||||
|
+ see("SocketException"));
|
||||||
|
} else {
|
||||||
|
// Return instance of same type if Exception has a String constructor
|
||||||
|
return wrapWithMessage(exception,
|
||||||
|
"DestHost:destPort " + destHost + ":" + destPort
|
||||||
|
+ " , LocalHost:localPort " + localHost
|
||||||
|
+ ":" + localPort + ". Failed on local exception: " +
|
||||||
|
exception);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
return (IOException) new IOException("Failed on local exception: "
|
||||||
|
+ exception + "; Host Details : "
|
||||||
|
+ getHostDetailsAsString(destHost, destPort, localHost))
|
||||||
|
.initCause(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,16 +824,16 @@ public class NetUtils {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <T extends IOException> T wrapWithMessage(
|
private static <T extends IOException> T wrapWithMessage(
|
||||||
T exception, String msg) {
|
T exception, String msg) throws T {
|
||||||
Class<? extends Throwable> clazz = exception.getClass();
|
Class<? extends Throwable> clazz = exception.getClass();
|
||||||
try {
|
try {
|
||||||
Constructor<? extends Throwable> ctor = clazz.getConstructor(String.class);
|
Constructor<? extends Throwable> ctor = clazz.getConstructor(String.class);
|
||||||
Throwable t = ctor.newInstance(msg);
|
Throwable t = ctor.newInstance(msg);
|
||||||
return (T)(t.initCause(exception));
|
return (T)(t.initCause(exception));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
LOG.warn("Unable to wrap exception of type " +
|
LOG.warn("Unable to wrap exception of type {}: it has no (String) "
|
||||||
clazz + ": it has no (String) constructor", e);
|
+ "constructor", clazz, e);
|
||||||
return exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.net.SocketException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -40,6 +41,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.io.IOUtils;
|
import org.apache.hadoop.io.IOUtils;
|
||||||
|
import org.apache.hadoop.security.KerberosAuthException;
|
||||||
import org.apache.hadoop.security.NetUtilsTestResolver;
|
import org.apache.hadoop.security.NetUtilsTestResolver;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -262,6 +264,44 @@ public class TestNetUtils {
|
||||||
assertInException(wrapped, "/EOFException");
|
assertInException(wrapped, "/EOFException");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrapKerbAuthException() throws Throwable {
|
||||||
|
IOException e = new KerberosAuthException("socket timeout on connection");
|
||||||
|
IOException wrapped = verifyExceptionClass(e, KerberosAuthException.class);
|
||||||
|
assertInException(wrapped, "socket timeout on connection");
|
||||||
|
assertInException(wrapped, "localhost");
|
||||||
|
assertInException(wrapped, "DestHost:destPort ");
|
||||||
|
assertInException(wrapped, "LocalHost:localPort");
|
||||||
|
assertRemoteDetailsIncluded(wrapped);
|
||||||
|
assertInException(wrapped, "KerberosAuthException");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrapIOEWithNoStringConstructor() throws Throwable {
|
||||||
|
IOException e = new CharacterCodingException();
|
||||||
|
IOException wrapped = verifyExceptionClass(e, IOException.class);
|
||||||
|
assertInException(wrapped, "Failed on local exception");
|
||||||
|
assertNotInException(wrapped, NetUtils.HADOOP_WIKI);
|
||||||
|
assertInException(wrapped, "Host Details ");
|
||||||
|
assertRemoteDetailsIncluded(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWrapIOEWithPrivateStringConstructor() throws Throwable {
|
||||||
|
class TestIOException extends CharacterCodingException{
|
||||||
|
private TestIOException(String cause){
|
||||||
|
}
|
||||||
|
TestIOException(){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IOException e = new TestIOException();
|
||||||
|
IOException wrapped = verifyExceptionClass(e, IOException.class);
|
||||||
|
assertInException(wrapped, "Failed on local exception");
|
||||||
|
assertNotInException(wrapped, NetUtils.HADOOP_WIKI);
|
||||||
|
assertInException(wrapped, "Host Details ");
|
||||||
|
assertRemoteDetailsIncluded(wrapped);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWrapSocketException() throws Throwable {
|
public void testWrapSocketException() throws Throwable {
|
||||||
IOException wrapped = verifyExceptionClass(new SocketException("failed"),
|
IOException wrapped = verifyExceptionClass(new SocketException("failed"),
|
||||||
|
|
Loading…
Reference in New Issue