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