HADOOP-9786. RetryInvocationHandler#isRpcInvocation should support ProtocolTranslator. Contributed by Suresh Srinivas and Jing Zhao.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1508304 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jing Zhao 2013-07-30 05:22:32 +00:00
parent 3ca892dc0a
commit f451228250
3 changed files with 47 additions and 6 deletions

View File

@ -500,6 +500,9 @@ Release 2.1.0-beta - 2013-07-02
HADOOP-9770. Make RetryCache#state non volatile. (suresh) HADOOP-9770. Make RetryCache#state non volatile. (suresh)
HADOOP-9786. RetryInvocationHandler#isRpcInvocation should support
ProtocolTranslator. (suresh and jing9)
OPTIMIZATIONS OPTIMIZATIONS
HADOOP-9150. Avoid unnecessary DNS resolution attempts for logical URIs HADOOP-9150. Avoid unnecessary DNS resolution attempts for logical URIs

View File

@ -30,12 +30,13 @@
import org.apache.hadoop.io.retry.RetryPolicy.RetryAction; import org.apache.hadoop.io.retry.RetryPolicy.RetryAction;
import org.apache.hadoop.ipc.Client; import org.apache.hadoop.ipc.Client;
import org.apache.hadoop.ipc.Client.ConnectionId; import org.apache.hadoop.ipc.Client.ConnectionId;
import org.apache.hadoop.ipc.ProtocolTranslator;
import org.apache.hadoop.ipc.RPC; import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RpcConstants; import org.apache.hadoop.ipc.RpcConstants;
import org.apache.hadoop.ipc.RpcInvocationHandler; import org.apache.hadoop.ipc.RpcInvocationHandler;
import org.apache.hadoop.util.ThreadUtil; import org.apache.hadoop.util.ThreadUtil;
import com.google.common.base.Preconditions; import com.google.common.annotations.VisibleForTesting;
class RetryInvocationHandler implements RpcInvocationHandler { class RetryInvocationHandler implements RpcInvocationHandler {
public static final Log LOG = LogFactory.getLog(RetryInvocationHandler.class); public static final Log LOG = LogFactory.getLog(RetryInvocationHandler.class);
@ -75,7 +76,7 @@ public Object invoke(Object proxy, Method method, Object[] args)
// The number of times this method invocation has been failed over. // The number of times this method invocation has been failed over.
int invocationFailoverCount = 0; int invocationFailoverCount = 0;
final boolean isRpc = isRpcInvocation(); final boolean isRpc = isRpcInvocation(currentProxy);
final int callId = isRpc? Client.nextCallId(): RpcConstants.INVALID_CALL_ID; final int callId = isRpc? Client.nextCallId(): RpcConstants.INVALID_CALL_ID;
int retries = 0; int retries = 0;
while (true) { while (true) {
@ -178,11 +179,15 @@ private Object invokeMethod(Method method, Object[] args) throws Throwable {
} }
} }
private boolean isRpcInvocation() { @VisibleForTesting
if (!Proxy.isProxyClass(currentProxy.getClass())) { static boolean isRpcInvocation(Object proxy) {
if (proxy instanceof ProtocolTranslator) {
proxy = ((ProtocolTranslator) proxy).getUnderlyingProxyObject();
}
if (!Proxy.isProxyClass(proxy.getClass())) {
return false; return false;
} }
final InvocationHandler ih = Proxy.getInvocationHandler(currentProxy); final InvocationHandler ih = Proxy.getInvocationHandler(proxy);
return ih instanceof RpcInvocationHandler; return ih instanceof RpcInvocationHandler;
} }

View File

@ -35,6 +35,7 @@
import org.apache.hadoop.io.retry.UnreliableInterface.FatalException; 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.RemoteException; import org.apache.hadoop.ipc.RemoteException;
public class TestRetryProxy extends TestCase { public class TestRetryProxy extends TestCase {
@ -58,6 +59,38 @@ public void testTryOnceThenFail() throws UnreliableException {
} }
} }
/**
* Test for {@link RetryInvocationHandler#isRpcInvocation(Object)}
*/
public void testRpcInvocation() throws Exception {
// For a proxy method should return true
final UnreliableInterface unreliable = (UnreliableInterface)
RetryProxy.create(UnreliableInterface.class, unreliableImpl, RETRY_FOREVER);
assertTrue(RetryInvocationHandler.isRpcInvocation(unreliable));
// Embed the proxy in ProtocolTranslator
ProtocolTranslator xlator = new ProtocolTranslator() {
int count = 0;
@Override
public Object getUnderlyingProxyObject() {
count++;
return unreliable;
}
@Override
public String toString() {
return "" + count;
}
};
// For a proxy wrapped in ProtocolTranslator method should return true
assertTrue(RetryInvocationHandler.isRpcInvocation(xlator));
// Ensure underlying proxy was looked at
assertEquals(xlator.toString(), "1");
// For non-proxy the method must return false
assertFalse(RetryInvocationHandler.isRpcInvocation(new Object()));
}
public void testRetryForever() throws UnreliableException { public void testRetryForever() throws UnreliableException {
UnreliableInterface unreliable = (UnreliableInterface) UnreliableInterface unreliable = (UnreliableInterface)
RetryProxy.create(UnreliableInterface.class, unreliableImpl, RETRY_FOREVER); RetryProxy.create(UnreliableInterface.class, unreliableImpl, RETRY_FOREVER);
@ -138,7 +171,7 @@ public void testRetryByException() throws UnreliableException {
} }
} }
public void testRetryByRemoteException() throws UnreliableException { public void testRetryByRemoteException() {
Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap = Map<Class<? extends Exception>, RetryPolicy> exceptionToPolicyMap =
Collections.<Class<? extends Exception>, RetryPolicy>singletonMap(FatalException.class, TRY_ONCE_THEN_FAIL); Collections.<Class<? extends Exception>, RetryPolicy>singletonMap(FatalException.class, TRY_ONCE_THEN_FAIL);