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