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.DataInput;
24 import java.io.DataOutput;
25 import java.io.IOException;
26 import java.lang.reflect.Proxy;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Collections;
32 import java.util.NavigableMap;
33 import java.util.TreeMap;
34 import java.util.concurrent.ExecutorService;
35 import java.util.concurrent.SynchronousQueue;
36 import java.util.concurrent.ThreadFactory;
37 import java.util.concurrent.ThreadPoolExecutor;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.atomic.AtomicInteger;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.apache.hadoop.conf.Configuration;
44 import org.apache.hadoop.hbase.HBaseConfiguration;
45 import org.apache.hadoop.hbase.HConstants;
46 import org.apache.hadoop.hbase.HRegionInfo;
47 import org.apache.hadoop.hbase.HRegionLocation;
48 import org.apache.hadoop.hbase.HServerAddress;
49 import org.apache.hadoop.hbase.HTableDescriptor;
50 import org.apache.hadoop.hbase.KeyValue;
51 import org.apache.hadoop.hbase.ServerName;
52 import org.apache.hadoop.hbase.client.HConnectionManager.HConnectable;
53 import org.apache.hadoop.hbase.client.coprocessor.Batch;
54 import org.apache.hadoop.hbase.ipc.CoprocessorProtocol;
55 import org.apache.hadoop.hbase.ipc.ExecRPCInvoker;
56 import org.apache.hadoop.hbase.util.Addressing;
57 import org.apache.hadoop.hbase.util.Bytes;
58 import org.apache.hadoop.hbase.util.Pair;
59 import org.apache.hadoop.hbase.util.Threads;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public class HTable implements HTableInterface {
103 private static final Log LOG = LogFactory.getLog(HTable.class);
104 private HConnection connection;
105 private final byte [] tableName;
106 private volatile Configuration configuration;
107 private final ArrayList<Put> writeBuffer = new ArrayList<Put>();
108 private long writeBufferSize;
109 private boolean clearBufferOnFail;
110 private boolean autoFlush;
111 private long currentWriteBufferSize;
112 protected int scannerCaching;
113 private int maxKeyValueSize;
114 private ExecutorService pool;
115 private boolean closed;
116 private int operationTimeout;
117 private final boolean cleanupPoolOnClose;
118 private final boolean cleanupConnectionOnClose;
119
120
121
122
123
124
125
126
127
128
129
130 public HTable(Configuration conf, final String tableName)
131 throws IOException {
132 this(conf, Bytes.toBytes(tableName));
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146 public HTable(Configuration conf, final byte [] tableName)
147 throws IOException {
148 this.tableName = tableName;
149 this.cleanupPoolOnClose = this.cleanupConnectionOnClose = true;
150 if (conf == null) {
151 this.connection = null;
152 return;
153 }
154 this.connection = HConnectionManager.getConnection(conf);
155 this.configuration = conf;
156
157 int maxThreads = conf.getInt("hbase.htable.threads.max", Integer.MAX_VALUE);
158 if (maxThreads == 0) {
159 maxThreads = 1;
160 }
161 long keepAliveTime = conf.getLong("hbase.htable.threads.keepalivetime", 60);
162
163
164
165
166
167 this.pool = new ThreadPoolExecutor(1, maxThreads,
168 keepAliveTime, TimeUnit.SECONDS,
169 new SynchronousQueue<Runnable>(),
170 Threads.newDaemonThreadFactory("hbase-table"));
171 ((ThreadPoolExecutor)this.pool).allowCoreThreadTimeOut(true);
172
173 this.finishSetup();
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public HTable(Configuration conf, final byte[] tableName, final ExecutorService pool)
189 throws IOException {
190 this.connection = HConnectionManager.getConnection(conf);
191 this.configuration = conf;
192 this.pool = pool;
193 this.tableName = tableName;
194 this.cleanupPoolOnClose = false;
195 this.cleanupConnectionOnClose = true;
196
197 this.finishSetup();
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211 public HTable(final byte[] tableName, final HConnection connection,
212 final ExecutorService pool) throws IOException {
213 if (pool == null || pool.isShutdown()) {
214 throw new IllegalArgumentException("Pool is null or shut down.");
215 }
216 if (connection == null || connection.isClosed()) {
217 throw new IllegalArgumentException("Connection is null or closed.");
218 }
219 this.tableName = tableName;
220 this.cleanupPoolOnClose = this.cleanupConnectionOnClose = false;
221 this.connection = connection;
222 this.configuration = connection.getConfiguration();
223 this.pool = pool;
224
225 this.finishSetup();
226 }
227
228
229
230
231
232 private void finishSetup() throws IOException {
233 this.connection.locateRegion(tableName, HConstants.EMPTY_START_ROW);
234 this.operationTimeout = HTableDescriptor.isMetaTable(tableName) ? HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT
235 : this.configuration.getInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT,
236 HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT);
237 this.writeBufferSize = this.configuration.getLong(
238 "hbase.client.write.buffer", 2097152);
239 this.clearBufferOnFail = true;
240 this.autoFlush = true;
241 this.currentWriteBufferSize = 0;
242 this.scannerCaching = this.configuration.getInt(
243 "hbase.client.scanner.caching", 1);
244
245 this.maxKeyValueSize = this.configuration.getInt(
246 "hbase.client.keyvalue.maxsize", -1);
247 this.closed = false;
248 }
249
250
251
252
253 @Override
254 public Configuration getConfiguration() {
255 return configuration;
256 }
257
258
259
260
261
262
263
264
265
266
267 @Deprecated
268 public static boolean isTableEnabled(String tableName) throws IOException {
269 return isTableEnabled(Bytes.toBytes(tableName));
270 }
271
272
273
274
275
276
277
278
279
280
281 @Deprecated
282 public static boolean isTableEnabled(byte[] tableName) throws IOException {
283 return isTableEnabled(HBaseConfiguration.create(), tableName);
284 }
285
286
287
288
289
290
291
292
293
294 @Deprecated
295 public static boolean isTableEnabled(Configuration conf, String tableName)
296 throws IOException {
297 return isTableEnabled(conf, Bytes.toBytes(tableName));
298 }
299
300
301
302
303
304
305
306
307 public static boolean isTableEnabled(Configuration conf,
308 final byte[] tableName) throws IOException {
309 return HConnectionManager.execute(new HConnectable<Boolean>(conf) {
310 @Override
311 public Boolean connect(HConnection connection) throws IOException {
312 return connection.isTableEnabled(tableName);
313 }
314 });
315 }
316
317
318
319
320
321
322
323 public HRegionLocation getRegionLocation(final String row)
324 throws IOException {
325 return connection.getRegionLocation(tableName, Bytes.toBytes(row), false);
326 }
327
328
329
330
331
332
333
334
335 public HRegionLocation getRegionLocation(final byte [] row)
336 throws IOException {
337 return connection.getRegionLocation(tableName, row, false);
338 }
339
340
341
342
343
344
345
346
347
348 public HRegionLocation getRegionLocation(final byte [] row, boolean reload)
349 throws IOException {
350 return connection.getRegionLocation(tableName, row, reload);
351 }
352
353
354
355
356 @Override
357 public byte [] getTableName() {
358 return this.tableName;
359 }
360
361
362
363
364
365
366
367
368 public HConnection getConnection() {
369 return this.connection;
370 }
371
372
373
374
375
376
377
378 public int getScannerCaching() {
379 return scannerCaching;
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393 public void setScannerCaching(int scannerCaching) {
394 this.scannerCaching = scannerCaching;
395 }
396
397
398
399
400 @Override
401 public HTableDescriptor getTableDescriptor() throws IOException {
402 return new UnmodifyableHTableDescriptor(
403 this.connection.getHTableDescriptor(this.tableName));
404 }
405
406
407
408
409
410
411
412
413 public byte [][] getStartKeys() throws IOException {
414 return getStartEndKeys().getFirst();
415 }
416
417
418
419
420
421
422
423
424 public byte[][] getEndKeys() throws IOException {
425 return getStartEndKeys().getSecond();
426 }
427
428
429
430
431
432
433
434
435
436 public Pair<byte[][],byte[][]> getStartEndKeys() throws IOException {
437 NavigableMap<HRegionInfo, ServerName> regions = getRegionLocations();
438 final List<byte[]> startKeyList = new ArrayList<byte[]>(regions.size());
439 final List<byte[]> endKeyList = new ArrayList<byte[]>(regions.size());
440
441 for (HRegionInfo region : regions.keySet()) {
442 startKeyList.add(region.getStartKey());
443 endKeyList.add(region.getEndKey());
444 }
445
446 return new Pair<byte [][], byte [][]>(
447 startKeyList.toArray(new byte[startKeyList.size()][]),
448 endKeyList.toArray(new byte[endKeyList.size()][]));
449 }
450
451
452
453
454
455
456
457 public Map<HRegionInfo, HServerAddress> getRegionsInfo() throws IOException {
458 final Map<HRegionInfo, HServerAddress> regionMap =
459 new TreeMap<HRegionInfo, HServerAddress>();
460
461 final Map<HRegionInfo, ServerName> regionLocations = getRegionLocations();
462
463 for (Map.Entry<HRegionInfo, ServerName> entry : regionLocations.entrySet()) {
464 HServerAddress server = new HServerAddress();
465 ServerName serverName = entry.getValue();
466 if (serverName != null && serverName.getHostAndPort() != null) {
467 server = new HServerAddress(Addressing.createInetSocketAddressFromHostAndPortStr(
468 serverName.getHostAndPort()));
469 }
470 regionMap.put(entry.getKey(), server);
471 }
472
473 return regionMap;
474 }
475
476
477
478
479
480
481
482
483 public NavigableMap<HRegionInfo, ServerName> getRegionLocations() throws IOException {
484 return MetaScanner.allTableRegions(getConfiguration(), getTableName(), false);
485 }
486
487
488
489
490
491
492
493
494
495
496 public List<HRegionLocation> getRegionsInRange(final byte [] startKey,
497 final byte [] endKey) throws IOException {
498 final boolean endKeyIsEndOfTable = Bytes.equals(endKey,
499 HConstants.EMPTY_END_ROW);
500 if ((Bytes.compareTo(startKey, endKey) > 0) && !endKeyIsEndOfTable) {
501 throw new IllegalArgumentException(
502 "Invalid range: " + Bytes.toStringBinary(startKey) +
503 " > " + Bytes.toStringBinary(endKey));
504 }
505 final List<HRegionLocation> regionList = new ArrayList<HRegionLocation>();
506 byte [] currentKey = startKey;
507 do {
508 HRegionLocation regionLocation = getRegionLocation(currentKey, false);
509 regionList.add(regionLocation);
510 currentKey = regionLocation.getRegionInfo().getEndKey();
511 } while (!Bytes.equals(currentKey, HConstants.EMPTY_END_ROW) &&
512 (endKeyIsEndOfTable || Bytes.compareTo(currentKey, endKey) < 0));
513 return regionList;
514 }
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538 public void prewarmRegionCache(Map<HRegionInfo, HServerAddress> regionMap) {
539 this.connection.prewarmRegionCache(this.getTableName(), regionMap);
540 }
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562 public void serializeRegionInfo(DataOutput out) throws IOException {
563 Map<HRegionInfo, HServerAddress> allRegions = this.getRegionsInfo();
564
565 out.writeInt(allRegions.size());
566 for (Map.Entry<HRegionInfo, HServerAddress> es : allRegions.entrySet()) {
567 es.getKey().write(out);
568 es.getValue().write(out);
569 }
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588 public Map<HRegionInfo, HServerAddress> deserializeRegionInfo(DataInput in)
589 throws IOException {
590 final Map<HRegionInfo, HServerAddress> allRegions =
591 new TreeMap<HRegionInfo, HServerAddress>();
592
593
594 int regionsCount = in.readInt();
595 for (int i = 0; i < regionsCount; ++i) {
596 HRegionInfo hri = new HRegionInfo();
597 hri.readFields(in);
598 HServerAddress hsa = new HServerAddress();
599 hsa.readFields(in);
600 allRegions.put(hri, hsa);
601 }
602 return allRegions;
603 }
604
605
606
607
608 @Override
609 public Result getRowOrBefore(final byte[] row, final byte[] family)
610 throws IOException {
611 return new ServerCallable<Result>(connection, tableName, row, operationTimeout) {
612 public Result call() throws IOException {
613 return server.getClosestRowBefore(location.getRegionInfo().getRegionName(),
614 row, family);
615 }
616 }.withRetries();
617 }
618
619
620
621
622 @Override
623 public ResultScanner getScanner(final Scan scan) throws IOException {
624 if (scan.getCaching() <= 0) {
625 scan.setCaching(getScannerCaching());
626 }
627 return new ClientScanner(getConfiguration(), scan, getTableName(),
628 this.connection);
629 }
630
631
632
633
634 @Override
635 public ResultScanner getScanner(byte [] family) throws IOException {
636 Scan scan = new Scan();
637 scan.addFamily(family);
638 return getScanner(scan);
639 }
640
641
642
643
644 @Override
645 public ResultScanner getScanner(byte [] family, byte [] qualifier)
646 throws IOException {
647 Scan scan = new Scan();
648 scan.addColumn(family, qualifier);
649 return getScanner(scan);
650 }
651
652
653
654
655 @Override
656 public Result get(final Get get) throws IOException {
657 return new ServerCallable<Result>(connection, tableName, get.getRow(), operationTimeout) {
658 public Result call() throws IOException {
659 return server.get(location.getRegionInfo().getRegionName(), get);
660 }
661 }.withRetries();
662 }
663
664
665
666
667 @Override
668 public Result[] get(List<Get> gets) throws IOException {
669 try {
670 Object [] r1 = batch((List)gets);
671
672
673 Result [] results = new Result[r1.length];
674 int i=0;
675 for (Object o : r1) {
676
677 results[i++] = (Result) o;
678 }
679
680 return results;
681 } catch (InterruptedException e) {
682 throw new IOException(e);
683 }
684 }
685
686
687
688
689 @Override
690 public void batch(final List<?extends Row> actions, final Object[] results)
691 throws InterruptedException, IOException {
692 connection.processBatch(actions, tableName, pool, results);
693 }
694
695
696
697
698 @Override
699 public Object[] batch(final List<? extends Row> actions) throws InterruptedException, IOException {
700 Object[] results = new Object[actions.size()];
701 connection.processBatch(actions, tableName, pool, results);
702 return results;
703 }
704
705
706
707
708 @Override
709 public void delete(final Delete delete)
710 throws IOException {
711 new ServerCallable<Boolean>(connection, tableName, delete.getRow(), operationTimeout) {
712 public Boolean call() throws IOException {
713 server.delete(location.getRegionInfo().getRegionName(), delete);
714 return null;
715 }
716 }.withRetries();
717 }
718
719
720
721
722 @Override
723 public void delete(final List<Delete> deletes)
724 throws IOException {
725 Object[] results = new Object[deletes.size()];
726 try {
727 connection.processBatch((List) deletes, tableName, pool, results);
728 } catch (InterruptedException e) {
729 throw new IOException(e);
730 } finally {
731
732
733
734 for (int i = results.length - 1; i>=0; i--) {
735
736 if (results[i] instanceof Result) {
737 deletes.remove(i);
738 }
739 }
740 }
741 }
742
743
744
745
746 @Override
747 public void put(final Put put) throws IOException {
748 doPut(put);
749 if (autoFlush) {
750 flushCommits();
751 }
752 }
753
754
755
756
757 @Override
758 public void put(final List<Put> puts) throws IOException {
759 for (Put put : puts) {
760 doPut(put);
761 }
762 if (autoFlush) {
763 flushCommits();
764 }
765 }
766
767 private void doPut(Put put) throws IOException{
768 validatePut(put);
769 writeBuffer.add(put);
770 currentWriteBufferSize += put.heapSize();
771 if (currentWriteBufferSize > writeBufferSize) {
772 flushCommits();
773 }
774 }
775
776
777
778
779 @Override
780 public void mutateRow(final RowMutations rm) throws IOException {
781 new ServerCallable<Void>(connection, tableName, rm.getRow(),
782 operationTimeout) {
783 public Void call() throws IOException {
784 server.mutateRow(location.getRegionInfo().getRegionName(), rm);
785 return null;
786 }
787 }.withRetries();
788 }
789
790
791
792
793 @Override
794 public Result append(final Append append) throws IOException {
795 if (append.numFamilies() == 0) {
796 throw new IOException(
797 "Invalid arguments to append, no columns specified");
798 }
799 return new ServerCallable<Result>(connection, tableName, append.getRow(), operationTimeout) {
800 public Result call() throws IOException {
801 return server.append(
802 location.getRegionInfo().getRegionName(), append);
803 }
804 }.withRetries();
805 }
806
807
808
809
810 @Override
811 public Result increment(final Increment increment) throws IOException {
812 if (!increment.hasFamilies()) {
813 throw new IOException(
814 "Invalid arguments to increment, no columns specified");
815 }
816 return new ServerCallable<Result>(connection, tableName, increment.getRow(), operationTimeout) {
817 public Result call() throws IOException {
818 return server.increment(
819 location.getRegionInfo().getRegionName(), increment);
820 }
821 }.withRetries();
822 }
823
824
825
826
827 @Override
828 public long incrementColumnValue(final byte [] row, final byte [] family,
829 final byte [] qualifier, final long amount)
830 throws IOException {
831 return incrementColumnValue(row, family, qualifier, amount, true);
832 }
833
834
835
836
837 @Override
838 public long incrementColumnValue(final byte [] row, final byte [] family,
839 final byte [] qualifier, final long amount, final boolean writeToWAL)
840 throws IOException {
841 NullPointerException npe = null;
842 if (row == null) {
843 npe = new NullPointerException("row is null");
844 } else if (family == null) {
845 npe = new NullPointerException("column is null");
846 }
847 if (npe != null) {
848 throw new IOException(
849 "Invalid arguments to incrementColumnValue", npe);
850 }
851 return new ServerCallable<Long>(connection, tableName, row, operationTimeout) {
852 public Long call() throws IOException {
853 return server.incrementColumnValue(
854 location.getRegionInfo().getRegionName(), row, family,
855 qualifier, amount, writeToWAL);
856 }
857 }.withRetries();
858 }
859
860
861
862
863 @Override
864 public boolean checkAndPut(final byte [] row,
865 final byte [] family, final byte [] qualifier, final byte [] value,
866 final Put put)
867 throws IOException {
868 return new ServerCallable<Boolean>(connection, tableName, row, operationTimeout) {
869 public Boolean call() throws IOException {
870 return server.checkAndPut(location.getRegionInfo().getRegionName(),
871 row, family, qualifier, value, put) ? Boolean.TRUE : Boolean.FALSE;
872 }
873 }.withRetries();
874 }
875
876
877
878
879
880 @Override
881 public boolean checkAndDelete(final byte [] row,
882 final byte [] family, final byte [] qualifier, final byte [] value,
883 final Delete delete)
884 throws IOException {
885 return new ServerCallable<Boolean>(connection, tableName, row, operationTimeout) {
886 public Boolean call() throws IOException {
887 return server.checkAndDelete(
888 location.getRegionInfo().getRegionName(),
889 row, family, qualifier, value, delete)
890 ? Boolean.TRUE : Boolean.FALSE;
891 }
892 }.withRetries();
893 }
894
895
896
897
898 @Override
899 public boolean exists(final Get get) throws IOException {
900 return new ServerCallable<Boolean>(connection, tableName, get.getRow(), operationTimeout) {
901 public Boolean call() throws IOException {
902 return server.
903 exists(location.getRegionInfo().getRegionName(), get);
904 }
905 }.withRetries();
906 }
907
908
909
910
911 @Override
912 public void flushCommits() throws IOException {
913 try {
914 Object[] results = new Object[writeBuffer.size()];
915 try {
916 this.connection.processBatch(writeBuffer, tableName, pool, results);
917 } catch (InterruptedException e) {
918 throw new IOException(e);
919 } finally {
920
921
922
923
924 for (int i = results.length - 1; i>=0; i--) {
925 if (results[i] instanceof Result) {
926
927 writeBuffer.remove(i);
928 }
929 }
930 }
931 } finally {
932 if (clearBufferOnFail) {
933 writeBuffer.clear();
934 currentWriteBufferSize = 0;
935 } else {
936
937 currentWriteBufferSize = 0;
938 for (Put aPut : writeBuffer) {
939 currentWriteBufferSize += aPut.heapSize();
940 }
941 }
942 }
943 }
944
945
946
947
948 @Override
949 public void close() throws IOException {
950 if (this.closed) {
951 return;
952 }
953 flushCommits();
954 if (cleanupPoolOnClose) {
955 this.pool.shutdown();
956 }
957 if (cleanupConnectionOnClose) {
958 if (this.connection != null) {
959 this.connection.close();
960 }
961 }
962 this.closed = true;
963 }
964
965
966 private void validatePut(final Put put) throws IllegalArgumentException{
967 if (put.isEmpty()) {
968 throw new IllegalArgumentException("No columns to insert");
969 }
970 if (maxKeyValueSize > 0) {
971 for (List<KeyValue> list : put.getFamilyMap().values()) {
972 for (KeyValue kv : list) {
973 if (kv.getLength() > maxKeyValueSize) {
974 throw new IllegalArgumentException("KeyValue size too large");
975 }
976 }
977 }
978 }
979 }
980
981
982
983
984 @Override
985 public RowLock lockRow(final byte [] row)
986 throws IOException {
987 return new ServerCallable<RowLock>(connection, tableName, row, operationTimeout) {
988 public RowLock call() throws IOException {
989 long lockId =
990 server.lockRow(location.getRegionInfo().getRegionName(), row);
991 return new RowLock(row,lockId);
992 }
993 }.withRetries();
994 }
995
996
997
998
999 @Override
1000 public void unlockRow(final RowLock rl)
1001 throws IOException {
1002 new ServerCallable<Boolean>(connection, tableName, rl.getRow(), operationTimeout) {
1003 public Boolean call() throws IOException {
1004 server.unlockRow(location.getRegionInfo().getRegionName(),
1005 rl.getLockId());
1006 return null;
1007 }
1008 }.withRetries();
1009 }
1010
1011
1012
1013
1014 @Override
1015 public boolean isAutoFlush() {
1016 return autoFlush;
1017 }
1018
1019
1020
1021
1022
1023
1024
1025 public void setAutoFlush(boolean autoFlush) {
1026 setAutoFlush(autoFlush, autoFlush);
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
1057 this.autoFlush = autoFlush;
1058 this.clearBufferOnFail = autoFlush || clearBufferOnFail;
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068 public long getWriteBufferSize() {
1069 return writeBufferSize;
1070 }
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 public void setWriteBufferSize(long writeBufferSize) throws IOException {
1081 this.writeBufferSize = writeBufferSize;
1082 if(currentWriteBufferSize > writeBufferSize) {
1083 flushCommits();
1084 }
1085 }
1086
1087
1088
1089
1090
1091 public ArrayList<Put> getWriteBuffer() {
1092 return writeBuffer;
1093 }
1094
1095
1096
1097
1098
1099 ExecutorService getPool() {
1100 return this.pool;
1101 }
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 public static void setRegionCachePrefetch(final byte[] tableName,
1113 final boolean enable) throws IOException {
1114 HConnectionManager.execute(new HConnectable<Void>(HBaseConfiguration
1115 .create()) {
1116 @Override
1117 public Void connect(HConnection connection) throws IOException {
1118 connection.setRegionCachePrefetch(tableName, enable);
1119 return null;
1120 }
1121 });
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 public static void setRegionCachePrefetch(final Configuration conf,
1135 final byte[] tableName, final boolean enable) throws IOException {
1136 HConnectionManager.execute(new HConnectable<Void>(conf) {
1137 @Override
1138 public Void connect(HConnection connection) throws IOException {
1139 connection.setRegionCachePrefetch(tableName, enable);
1140 return null;
1141 }
1142 });
1143 }
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 public static boolean getRegionCachePrefetch(final Configuration conf,
1154 final byte[] tableName) throws IOException {
1155 return HConnectionManager.execute(new HConnectable<Boolean>(conf) {
1156 @Override
1157 public Boolean connect(HConnection connection) throws IOException {
1158 return connection.getRegionCachePrefetch(tableName);
1159 }
1160 });
1161 }
1162
1163
1164
1165
1166
1167
1168
1169
1170 public static boolean getRegionCachePrefetch(final byte[] tableName) throws IOException {
1171 return HConnectionManager.execute(new HConnectable<Boolean>(
1172 HBaseConfiguration.create()) {
1173 @Override
1174 public Boolean connect(HConnection connection) throws IOException {
1175 return connection.getRegionCachePrefetch(tableName);
1176 }
1177 });
1178 }
1179
1180
1181
1182
1183
1184 public void clearRegionCache() {
1185 this.connection.clearRegionCache();
1186 }
1187
1188
1189
1190
1191 @Override
1192 public <T extends CoprocessorProtocol> T coprocessorProxy(
1193 Class<T> protocol, byte[] row) {
1194 return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(),
1195 new Class[]{protocol},
1196 new ExecRPCInvoker(configuration,
1197 connection,
1198 protocol,
1199 tableName,
1200 row));
1201 }
1202
1203
1204
1205
1206 @Override
1207 public <T extends CoprocessorProtocol, R> Map<byte[],R> coprocessorExec(
1208 Class<T> protocol, byte[] startKey, byte[] endKey,
1209 Batch.Call<T,R> callable)
1210 throws IOException, Throwable {
1211
1212 final Map<byte[],R> results = Collections.synchronizedMap(new TreeMap<byte[],R>(
1213 Bytes.BYTES_COMPARATOR));
1214 coprocessorExec(protocol, startKey, endKey, callable,
1215 new Batch.Callback<R>(){
1216 public void update(byte[] region, byte[] row, R value) {
1217 results.put(region, value);
1218 }
1219 });
1220 return results;
1221 }
1222
1223
1224
1225
1226 @Override
1227 public <T extends CoprocessorProtocol, R> void coprocessorExec(
1228 Class<T> protocol, byte[] startKey, byte[] endKey,
1229 Batch.Call<T,R> callable, Batch.Callback<R> callback)
1230 throws IOException, Throwable {
1231
1232
1233 List<byte[]> keys = getStartKeysInRange(startKey, endKey);
1234 connection.processExecs(protocol, keys, tableName, pool, callable,
1235 callback);
1236 }
1237
1238 private List<byte[]> getStartKeysInRange(byte[] start, byte[] end)
1239 throws IOException {
1240 Pair<byte[][],byte[][]> startEndKeys = getStartEndKeys();
1241 byte[][] startKeys = startEndKeys.getFirst();
1242 byte[][] endKeys = startEndKeys.getSecond();
1243
1244 if (start == null) {
1245 start = HConstants.EMPTY_START_ROW;
1246 }
1247 if (end == null) {
1248 end = HConstants.EMPTY_END_ROW;
1249 }
1250
1251 List<byte[]> rangeKeys = new ArrayList<byte[]>();
1252 for (int i=0; i<startKeys.length; i++) {
1253 if (Bytes.compareTo(start, startKeys[i]) >= 0 ) {
1254 if (Bytes.equals(endKeys[i], HConstants.EMPTY_END_ROW) ||
1255 Bytes.compareTo(start, endKeys[i]) < 0) {
1256 rangeKeys.add(start);
1257 }
1258 } else if (Bytes.equals(end, HConstants.EMPTY_END_ROW) ||
1259 Bytes.compareTo(startKeys[i], end) <= 0) {
1260 rangeKeys.add(startKeys[i]);
1261 } else {
1262 break;
1263 }
1264 }
1265
1266 return rangeKeys;
1267 }
1268
1269 public void setOperationTimeout(int operationTimeout) {
1270 this.operationTimeout = operationTimeout;
1271 }
1272
1273 public int getOperationTimeout() {
1274 return operationTimeout;
1275 }
1276
1277 }