HADOOP-7928. HA: Client failover policy is incorrectly trying to fail over all IOExceptions. Contributed by Aaron T. Myers.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-1623@1215019 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
353bc3799d
commit
116bf57bd6
@ -15,3 +15,6 @@ HADOOP-7922. Improve some logging for client IPC failovers and
|
|||||||
StandbyExceptions (todd)
|
StandbyExceptions (todd)
|
||||||
|
|
||||||
HADOOP-7921. StandbyException should extend IOException (todd)
|
HADOOP-7921. StandbyException should extend IOException (todd)
|
||||||
|
|
||||||
|
HADOOP-7928. HA: Client failover policy is incorrectly trying to fail over all
|
||||||
|
IOExceptions (atm)
|
||||||
|
@ -341,7 +341,7 @@ public RetryAction shouldRetry(Exception e, int retries,
|
|||||||
failovers == 0 ? 0 :
|
failovers == 0 ? 0 :
|
||||||
calculateExponentialTime(delayMillis, failovers, maxDelayBase));
|
calculateExponentialTime(delayMillis, failovers, maxDelayBase));
|
||||||
} else if (e instanceof SocketException ||
|
} else if (e instanceof SocketException ||
|
||||||
e instanceof IOException) {
|
(e instanceof IOException && !(e instanceof RemoteException))) {
|
||||||
if (isMethodIdempotent) {
|
if (isMethodIdempotent) {
|
||||||
return RetryAction.FAILOVER_AND_RETRY;
|
return RetryAction.FAILOVER_AND_RETRY;
|
||||||
} else {
|
} else {
|
||||||
|
@ -181,7 +181,7 @@ public void testFailoverOnNetworkExceptionIdempotentOperation()
|
|||||||
|
|
||||||
assertEquals("impl1", unreliable.succeedsOnceThenFailsReturningString());
|
assertEquals("impl1", unreliable.succeedsOnceThenFailsReturningString());
|
||||||
try {
|
try {
|
||||||
assertEquals("impl2", unreliable.succeedsOnceThenFailsReturningString());
|
unreliable.succeedsOnceThenFailsReturningString();
|
||||||
fail("should not have succeeded twice");
|
fail("should not have succeeded twice");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Make sure we *don't* fail over since the first implementation threw an
|
// Make sure we *don't* fail over since the first implementation threw an
|
||||||
@ -304,4 +304,26 @@ public void run() {
|
|||||||
String result = unreliable.failsIfIdentifierDoesntMatch("renamed-impl1");
|
String result = unreliable.failsIfIdentifierDoesntMatch("renamed-impl1");
|
||||||
assertEquals("renamed-impl1", result);
|
assertEquals("renamed-impl1", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that normal IO exceptions don't result in a failover.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testExpectedIOException() {
|
||||||
|
UnreliableInterface unreliable = (UnreliableInterface)RetryProxy
|
||||||
|
.create(UnreliableInterface.class,
|
||||||
|
new FlipFlopProxyProvider(UnreliableInterface.class,
|
||||||
|
new UnreliableImplementation("impl1", TypeOfExceptionToFailWith.REMOTE_EXCEPTION),
|
||||||
|
new UnreliableImplementation("impl2", TypeOfExceptionToFailWith.UNRELIABLE_EXCEPTION)),
|
||||||
|
RetryPolicies.failoverOnNetworkException(
|
||||||
|
RetryPolicies.TRY_ONCE_THEN_FAIL, 10, 1000, 10000));
|
||||||
|
|
||||||
|
try {
|
||||||
|
unreliable.failsIfIdentifierDoesntMatch("no-such-identifier");
|
||||||
|
fail("Should have thrown *some* exception");
|
||||||
|
} catch (Exception e) {
|
||||||
|
assertTrue("Expected IOE but got " + e.getClass(),
|
||||||
|
e instanceof IOException);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.hadoop.io.retry.UnreliableInterface.UnreliableException;
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
import org.apache.hadoop.ipc.StandbyException;
|
import org.apache.hadoop.ipc.StandbyException;
|
||||||
|
|
||||||
@ -37,7 +38,8 @@ public class UnreliableImplementation implements UnreliableInterface {
|
|||||||
public static enum TypeOfExceptionToFailWith {
|
public static enum TypeOfExceptionToFailWith {
|
||||||
UNRELIABLE_EXCEPTION,
|
UNRELIABLE_EXCEPTION,
|
||||||
STANDBY_EXCEPTION,
|
STANDBY_EXCEPTION,
|
||||||
IO_EXCEPTION
|
IO_EXCEPTION,
|
||||||
|
REMOTE_EXCEPTION
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnreliableImplementation() {
|
public UnreliableImplementation() {
|
||||||
@ -95,14 +97,7 @@ public String succeedsOnceThenFailsReturningString()
|
|||||||
if (succeedsOnceThenFailsCount++ < 1) {
|
if (succeedsOnceThenFailsCount++ < 1) {
|
||||||
return identifier;
|
return identifier;
|
||||||
} else {
|
} else {
|
||||||
switch (exceptionToFailWith) {
|
throwAppropriateException(exceptionToFailWith, identifier);
|
||||||
case STANDBY_EXCEPTION:
|
|
||||||
throw new StandbyException(identifier);
|
|
||||||
case UNRELIABLE_EXCEPTION:
|
|
||||||
throw new UnreliableException(identifier);
|
|
||||||
case IO_EXCEPTION:
|
|
||||||
throw new IOException(identifier);
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,16 +108,8 @@ public String succeedsTenTimesThenFailsReturningString()
|
|||||||
if (succeedsTenTimesThenFailsCount++ < 10) {
|
if (succeedsTenTimesThenFailsCount++ < 10) {
|
||||||
return identifier;
|
return identifier;
|
||||||
} else {
|
} else {
|
||||||
switch (exceptionToFailWith) {
|
throwAppropriateException(exceptionToFailWith, identifier);
|
||||||
case STANDBY_EXCEPTION:
|
return null;
|
||||||
throw new StandbyException(identifier);
|
|
||||||
case UNRELIABLE_EXCEPTION:
|
|
||||||
throw new UnreliableException(identifier);
|
|
||||||
case IO_EXCEPTION:
|
|
||||||
throw new IOException(identifier);
|
|
||||||
default:
|
|
||||||
throw new RuntimeException(identifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,16 +119,8 @@ public String succeedsOnceThenFailsReturningStringIdempotent()
|
|||||||
if (succeedsOnceThenFailsIdempotentCount++ < 1) {
|
if (succeedsOnceThenFailsIdempotentCount++ < 1) {
|
||||||
return identifier;
|
return identifier;
|
||||||
} else {
|
} else {
|
||||||
switch (exceptionToFailWith) {
|
throwAppropriateException(exceptionToFailWith, identifier);
|
||||||
case STANDBY_EXCEPTION:
|
return null;
|
||||||
throw new StandbyException(identifier);
|
|
||||||
case UNRELIABLE_EXCEPTION:
|
|
||||||
throw new UnreliableException(identifier);
|
|
||||||
case IO_EXCEPTION:
|
|
||||||
throw new IOException(identifier);
|
|
||||||
default:
|
|
||||||
throw new RuntimeException(identifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,17 +132,24 @@ public String failsIfIdentifierDoesntMatch(String identifier)
|
|||||||
} else {
|
} else {
|
||||||
String message = "expected '" + this.identifier + "' but received '" +
|
String message = "expected '" + this.identifier + "' but received '" +
|
||||||
identifier + "'";
|
identifier + "'";
|
||||||
switch (exceptionToFailWith) {
|
throwAppropriateException(exceptionToFailWith, message);
|
||||||
case STANDBY_EXCEPTION:
|
return null;
|
||||||
throw new StandbyException(message);
|
|
||||||
case UNRELIABLE_EXCEPTION:
|
|
||||||
throw new UnreliableException(message);
|
|
||||||
case IO_EXCEPTION:
|
|
||||||
throw new IOException(message);
|
|
||||||
default:
|
|
||||||
throw new RuntimeException(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void throwAppropriateException(TypeOfExceptionToFailWith eType,
|
||||||
|
String message) throws UnreliableException, StandbyException, IOException {
|
||||||
|
switch (eType) {
|
||||||
|
case STANDBY_EXCEPTION:
|
||||||
|
throw new StandbyException(message);
|
||||||
|
case UNRELIABLE_EXCEPTION:
|
||||||
|
throw new UnreliableException(message);
|
||||||
|
case IO_EXCEPTION:
|
||||||
|
throw new IOException(message);
|
||||||
|
case REMOTE_EXCEPTION:
|
||||||
|
throw new RemoteException(IOException.class.getName(), message);
|
||||||
|
default:
|
||||||
|
throw new RuntimeException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user