1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import com.google.protobuf.Service;
22 import com.google.protobuf.ServiceException;
23 import org.apache.hadoop.classification.InterfaceAudience;
24 import org.apache.hadoop.classification.InterfaceStability;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.hbase.HBaseConfiguration;
27 import org.apache.hadoop.hbase.HTableDescriptor;
28 import org.apache.hadoop.hbase.client.coprocessor.Batch;
29 import org.apache.hadoop.hbase.client.coprocessor.Batch.Callback;
30 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
31 import org.apache.hadoop.hbase.util.Bytes;
32 import org.apache.hadoop.hbase.util.PoolMap;
33 import org.apache.hadoop.hbase.util.PoolMap.PoolType;
34
35 import java.io.Closeable;
36 import java.io.IOException;
37 import java.util.Collection;
38 import java.util.List;
39 import java.util.Map;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 @InterfaceAudience.Public
64 @InterfaceStability.Stable
65 public class HTablePool implements Closeable {
66 private final PoolMap<String, HTableInterface> tables;
67 private final int maxSize;
68 private final PoolType poolType;
69 private final Configuration config;
70 private final HTableInterfaceFactory tableFactory;
71
72
73
74
75 public HTablePool() {
76 this(HBaseConfiguration.create(), Integer.MAX_VALUE);
77 }
78
79
80
81
82
83
84
85
86
87 public HTablePool(final Configuration config, final int maxSize) {
88 this(config, maxSize, null, null);
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102 public HTablePool(final Configuration config, final int maxSize,
103 final HTableInterfaceFactory tableFactory) {
104 this(config, maxSize, tableFactory, PoolType.Reusable);
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public HTablePool(final Configuration config, final int maxSize,
120 final PoolType poolType) {
121 this(config, maxSize, null, poolType);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 public HTablePool(final Configuration config, final int maxSize,
142 final HTableInterfaceFactory tableFactory, PoolType poolType) {
143
144
145 this.config = config == null ? HBaseConfiguration.create() : config;
146 this.maxSize = maxSize;
147 this.tableFactory = tableFactory == null ? new HTableFactory()
148 : tableFactory;
149 if (poolType == null) {
150 this.poolType = PoolType.Reusable;
151 } else {
152 switch (poolType) {
153 case Reusable:
154 case ThreadLocal:
155 this.poolType = poolType;
156 break;
157 default:
158 this.poolType = PoolType.Reusable;
159 break;
160 }
161 }
162 this.tables = new PoolMap<String, HTableInterface>(this.poolType,
163 this.maxSize);
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177 public HTableInterface getTable(String tableName) {
178
179 HTableInterface table = findOrCreateTable(tableName);
180
181
182 return new PooledHTable(table);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197 private HTableInterface findOrCreateTable(String tableName) {
198 HTableInterface table = tables.get(tableName);
199 if (table == null) {
200 table = createHTable(tableName);
201 }
202 return table;
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217 public HTableInterface getTable(byte[] tableName) {
218 return getTable(Bytes.toString(tableName));
219 }
220
221
222
223
224
225
226
227
228
229 public void putTable(HTableInterface table) throws IOException {
230
231
232
233
234
235
236 if (table instanceof PooledHTable) {
237 returnTable(((PooledHTable) table).getWrappedTable());
238 } else {
239
240
241
242
243 throw new IllegalArgumentException("not a pooled table: " + table);
244 }
245 }
246
247
248
249
250
251
252
253
254
255
256
257 private void returnTable(HTableInterface table) throws IOException {
258
259 String tableName = Bytes.toString(table.getTableName());
260 if (tables.size(tableName) >= maxSize) {
261
262 this.tables.remove(tableName, table);
263 this.tableFactory.releaseHTableInterface(table);
264 return;
265 }
266 tables.put(tableName, table);
267 }
268
269 protected HTableInterface createHTable(String tableName) {
270 return this.tableFactory.createHTableInterface(config,
271 Bytes.toBytes(tableName));
272 }
273
274
275
276
277
278
279
280
281
282
283
284 public void closeTablePool(final String tableName) throws IOException {
285 Collection<HTableInterface> tables = this.tables.values(tableName);
286 if (tables != null) {
287 for (HTableInterface table : tables) {
288 this.tableFactory.releaseHTableInterface(table);
289 }
290 }
291 this.tables.remove(tableName);
292 }
293
294
295
296
297
298
299 public void closeTablePool(final byte[] tableName) throws IOException {
300 closeTablePool(Bytes.toString(tableName));
301 }
302
303
304
305
306
307
308
309 public void close() throws IOException {
310 for (String tableName : tables.keySet()) {
311 closeTablePool(tableName);
312 }
313 this.tables.clear();
314 }
315
316 public int getCurrentPoolSize(String tableName) {
317 return tables.size(tableName);
318 }
319
320
321
322
323
324
325 class PooledHTable implements HTableInterface {
326
327 private HTableInterface table;
328
329 public PooledHTable(HTableInterface table) {
330 this.table = table;
331 }
332
333 @Override
334 public byte[] getTableName() {
335 return table.getTableName();
336 }
337
338 @Override
339 public Configuration getConfiguration() {
340 return table.getConfiguration();
341 }
342
343 @Override
344 public HTableDescriptor getTableDescriptor() throws IOException {
345 return table.getTableDescriptor();
346 }
347
348 @Override
349 public boolean exists(Get get) throws IOException {
350 return table.exists(get);
351 }
352
353 @Override
354 public Boolean[] exists(List<Get> gets) throws IOException {
355 return table.exists(gets);
356 }
357
358 @Override
359 public void batch(List<? extends Row> actions, Object[] results) throws IOException,
360 InterruptedException {
361 table.batch(actions, results);
362 }
363
364 @Override
365 public Object[] batch(List<? extends Row> actions) throws IOException,
366 InterruptedException {
367 return table.batch(actions);
368 }
369
370 @Override
371 public Result get(Get get) throws IOException {
372 return table.get(get);
373 }
374
375 @Override
376 public Result[] get(List<Get> gets) throws IOException {
377 return table.get(gets);
378 }
379
380 @Override
381 @SuppressWarnings("deprecation")
382 public Result getRowOrBefore(byte[] row, byte[] family) throws IOException {
383 return table.getRowOrBefore(row, family);
384 }
385
386 @Override
387 public ResultScanner getScanner(Scan scan) throws IOException {
388 return table.getScanner(scan);
389 }
390
391 @Override
392 public ResultScanner getScanner(byte[] family) throws IOException {
393 return table.getScanner(family);
394 }
395
396 @Override
397 public ResultScanner getScanner(byte[] family, byte[] qualifier)
398 throws IOException {
399 return table.getScanner(family, qualifier);
400 }
401
402 @Override
403 public void put(Put put) throws IOException {
404 table.put(put);
405 }
406
407 @Override
408 public void put(List<Put> puts) throws IOException {
409 table.put(puts);
410 }
411
412 @Override
413 public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier,
414 byte[] value, Put put) throws IOException {
415 return table.checkAndPut(row, family, qualifier, value, put);
416 }
417
418 @Override
419 public void delete(Delete delete) throws IOException {
420 table.delete(delete);
421 }
422
423 @Override
424 public void delete(List<Delete> deletes) throws IOException {
425 table.delete(deletes);
426 }
427
428 @Override
429 public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier,
430 byte[] value, Delete delete) throws IOException {
431 return table.checkAndDelete(row, family, qualifier, value, delete);
432 }
433
434 @Override
435 public Result increment(Increment increment) throws IOException {
436 return table.increment(increment);
437 }
438
439 @Override
440 public long incrementColumnValue(byte[] row, byte[] family,
441 byte[] qualifier, long amount) throws IOException {
442 return table.incrementColumnValue(row, family, qualifier, amount);
443 }
444
445 @Override
446 public long incrementColumnValue(byte[] row, byte[] family,
447 byte[] qualifier, long amount, boolean writeToWAL) throws IOException {
448 return table.incrementColumnValue(row, family, qualifier, amount,
449 writeToWAL);
450 }
451
452 @Override
453 public boolean isAutoFlush() {
454 return table.isAutoFlush();
455 }
456
457 @Override
458 public void flushCommits() throws IOException {
459 table.flushCommits();
460 }
461
462
463
464
465
466
467 public void close() throws IOException {
468 returnTable(table);
469 }
470
471 @Override
472 public CoprocessorRpcChannel coprocessorService(byte[] row) {
473 return table.coprocessorService(row);
474 }
475
476 @Override
477 public <T extends Service, R> Map<byte[], R> coprocessorService(Class<T> service,
478 byte[] startKey, byte[] endKey, Batch.Call<T, R> callable)
479 throws ServiceException, Throwable {
480 return table.coprocessorService(service, startKey, endKey, callable);
481 }
482
483 @Override
484 public <T extends Service, R> void coprocessorService(Class<T> service,
485 byte[] startKey, byte[] endKey, Batch.Call<T, R> callable, Callback<R> callback)
486 throws ServiceException, Throwable {
487 table.coprocessorService(service, startKey, endKey, callable, callback);
488 }
489
490 @Override
491 public String toString() {
492 return "PooledHTable{" + ", table=" + table + '}';
493 }
494
495
496
497
498
499
500 HTableInterface getWrappedTable() {
501 return table;
502 }
503
504 @Override
505 public <R> void batchCallback(List<? extends Row> actions,
506 Object[] results, Callback<R> callback) throws IOException,
507 InterruptedException {
508 table.batchCallback(actions, results, callback);
509 }
510
511 @Override
512 public <R> Object[] batchCallback(List<? extends Row> actions,
513 Callback<R> callback) throws IOException, InterruptedException {
514 return table.batchCallback(actions, callback);
515 }
516
517 @Override
518 public void mutateRow(RowMutations rm) throws IOException {
519 table.mutateRow(rm);
520 }
521
522 @Override
523 public Result append(Append append) throws IOException {
524 return table.append(append);
525 }
526
527 @Override
528 public void setAutoFlush(boolean autoFlush) {
529 table.setAutoFlush(autoFlush);
530 }
531
532 @Override
533 public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
534 table.setAutoFlush(autoFlush, clearBufferOnFail);
535 }
536
537 @Override
538 public long getWriteBufferSize() {
539 return table.getWriteBufferSize();
540 }
541
542 @Override
543 public void setWriteBufferSize(long writeBufferSize) throws IOException {
544 table.setWriteBufferSize(writeBufferSize);
545 }
546 }
547 }