HADOOP-16580. Disable retry of FailoverOnNetworkExceptionRetry in case of AccessControlException. Contributed by Adam Antal

(cherry picked from commit c79a5f2d99)
This commit is contained in:
Kihwal Lee 2020-01-24 11:07:06 -06:00
parent 296786a647
commit 2873a705f4
4 changed files with 66 additions and 0 deletions

View File

@ -39,6 +39,7 @@ import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ipc.RetriableException;
import org.apache.hadoop.ipc.StandbyException;
import org.apache.hadoop.net.ConnectTimeoutException;
import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
import org.ietf.jgss.GSSException;
@ -689,6 +690,9 @@ public class RetryPolicies {
} else if (e instanceof InvalidToken) {
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
"Invalid or Cancelled Token");
} else if (e instanceof AccessControlException) {
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
"Access denied");
} else if (e instanceof SocketException
|| (e instanceof IOException && !(e instanceof RemoteException))) {
if (isIdempotentOrAtMostOnce) {

View File

@ -25,6 +25,7 @@ import org.apache.hadoop.io.retry.UnreliableInterface.FatalException;
import org.apache.hadoop.io.retry.UnreliableInterface.UnreliableException;
import org.apache.hadoop.ipc.ProtocolTranslator;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.security.AccessControlException;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
@ -48,6 +49,14 @@ import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.*;
/**
* TestRetryProxy tests the behaviour of the {@link RetryPolicy} class using
* a certain method of {@link UnreliableInterface} implemented by
* {@link UnreliableImplementation}.
*
* Some methods may be sensitive to the {@link Idempotent} annotation
* (annotated in {@link UnreliableInterface}).
*/
public class TestRetryProxy {
private UnreliableImplementation unreliableImpl;
@ -348,4 +357,24 @@ public class TestRetryProxy {
assertEquals(RetryDecision.FAIL, caughtRetryAction.action);
}
}
@Test
public void testNoRetryOnAccessControlException() throws Exception {
RetryPolicy policy = mock(RetryPolicy.class);
RetryPolicy realPolicy = RetryPolicies.failoverOnNetworkException(5);
setupMockPolicy(policy, realPolicy);
UnreliableInterface unreliable = (UnreliableInterface) RetryProxy.create(
UnreliableInterface.class, unreliableImpl, policy);
try {
unreliable.failsWithAccessControlExceptionEightTimes();
fail("Should fail");
} catch (AccessControlException e) {
// expected
verify(policy, times(1)).shouldRetry(any(Exception.class), anyInt(),
anyInt(), anyBoolean());
assertEquals(RetryDecision.FAIL, caughtRetryAction.action);
}
}
}

View File

@ -23,7 +23,14 @@ import javax.security.sasl.SaslException;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ipc.StandbyException;
import org.apache.hadoop.security.AccessControlException;
/**
* For the usage and purpose of this class see {@link UnreliableInterface}
* which this class implements.
*
* @see UnreliableInterface
*/
class UnreliableImplementation implements UnreliableInterface {
private int failsOnceInvocationCount,
@ -32,6 +39,7 @@ class UnreliableImplementation implements UnreliableInterface {
failsOnceRemoteExceptionInvocationCount,
failsTenTimesInvocationCount,
failsWithSASLExceptionTenTimesInvocationCount,
failsWithAccessControlExceptionInvocationCount,
succeedsOnceThenFailsCount,
succeedsOnceThenFailsIdempotentCount,
succeedsTenTimesThenFailsCount;
@ -123,6 +131,14 @@ class UnreliableImplementation implements UnreliableInterface {
}
}
@Override
public void failsWithAccessControlExceptionEightTimes()
throws AccessControlException {
if (failsWithAccessControlExceptionInvocationCount++ < 8) {
throw new AccessControlException();
}
}
@Override
public String succeedsOnceThenFailsReturningString()
throws UnreliableException, IOException, StandbyException {

View File

@ -24,7 +24,20 @@ import javax.security.sasl.SaslException;
import org.apache.hadoop.ipc.RemoteException;
import org.apache.hadoop.ipc.StandbyException;
import org.apache.hadoop.security.AccessControlException;
/**
* The methods of UnreliableInterface could throw exceptions in a
* predefined way. It is currently used for testing {@link RetryPolicy}
* and {@link FailoverProxyProvider} classes, but can be potentially used
* to test any class's behaviour where an underlying interface or class
* may throw exceptions.
*
* Some methods may be annotated with the {@link Idempotent} annotation.
* In order to test those some methods of UnreliableInterface are annotated,
* but they are not actually Idempotent functions.
*
*/
public interface UnreliableInterface {
public static class UnreliableException extends Exception {
@ -66,6 +79,10 @@ public interface UnreliableInterface {
void failsWithSASLExceptionTenTimes() throws SaslException;
@Idempotent
void failsWithAccessControlExceptionEightTimes()
throws AccessControlException;
public String succeedsOnceThenFailsReturningString()
throws UnreliableException, StandbyException, IOException;
@Idempotent