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