1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.ipc;
21
22 import com.google.protobuf.Message;
23 import com.google.protobuf.ServiceException;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.CellScanner;
28 import org.apache.hadoop.hbase.IpcProtocol;
29 import org.apache.hadoop.hbase.security.User;
30 import org.apache.hadoop.hbase.util.Pair;
31 import org.apache.hadoop.ipc.RemoteException;
32
33 import java.io.IOException;
34 import java.lang.reflect.InvocationHandler;
35 import java.lang.reflect.Method;
36 import java.lang.reflect.Proxy;
37 import java.net.InetSocketAddress;
38 import java.util.Map;
39 import java.util.concurrent.ConcurrentHashMap;
40
41 public class ProtobufRpcClientEngine implements RpcClientEngine {
42
43 private static final Log LOG =
44 LogFactory.getLog("org.apache.hadoop.hbase.ipc.ProtobufRpcClientEngine");
45
46 public HBaseClient getClient() {
47 return client;
48 }
49
50 protected HBaseClient client;
51
52 public ProtobufRpcClientEngine(Configuration conf, String clusterId) {
53 this.client = new HBaseClient(conf, clusterId);
54 }
55
56
57 @Override
58 public <T extends IpcProtocol> T getProxy(
59 Class<T> protocol, InetSocketAddress addr,
60 Configuration conf, int rpcTimeout) throws IOException {
61 final Invoker invoker = new Invoker(protocol, addr, User.getCurrent(), rpcTimeout, client);
62 return (T) Proxy.newProxyInstance(
63 protocol.getClassLoader(), new Class[]{protocol}, invoker);
64 }
65
66 @Override
67 public void close() {
68 this.client.stop();
69 }
70
71 static class Invoker implements InvocationHandler {
72 private static final Map<String, Message> returnTypes =
73 new ConcurrentHashMap<String, Message>();
74 private Class<? extends IpcProtocol> protocol;
75 private InetSocketAddress address;
76 private User ticket;
77 private HBaseClient client;
78 final private int rpcTimeout;
79
80 public Invoker(Class<? extends IpcProtocol> protocol, InetSocketAddress addr, User ticket,
81 int rpcTimeout, HBaseClient client)
82 throws IOException {
83 this.protocol = protocol;
84 this.address = addr;
85 this.ticket = ticket;
86 this.client = client;
87 this.rpcTimeout = rpcTimeout;
88 }
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 @Override
109 public Object invoke(Object proxy, Method method, Object[] args)
110 throws ServiceException {
111 long startTime = 0;
112 if (LOG.isTraceEnabled()) {
113 startTime = System.currentTimeMillis();
114 }
115 if (args.length != 2) {
116 throw new ServiceException(method.getName() + " didn't get two args: " + args.length);
117 }
118
119
120 PayloadCarryingRpcController controller = (PayloadCarryingRpcController)args[0];
121 CellScanner cells = null;
122 if (controller != null) {
123 cells = controller.cellScanner();
124
125 controller.setCellScanner(null);
126 }
127
128 Message param = (Message)args[1];
129 Pair<Message, CellScanner> val = null;
130 try {
131 val = client.call(method, param, cells, address, protocol, ticket, rpcTimeout);
132 if (controller != null) {
133
134 if (val.getSecond() != null) controller.setCellScanner(val.getSecond());
135 } else if (val.getSecond() != null) {
136 throw new ServiceException("Client dropping data on the floor!");
137 }
138
139 if (LOG.isTraceEnabled()) {
140 long callTime = System.currentTimeMillis() - startTime;
141 if (LOG.isTraceEnabled()) LOG.trace("Call: " + method.getName() + " " + callTime);
142 }
143 return val.getFirst();
144 } catch (Throwable e) {
145 if (e instanceof RemoteException) {
146 Throwable cause = ((RemoteException)e).unwrapRemoteException();
147 throw new ServiceException("methodName=" + method.getName(), cause);
148 }
149 throw new ServiceException(e);
150 }
151 }
152
153 static Message getReturnProtoType(Method method) throws Exception {
154 if (returnTypes.containsKey(method.getName())) {
155 return returnTypes.get(method.getName());
156 }
157 Class<?> returnType = method.getReturnType();
158 if (returnType.getName().equals("void")) return null;
159 Method newInstMethod = returnType.getMethod("getDefaultInstance");
160 newInstMethod.setAccessible(true);
161 Message protoType = (Message) newInstMethod.invoke(null, (Object[]) null);
162 returnTypes.put(method.getName(), protoType);
163 return protoType;
164 }
165 }
166 }