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