HADOOP-16580. Disable retry of FailoverOnNetworkExceptionRetry in case of AccessControlException. Contributed by Adam Antal
(cherry picked from commit c79a5f2d99
)
This commit is contained in:
parent
3a5474c61e
commit
0bbd48c7a8
|
@ -38,6 +38,7 @@ import org.apache.hadoop.ipc.RemoteException;
|
||||||
import org.apache.hadoop.ipc.RetriableException;
|
import org.apache.hadoop.ipc.RetriableException;
|
||||||
import org.apache.hadoop.ipc.StandbyException;
|
import org.apache.hadoop.ipc.StandbyException;
|
||||||
import org.apache.hadoop.net.ConnectTimeoutException;
|
import org.apache.hadoop.net.ConnectTimeoutException;
|
||||||
|
import org.apache.hadoop.security.AccessControlException;
|
||||||
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
|
import org.apache.hadoop.security.token.SecretManager.InvalidToken;
|
||||||
import org.ietf.jgss.GSSException;
|
import org.ietf.jgss.GSSException;
|
||||||
|
|
||||||
|
@ -688,6 +689,9 @@ public class RetryPolicies {
|
||||||
} else if (e instanceof InvalidToken) {
|
} else if (e instanceof InvalidToken) {
|
||||||
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
|
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
|
||||||
"Invalid or Cancelled Token");
|
"Invalid or Cancelled Token");
|
||||||
|
} else if (e instanceof AccessControlException) {
|
||||||
|
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
|
||||||
|
"Access denied");
|
||||||
} else if (e instanceof SocketException
|
} else if (e instanceof SocketException
|
||||||
|| (e instanceof IOException && !(e instanceof RemoteException))) {
|
|| (e instanceof IOException && !(e instanceof RemoteException))) {
|
||||||
if (isIdempotentOrAtMostOnce) {
|
if (isIdempotentOrAtMostOnce) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.hadoop.io.retry.UnreliableInterface.FatalException;
|
||||||
import org.apache.hadoop.io.retry.UnreliableInterface.UnreliableException;
|
import org.apache.hadoop.io.retry.UnreliableInterface.UnreliableException;
|
||||||
import org.apache.hadoop.ipc.ProtocolTranslator;
|
import org.apache.hadoop.ipc.ProtocolTranslator;
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
|
import org.apache.hadoop.security.AccessControlException;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
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.Matchers.anyInt;
|
||||||
import static org.mockito.Mockito.*;
|
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 {
|
public class TestRetryProxy {
|
||||||
|
|
||||||
private UnreliableImplementation unreliableImpl;
|
private UnreliableImplementation unreliableImpl;
|
||||||
|
@ -348,4 +357,24 @@ public class TestRetryProxy {
|
||||||
assertEquals(RetryDecision.FAIL, caughtRetryAction.action);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,14 @@ import javax.security.sasl.SaslException;
|
||||||
|
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
import org.apache.hadoop.ipc.StandbyException;
|
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 {
|
class UnreliableImplementation implements UnreliableInterface {
|
||||||
|
|
||||||
private int failsOnceInvocationCount,
|
private int failsOnceInvocationCount,
|
||||||
|
@ -32,6 +39,7 @@ class UnreliableImplementation implements UnreliableInterface {
|
||||||
failsOnceRemoteExceptionInvocationCount,
|
failsOnceRemoteExceptionInvocationCount,
|
||||||
failsTenTimesInvocationCount,
|
failsTenTimesInvocationCount,
|
||||||
failsWithSASLExceptionTenTimesInvocationCount,
|
failsWithSASLExceptionTenTimesInvocationCount,
|
||||||
|
failsWithAccessControlExceptionInvocationCount,
|
||||||
succeedsOnceThenFailsCount,
|
succeedsOnceThenFailsCount,
|
||||||
succeedsOnceThenFailsIdempotentCount,
|
succeedsOnceThenFailsIdempotentCount,
|
||||||
succeedsTenTimesThenFailsCount;
|
succeedsTenTimesThenFailsCount;
|
||||||
|
@ -123,6 +131,14 @@ class UnreliableImplementation implements UnreliableInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void failsWithAccessControlExceptionEightTimes()
|
||||||
|
throws AccessControlException {
|
||||||
|
if (failsWithAccessControlExceptionInvocationCount++ < 8) {
|
||||||
|
throw new AccessControlException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String succeedsOnceThenFailsReturningString()
|
public String succeedsOnceThenFailsReturningString()
|
||||||
throws UnreliableException, IOException, StandbyException {
|
throws UnreliableException, IOException, StandbyException {
|
||||||
|
|
|
@ -24,7 +24,20 @@ import javax.security.sasl.SaslException;
|
||||||
|
|
||||||
import org.apache.hadoop.ipc.RemoteException;
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
import org.apache.hadoop.ipc.StandbyException;
|
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 interface UnreliableInterface {
|
||||||
|
|
||||||
public static class UnreliableException extends Exception {
|
public static class UnreliableException extends Exception {
|
||||||
|
@ -66,6 +79,10 @@ public interface UnreliableInterface {
|
||||||
|
|
||||||
void failsWithSASLExceptionTenTimes() throws SaslException;
|
void failsWithSASLExceptionTenTimes() throws SaslException;
|
||||||
|
|
||||||
|
@Idempotent
|
||||||
|
void failsWithAccessControlExceptionEightTimes()
|
||||||
|
throws AccessControlException;
|
||||||
|
|
||||||
public String succeedsOnceThenFailsReturningString()
|
public String succeedsOnceThenFailsReturningString()
|
||||||
throws UnreliableException, StandbyException, IOException;
|
throws UnreliableException, StandbyException, IOException;
|
||||||
@Idempotent
|
@Idempotent
|
||||||
|
|
Loading…
Reference in New Issue