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.thrift2;
21
22 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deleteFromThrift;
23 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deletesFromHBase;
24 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deletesFromThrift;
25 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.getFromThrift;
26 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.getsFromThrift;
27 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.incrementFromThrift;
28 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.putFromThrift;
29 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.putsFromThrift;
30 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.resultFromHBase;
31 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.resultsFromHBase;
32 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.scanFromThrift;
33 import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.rowMutationsFromThrift;
34 import static org.apache.thrift.TBaseHelper.byteBufferToByteArray;
35
36 import java.io.IOException;
37 import java.lang.reflect.InvocationHandler;
38 import java.lang.reflect.InvocationTargetException;
39 import java.lang.reflect.Method;
40 import java.lang.reflect.Proxy;
41 import java.nio.ByteBuffer;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.concurrent.ConcurrentHashMap;
45 import java.util.concurrent.atomic.AtomicInteger;
46
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49 import org.apache.hadoop.conf.Configuration;
50 import org.apache.hadoop.hbase.client.Delete;
51 import org.apache.hadoop.hbase.client.HTableInterface;
52 import org.apache.hadoop.hbase.client.HTablePool;
53 import org.apache.hadoop.hbase.client.ResultScanner;
54 import org.apache.hadoop.hbase.thrift.ThriftMetrics;
55 import org.apache.hadoop.hbase.thrift2.generated.TDelete;
56 import org.apache.hadoop.hbase.thrift2.generated.TGet;
57 import org.apache.hadoop.hbase.thrift2.generated.THBaseService;
58 import org.apache.hadoop.hbase.thrift2.generated.TIOError;
59 import org.apache.hadoop.hbase.thrift2.generated.TIllegalArgument;
60 import org.apache.hadoop.hbase.thrift2.generated.TIncrement;
61 import org.apache.hadoop.hbase.thrift2.generated.TPut;
62 import org.apache.hadoop.hbase.thrift2.generated.TResult;
63 import org.apache.hadoop.hbase.thrift2.generated.TScan;
64 import org.apache.hadoop.hbase.thrift2.generated.TRowMutations;
65 import org.apache.thrift.TException;
66
67
68
69
70
71 public class ThriftHBaseServiceHandler implements THBaseService.Iface {
72
73
74 private final HTablePool htablePool;
75 private static final Log LOG = LogFactory.getLog(ThriftHBaseServiceHandler.class);
76
77
78
79 private final AtomicInteger nextScannerId = new AtomicInteger(0);
80 private final Map<Integer, ResultScanner> scannerMap =
81 new ConcurrentHashMap<Integer, ResultScanner>();
82
83 public static THBaseService.Iface newInstance(Configuration conf, ThriftMetrics metrics) {
84 THBaseService.Iface handler = new ThriftHBaseServiceHandler(conf);
85 return (THBaseService.Iface) Proxy.newProxyInstance(handler.getClass().getClassLoader(),
86 new Class[] { THBaseService.Iface.class }, new THBaseServiceMetricsProxy(handler, metrics));
87 }
88
89 private static class THBaseServiceMetricsProxy implements InvocationHandler {
90 private final THBaseService.Iface handler;
91 private final ThriftMetrics metrics;
92
93 private THBaseServiceMetricsProxy(THBaseService.Iface handler, ThriftMetrics metrics) {
94 this.handler = handler;
95 this.metrics = metrics;
96 }
97
98 @Override
99 public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
100 Object result;
101 try {
102 long start = now();
103 result = m.invoke(handler, args);
104 int processTime = (int) (now() - start);
105 metrics.incMethodTime(m.getName(), processTime);
106 } catch (InvocationTargetException e) {
107 throw e.getTargetException();
108 } catch (Exception e) {
109 throw new RuntimeException("unexpected invocation exception: " + e.getMessage());
110 }
111 return result;
112 }
113 }
114
115 private static long now() {
116 return System.nanoTime();
117 }
118
119 ThriftHBaseServiceHandler(Configuration conf) {
120 htablePool = new HTablePool(conf, Integer.MAX_VALUE);
121 }
122
123 private HTableInterface getTable(ByteBuffer tableName) {
124 return htablePool.getTable(byteBufferToByteArray(tableName));
125 }
126
127 private void closeTable(HTableInterface table) throws TIOError {
128 try {
129 table.close();
130 } catch (IOException e) {
131 throw getTIOError(e);
132 }
133 }
134
135 private TIOError getTIOError(IOException e) {
136 TIOError err = new TIOError();
137 err.setMessage(e.getMessage());
138 return err;
139 }
140
141
142
143
144
145
146 private int addScanner(ResultScanner scanner) {
147 int id = nextScannerId.getAndIncrement();
148 scannerMap.put(id, scanner);
149 return id;
150 }
151
152
153
154
155
156
157 private ResultScanner getScanner(int id) {
158 return scannerMap.get(id);
159 }
160
161
162
163
164
165
166 protected ResultScanner removeScanner(int id) {
167 return scannerMap.remove(id);
168 }
169
170 @Override
171 public boolean exists(ByteBuffer table, TGet get) throws TIOError, TException {
172 HTableInterface htable = getTable(table);
173 try {
174 return htable.exists(getFromThrift(get));
175 } catch (IOException e) {
176 throw getTIOError(e);
177 } finally {
178 closeTable(htable);
179 }
180 }
181
182 @Override
183 public TResult get(ByteBuffer table, TGet get) throws TIOError, TException {
184 HTableInterface htable = getTable(table);
185 try {
186 return resultFromHBase(htable.get(getFromThrift(get)));
187 } catch (IOException e) {
188 throw getTIOError(e);
189 } finally {
190 closeTable(htable);
191 }
192 }
193
194 @Override
195 public List<TResult> getMultiple(ByteBuffer table, List<TGet> gets) throws TIOError, TException {
196 HTableInterface htable = getTable(table);
197 try {
198 return resultsFromHBase(htable.get(getsFromThrift(gets)));
199 } catch (IOException e) {
200 throw getTIOError(e);
201 } finally {
202 closeTable(htable);
203 }
204 }
205
206 @Override
207 public void put(ByteBuffer table, TPut put) throws TIOError, TException {
208 HTableInterface htable = getTable(table);
209 try {
210 htable.put(putFromThrift(put));
211 } catch (IOException e) {
212 throw getTIOError(e);
213 } finally {
214 closeTable(htable);
215 }
216 }
217
218 @Override
219 public boolean checkAndPut(ByteBuffer table, ByteBuffer row, ByteBuffer family,
220 ByteBuffer qualifier, ByteBuffer value, TPut put) throws TIOError, TException {
221 HTableInterface htable = getTable(table);
222 try {
223 return htable.checkAndPut(byteBufferToByteArray(row), byteBufferToByteArray(family),
224 byteBufferToByteArray(qualifier), (value == null) ? null : byteBufferToByteArray(value),
225 putFromThrift(put));
226 } catch (IOException e) {
227 throw getTIOError(e);
228 } finally {
229 closeTable(htable);
230 }
231 }
232
233 @Override
234 public void putMultiple(ByteBuffer table, List<TPut> puts) throws TIOError, TException {
235 HTableInterface htable = getTable(table);
236 try {
237 htable.put(putsFromThrift(puts));
238 } catch (IOException e) {
239 throw getTIOError(e);
240 } finally {
241 closeTable(htable);
242 }
243 }
244
245 @Override
246 public void deleteSingle(ByteBuffer table, TDelete deleteSingle) throws TIOError, TException {
247 HTableInterface htable = getTable(table);
248 try {
249 htable.delete(deleteFromThrift(deleteSingle));
250 } catch (IOException e) {
251 throw getTIOError(e);
252 } finally {
253 closeTable(htable);
254 }
255 }
256
257 @Override
258 public List<TDelete> deleteMultiple(ByteBuffer table, List<TDelete> deletes) throws TIOError,
259 TException {
260 HTableInterface htable = getTable(table);
261 List<Delete> tempDeletes = deletesFromThrift(deletes);
262 try {
263 htable.delete(tempDeletes);
264 } catch (IOException e) {
265 throw getTIOError(e);
266 } finally {
267 closeTable(htable);
268 }
269 return deletesFromHBase(tempDeletes);
270 }
271
272 @Override
273 public boolean checkAndDelete(ByteBuffer table, ByteBuffer row, ByteBuffer family,
274 ByteBuffer qualifier, ByteBuffer value, TDelete deleteSingle) throws TIOError, TException {
275 HTableInterface htable = getTable(table);
276
277 try {
278 if (value == null) {
279 return htable.checkAndDelete(byteBufferToByteArray(row), byteBufferToByteArray(family),
280 byteBufferToByteArray(qualifier), null, deleteFromThrift(deleteSingle));
281 } else {
282 return htable.checkAndDelete(byteBufferToByteArray(row), byteBufferToByteArray(family),
283 byteBufferToByteArray(qualifier), byteBufferToByteArray(value),
284 deleteFromThrift(deleteSingle));
285 }
286 } catch (IOException e) {
287 throw getTIOError(e);
288 } finally {
289 closeTable(htable);
290 }
291 }
292
293 @Override
294 public TResult increment(ByteBuffer table, TIncrement increment) throws TIOError, TException {
295 HTableInterface htable = getTable(table);
296 try {
297 return resultFromHBase(htable.increment(incrementFromThrift(increment)));
298 } catch (IOException e) {
299 throw getTIOError(e);
300 } finally {
301 closeTable(htable);
302 }
303 }
304
305 @Override
306 public int openScanner(ByteBuffer table, TScan scan) throws TIOError, TException {
307 HTableInterface htable = getTable(table);
308 ResultScanner resultScanner = null;
309 try {
310 resultScanner = htable.getScanner(scanFromThrift(scan));
311 } catch (IOException e) {
312 throw getTIOError(e);
313 } finally {
314 closeTable(htable);
315 }
316 return addScanner(resultScanner);
317 }
318
319 @Override
320 public List<TResult> getScannerRows(int scannerId, int numRows) throws TIOError,
321 TIllegalArgument, TException {
322 ResultScanner scanner = getScanner(scannerId);
323 if (scanner == null) {
324 TIllegalArgument ex = new TIllegalArgument();
325 ex.setMessage("Invalid scanner Id");
326 throw ex;
327 }
328
329 try {
330 return resultsFromHBase(scanner.next(numRows));
331 } catch (IOException e) {
332 throw getTIOError(e);
333 }
334 }
335
336 @Override
337 public void closeScanner(int scannerId) throws TIOError, TIllegalArgument, TException {
338 LOG.debug("scannerClose: id=" + scannerId);
339 ResultScanner scanner = getScanner(scannerId);
340 if (scanner == null) {
341 String message = "scanner ID is invalid";
342 LOG.warn(message);
343 TIllegalArgument ex = new TIllegalArgument();
344 ex.setMessage("Invalid scanner Id");
345 throw ex;
346 }
347 scanner.close();
348 removeScanner(scannerId);
349 }
350
351 @Override
352 public void mutateRow(ByteBuffer table, TRowMutations rowMutations) throws TIOError, TException {
353 HTableInterface htable = getTable(table);
354 try {
355 htable.mutateRow(rowMutationsFromThrift(rowMutations));
356 } catch (IOException e) {
357 throw getTIOError(e);
358 } finally {
359 closeTable(htable);
360 }
361 }
362 }