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
34 import java.io.IOException;
35 import java.lang.reflect.InvocationHandler;
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.Method;
38 import java.lang.reflect.Proxy;
39 import java.nio.ByteBuffer;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.atomic.AtomicInteger;
44
45 import org.apache.commons.logging.Log;
46 import org.apache.commons.logging.LogFactory;
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 public class ThriftHBaseServiceHandler implements THBaseService.Iface {
69
70
71 private final HTablePool htablePool;
72 private static final Log LOG = LogFactory.getLog(ThriftHBaseServiceHandler.class);
73
74
75
76 private final AtomicInteger nextScannerId = new AtomicInteger(0);
77 private final Map<Integer, ResultScanner> scannerMap = new ConcurrentHashMap<Integer, ResultScanner>();
78
79 public static THBaseService.Iface newInstance(
80 Configuration conf, ThriftMetrics metrics) {
81 THBaseService.Iface handler = new ThriftHBaseServiceHandler(conf);
82 return (THBaseService.Iface) Proxy.newProxyInstance(
83 handler.getClass().getClassLoader(),
84 new Class[]{THBaseService.Iface.class},
85 new THBaseServiceMetricsProxy(handler, metrics));
86 }
87
88 private static class THBaseServiceMetricsProxy implements InvocationHandler {
89 private final THBaseService.Iface handler;
90 private final ThriftMetrics metrics;
91
92 private THBaseServiceMetricsProxy(
93 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)
100 throws Throwable {
101 Object result;
102 try {
103 long start = now();
104 result = m.invoke(handler, args);
105 int processTime = (int)(now() - start);
106 metrics.incMethodTime(m.getName(), processTime);
107 } catch (InvocationTargetException e) {
108 throw e.getTargetException();
109 } catch (Exception e) {
110 throw new RuntimeException(
111 "unexpected invocation exception: " + e.getMessage());
112 }
113 return result;
114 }
115 }
116
117 private static long now() {
118 return System.nanoTime();
119 }
120
121 ThriftHBaseServiceHandler(Configuration conf) {
122 htablePool = new HTablePool(conf, Integer.MAX_VALUE);
123 }
124
125 private HTableInterface getTable(byte[] tableName) {
126 return htablePool.getTable(tableName);
127 }
128
129 private void closeTable(HTableInterface table) throws TIOError {
130 try {
131 table.close();
132 } catch (IOException e) {
133 throw getTIOError(e);
134 }
135 }
136
137 private TIOError getTIOError(IOException e) {
138 TIOError err = new TIOError();
139 err.setMessage(e.getMessage());
140 return err;
141 }
142
143
144
145
146
147
148
149 private int addScanner(ResultScanner scanner) {
150 int id = nextScannerId.getAndIncrement();
151 scannerMap.put(id, scanner);
152 return id;
153 }
154
155
156
157
158
159
160
161 private ResultScanner getScanner(int id) {
162 return scannerMap.get(id);
163 }
164
165
166
167
168
169
170
171 protected ResultScanner removeScanner(int id) {
172 return scannerMap.remove(id);
173 }
174
175 @Override
176 public boolean exists(ByteBuffer table, TGet get) throws TIOError, TException {
177 HTableInterface htable = getTable(table.array());
178 try {
179 return htable.exists(getFromThrift(get));
180 } catch (IOException e) {
181 throw getTIOError(e);
182 } finally {
183 closeTable(htable);
184 }
185 }
186
187 @Override
188 public TResult get(ByteBuffer table, TGet get) throws TIOError, TException {
189 HTableInterface htable = getTable(table.array());
190 try {
191 return resultFromHBase(htable.get(getFromThrift(get)));
192 } catch (IOException e) {
193 throw getTIOError(e);
194 } finally {
195 closeTable(htable);
196 }
197 }
198
199 @Override
200 public List<TResult> getMultiple(ByteBuffer table, List<TGet> gets) throws TIOError, TException {
201 HTableInterface htable = getTable(table.array());
202 try {
203 return resultsFromHBase(htable.get(getsFromThrift(gets)));
204 } catch (IOException e) {
205 throw getTIOError(e);
206 } finally {
207 closeTable(htable);
208 }
209 }
210
211 @Override
212 public void put(ByteBuffer table, TPut put) throws TIOError, TException {
213 HTableInterface htable = getTable(table.array());
214 try {
215 htable.put(putFromThrift(put));
216 } catch (IOException e) {
217 throw getTIOError(e);
218 } finally {
219 closeTable(htable);
220 }
221 }
222
223 @Override
224 public boolean checkAndPut(ByteBuffer table, ByteBuffer row, ByteBuffer family, ByteBuffer qualifier, ByteBuffer value, TPut put)
225 throws TIOError, TException {
226 HTableInterface htable = getTable(table.array());
227 try {
228 return htable.checkAndPut(row.array(), family.array(), qualifier.array(), (value == null) ? null : value.array(), putFromThrift(put));
229 } catch (IOException e) {
230 throw getTIOError(e);
231 } finally {
232 closeTable(htable);
233 }
234 }
235
236 @Override
237 public void putMultiple(ByteBuffer table, List<TPut> puts) throws TIOError, TException {
238 HTableInterface htable = getTable(table.array());
239 try {
240 htable.put(putsFromThrift(puts));
241 } catch (IOException e) {
242 throw getTIOError(e);
243 } finally {
244 closeTable(htable);
245 }
246 }
247
248 @Override
249 public void deleteSingle(ByteBuffer table, TDelete deleteSingle) throws TIOError, TException {
250 HTableInterface htable = getTable(table.array());
251 try {
252 htable.delete(deleteFromThrift(deleteSingle));
253 } catch (IOException e) {
254 throw getTIOError(e);
255 } finally {
256 closeTable(htable);
257 }
258 }
259
260 @Override
261 public List<TDelete> deleteMultiple(ByteBuffer table, List<TDelete> deletes) throws TIOError, TException {
262 HTableInterface htable = getTable(table.array());
263 List<Delete> tempDeletes = deletesFromThrift(deletes);
264 try {
265 htable.delete(tempDeletes);
266 } catch (IOException e) {
267 throw getTIOError(e);
268 } finally {
269 closeTable(htable);
270 }
271 return deletesFromHBase(tempDeletes);
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 }