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