HADOOP-9792. Merge 1508312 from trunk.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1508313 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b3f765ad3d
commit
1b8522d03d
|
@ -107,6 +107,9 @@ Release 2.1.0-beta - 2013-07-02
|
|||
HADOOP-9762. RetryCache utility for implementing RPC retries.
|
||||
(Suresh Srinivas via jing9)
|
||||
|
||||
HADOOP-9792. Retry the methods that are tagged @AtMostOnce along
|
||||
with @Idempotent. (suresh)
|
||||
|
||||
IMPROVEMENTS
|
||||
|
||||
HADOOP-9164. Print paths of loaded native libraries in
|
||||
|
|
|
@ -51,8 +51,8 @@ public interface FailoverProxyProvider<T> extends Closeable {
|
|||
/**
|
||||
* Return a reference to the interface this provider's proxy objects actually
|
||||
* implement. If any of the methods on this interface are annotated as being
|
||||
* {@link Idempotent}, then this fact will be passed to the
|
||||
* {@link RetryPolicy#shouldRetry(Exception, int, int, boolean)} method on
|
||||
* {@link Idempotent} or {@link AtMostOnce}, then this fact will be passed to
|
||||
* the {@link RetryPolicy#shouldRetry(Exception, int, int, boolean)} method on
|
||||
* error, for use in determining whether or not failover should be attempted.
|
||||
*
|
||||
* @return the interface implemented by the proxy objects returned by
|
||||
|
|
|
@ -53,7 +53,7 @@ class RetryInvocationHandler implements RpcInvocationHandler {
|
|||
private final Map<String,RetryPolicy> methodNameToPolicyMap;
|
||||
private Object currentProxy;
|
||||
|
||||
RetryInvocationHandler(FailoverProxyProvider proxyProvider,
|
||||
protected RetryInvocationHandler(FailoverProxyProvider proxyProvider,
|
||||
RetryPolicy retryPolicy) {
|
||||
this(proxyProvider, retryPolicy, Collections.<String, RetryPolicy>emptyMap());
|
||||
}
|
||||
|
@ -97,11 +97,16 @@ class RetryInvocationHandler implements RpcInvocationHandler {
|
|||
hasMadeASuccessfulCall = true;
|
||||
return ret;
|
||||
} catch (Exception e) {
|
||||
boolean isMethodIdempotent = proxyProvider.getInterface()
|
||||
boolean isIdempotentOrAtMostOnce = proxyProvider.getInterface()
|
||||
.getMethod(method.getName(), method.getParameterTypes())
|
||||
.isAnnotationPresent(Idempotent.class);
|
||||
if (!isIdempotentOrAtMostOnce) {
|
||||
isIdempotentOrAtMostOnce = proxyProvider.getInterface()
|
||||
.getMethod(method.getName(), method.getParameterTypes())
|
||||
.isAnnotationPresent(AtMostOnce.class);
|
||||
}
|
||||
RetryAction action = policy.shouldRetry(e, retries++,
|
||||
invocationFailoverCount, isMethodIdempotent);
|
||||
invocationFailoverCount, isIdempotentOrAtMostOnce);
|
||||
if (action.action == RetryAction.RetryDecision.FAIL) {
|
||||
if (action.reason != null) {
|
||||
LOG.warn("Exception while invoking " +
|
||||
|
@ -169,7 +174,7 @@ class RetryInvocationHandler implements RpcInvocationHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private Object invokeMethod(Method method, Object[] args) throws Throwable {
|
||||
protected Object invokeMethod(Method method, Object[] args) throws Throwable {
|
||||
try {
|
||||
if (!method.isAccessible()) {
|
||||
method.setAccessible(true);
|
||||
|
|
|
@ -153,7 +153,7 @@ public class RetryPolicies {
|
|||
static class TryOnceThenFail implements RetryPolicy {
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
return RetryAction.FAIL;
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ public class RetryPolicies {
|
|||
static class RetryForever implements RetryPolicy {
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
return RetryAction.RETRY;
|
||||
}
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ public class RetryPolicies {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
if (retries >= maxRetries) {
|
||||
return RetryAction.FAIL;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ public class RetryPolicies {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int curRetry, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
final Pair p = searchPair(curRetry);
|
||||
if (p == null) {
|
||||
//no more retries.
|
||||
|
@ -435,12 +435,12 @@ public class RetryPolicies {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
RetryPolicy policy = exceptionToPolicyMap.get(e.getClass());
|
||||
if (policy == null) {
|
||||
policy = defaultPolicy;
|
||||
}
|
||||
return policy.shouldRetry(e, retries, failovers, isMethodIdempotent);
|
||||
return policy.shouldRetry(e, retries, failovers, isIdempotentOrAtMostOnce);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ public class RetryPolicies {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception {
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
RetryPolicy policy = null;
|
||||
if (e instanceof RemoteException) {
|
||||
policy = exceptionNameToPolicyMap.get(
|
||||
|
@ -472,7 +472,7 @@ public class RetryPolicies {
|
|||
if (policy == null) {
|
||||
policy = defaultPolicy;
|
||||
}
|
||||
return policy.shouldRetry(e, retries, failovers, isMethodIdempotent);
|
||||
return policy.shouldRetry(e, retries, failovers, isIdempotentOrAtMostOnce);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ public class RetryPolicies {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries,
|
||||
int failovers, boolean isMethodIdempotent) throws Exception {
|
||||
int failovers, boolean isIdempotentOrAtMostOnce) throws Exception {
|
||||
if (failovers >= maxFailovers) {
|
||||
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
|
||||
"failovers (" + failovers + ") exceeded maximum allowed ("
|
||||
|
@ -553,7 +553,7 @@ public class RetryPolicies {
|
|||
calculateExponentialTime(delayMillis, failovers, maxDelayBase));
|
||||
} else if (e instanceof SocketException ||
|
||||
(e instanceof IOException && !(e instanceof RemoteException))) {
|
||||
if (isMethodIdempotent) {
|
||||
if (isIdempotentOrAtMostOnce) {
|
||||
return RetryAction.FAILOVER_AND_RETRY;
|
||||
} else {
|
||||
return new RetryAction(RetryAction.RetryDecision.FAIL, 0,
|
||||
|
@ -562,7 +562,7 @@ public class RetryPolicies {
|
|||
}
|
||||
} else {
|
||||
return fallbackPolicy.shouldRetry(e, retries, failovers,
|
||||
isMethodIdempotent);
|
||||
isIdempotentOrAtMostOnce);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,24 +75,25 @@ public interface RetryPolicy {
|
|||
|
||||
/**
|
||||
* <p>
|
||||
* Determines whether the framework should retry a
|
||||
* method for the given exception, and the number
|
||||
* of retries that have been made for that operation
|
||||
* Determines whether the framework should retry a method for the given
|
||||
* exception, and the number of retries that have been made for that operation
|
||||
* so far.
|
||||
* </p>
|
||||
*
|
||||
* @param e The exception that caused the method to fail
|
||||
* @param retries The number of times the method has been retried
|
||||
* @param failovers The number of times the method has failed over to a
|
||||
* different backend implementation
|
||||
* @param isMethodIdempotent <code>true</code> if the method is idempotent
|
||||
* and so can reasonably be retried on failover when we don't know if the
|
||||
* previous attempt reached the server or not
|
||||
* different backend implementation
|
||||
* @param isIdempotentOrAtMostOnce <code>true</code> if the method is
|
||||
* {@link Idempotent} or {@link AtMostOnce} and so can reasonably be
|
||||
* retried on failover when we don't know if the previous attempt
|
||||
* reached the server or not
|
||||
* @return <code>true</code> if the method should be retried,
|
||||
* <code>false</code> if the method should not be retried
|
||||
* but shouldn't fail with an exception (only for void methods)
|
||||
* @throws Exception The re-thrown exception <code>e</code> indicating
|
||||
* that the method failed and should not be retried further
|
||||
* <code>false</code> if the method should not be retried but
|
||||
* shouldn't fail with an exception (only for void methods)
|
||||
* @throws Exception The re-thrown exception <code>e</code> indicating that
|
||||
* the method failed and should not be retried further
|
||||
*/
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) throws Exception;
|
||||
boolean isIdempotentOrAtMostOnce) throws Exception;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public class TestFailoverProxy {
|
|||
|
||||
@Override
|
||||
public RetryAction shouldRetry(Exception e, int retries, int failovers,
|
||||
boolean isMethodIdempotent) {
|
||||
boolean isIdempotentOrAtMostOnce) {
|
||||
return failovers < 1 ? RetryAction.FAILOVER_AND_RETRY : RetryAction.FAIL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue