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 return getRegionsInRange(startKey, endKey, false);
499 }
500
501
502
503
504
505
506
507
508
509
510
511 public List<HRegionLocation> getRegionsInRange(final byte [] startKey,
512 final byte [] endKey, final boolean reload) throws IOException {
513 return getKeysAndRegionsInRange(startKey, endKey, false, reload).getSecond();
514 }
515
516
517
518
519
520
521
522
523
524
525
526
527 private Pair<List<byte[]>, List<HRegionLocation>> getKeysAndRegionsInRange(
528 final byte[] startKey, final byte[] endKey, final boolean includeEndKey)
529 throws IOException {
530 return getKeysAndRegionsInRange(startKey, endKey, includeEndKey, false);
531 }
532
533
534
535
536
537
538
539
540
541
542
543
544
545 private Pair<List<byte[]>, List<HRegionLocation>> getKeysAndRegionsInRange(
546 final byte[] startKey, final byte[] endKey, final boolean includeEndKey,
547 final boolean reload) throws IOException {
548 final boolean endKeyIsEndOfTable = Bytes.equals(endKey,HConstants.EMPTY_END_ROW);
549 if ((Bytes.compareTo(startKey, endKey) > 0) && !endKeyIsEndOfTable) {
550 throw new IllegalArgumentException(
551 "Invalid range: " + Bytes.toStringBinary(startKey) +
552 " > " + Bytes.toStringBinary(endKey));
553 }
554 List<byte[]> keysInRange = new ArrayList<byte[]>();
555 List<HRegionLocation> regionsInRange = new ArrayList<HRegionLocation>();
556 byte[] currentKey = startKey;
557 do {
558 HRegionLocation regionLocation = getRegionLocation(currentKey, reload);
559 keysInRange.add(currentKey);
560 regionsInRange.add(regionLocation);
561 currentKey = regionLocation.getRegionInfo().getEndKey();
562 } while (!Bytes.equals(currentKey, HConstants.EMPTY_END_ROW)
563 && (endKeyIsEndOfTable || Bytes.compareTo(currentKey, endKey) < 0
564 || (includeEndKey && Bytes.compareTo(currentKey, endKey) == 0)));
565 return new Pair<List<byte[]>, List<HRegionLocation>>(keysInRange,
566 regionsInRange);
567 }
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591 public void prewarmRegionCache(Map<HRegionInfo, HServerAddress> regionMap) {
592 this.connection.prewarmRegionCache(this.getTableName(), regionMap);
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615 public void serializeRegionInfo(DataOutput out) throws IOException {
616 Map<HRegionInfo, HServerAddress> allRegions = this.getRegionsInfo();
617
618 out.writeInt(allRegions.size());
619 for (Map.Entry<HRegionInfo, HServerAddress> es : allRegions.entrySet()) {
620 es.getKey().write(out);
621 es.getValue().write(out);
622 }
623 }
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641 public Map<HRegionInfo, HServerAddress> deserializeRegionInfo(DataInput in)
642 throws IOException {
643 final Map<HRegionInfo, HServerAddress> allRegions =
644 new TreeMap<HRegionInfo, HServerAddress>();
645
646
647 int regionsCount = in.readInt();
648 for (int i = 0; i < regionsCount; ++i) {
649 HRegionInfo hri = new HRegionInfo();
650 hri.readFields(in);
651 HServerAddress hsa = new HServerAddress();
652 hsa.readFields(in);
653 allRegions.put(hri, hsa);
654 }
655 return allRegions;
656 }
657
658
659
660
661 @Override
662 public Result getRowOrBefore(final byte[] row, final byte[] family)
663 throws IOException {
664 return new ServerCallable<Result>(connection, tableName, row, operationTimeout) {
665 public Result call() throws IOException {
666 return server.getClosestRowBefore(location.getRegionInfo().getRegionName(),
667 row, family);
668 }
669 }.withRetries();
670 }
671
672
673
674
675 @Override
676 public ResultScanner getScanner(final Scan scan) throws IOException {
677 if (scan.getCaching() <= 0) {
678 scan.setCaching(getScannerCaching());
679 }
680 return new ClientScanner(getConfiguration(), scan, getTableName(),
681 this.connection);
682 }
683
684
685
686
687 @Override
688 public ResultScanner getScanner(byte [] family) throws IOException {
689 Scan scan = new Scan();
690 scan.addFamily(family);
691 return getScanner(scan);
692 }
693
694
695
696
697 @Override
698 public ResultScanner getScanner(byte [] family, byte [] qualifier)
699 throws IOException {
700 Scan scan = new Scan();
701 scan.addColumn(family, qualifier);
702 return getScanner(scan);
703 }
704
705
706
707
708 @Override
709 public Result get(final Get get) throws IOException {
710 return new ServerCallable<Result>(connection, tableName, get.getRow(), operationTimeout) {
711 public Result call() throws IOException {
712 return server.get(location.getRegionInfo().getRegionName(), get);
713 }
714 }.withRetries();
715 }
716
717
718
719
720 @Override
721 public Result[] get(List<Get> gets) throws IOException {
722 if (gets.size() == 1) {
723 return new Result[]{get(gets.get(0))};
724 }
725 try {
726 Object [] r1 = batch((List)gets);
727
728
729 Result [] results = new Result[r1.length];
730 int i=0;
731 for (Object o : r1) {
732
733 results[i++] = (Result) o;
734 }
735
736 return results;
737 } catch (InterruptedException e) {
738 throw new IOException(e);
739 }
740 }
741
742
743
744
745 @Override
746 public void batch(final List<?extends Row> actions, final Object[] results)
747 throws InterruptedException, IOException {
748 connection.processBatch(actions, tableName, pool, results);
749 }
750
751
752
753
754 @Override
755 public Object[] batch(final List<? extends Row> actions) throws InterruptedException, IOException {
756 Object[] results = new Object[actions.size()];
757 connection.processBatch(actions, tableName, pool, results);
758 return results;
759 }
760
761
762
763
764 @Override
765 public void delete(final Delete delete)
766 throws IOException {
767 new ServerCallable<Boolean>(connection, tableName, delete.getRow(), operationTimeout) {
768 public Boolean call() throws IOException {
769 server.delete(location.getRegionInfo().getRegionName(), delete);
770 return null;
771 }
772 }.withRetries();
773 }
774
775
776
777
778 @Override
779 public void delete(final List<Delete> deletes)
780 throws IOException {
781 Object[] results = new Object[deletes.size()];
782 try {
783 connection.processBatch((List) deletes, tableName, pool, results);
784 } catch (InterruptedException e) {
785 throw new IOException(e);
786 } finally {
787
788
789
790 for (int i = results.length - 1; i>=0; i--) {
791
792 if (results[i] instanceof Result) {
793 deletes.remove(i);
794 }
795 }
796 }
797 }
798
799
800
801
802 @Override
803 public void put(final Put put) throws IOException {
804 doPut(put);
805 if (autoFlush) {
806 flushCommits();
807 }
808 }
809
810
811
812
813 @Override
814 public void put(final List<Put> puts) throws IOException {
815 for (Put put : puts) {
816 doPut(put);
817 }
818 if (autoFlush) {
819 flushCommits();
820 }
821 }
822
823 private void doPut(Put put) throws IOException{
824 validatePut(put);
825 writeBuffer.add(put);
826 currentWriteBufferSize += put.heapSize();
827 if (currentWriteBufferSize > writeBufferSize) {
828 flushCommits();
829 }
830 }
831
832
833
834
835 @Override
836 public void mutateRow(final RowMutations rm) throws IOException {
837 new ServerCallable<Void>(connection, tableName, rm.getRow(),
838 operationTimeout) {
839 public Void call() throws IOException {
840 server.mutateRow(location.getRegionInfo().getRegionName(), rm);
841 return null;
842 }
843 }.withRetries();
844 }
845
846
847
848
849 @Override
850 public Result append(final Append append) throws IOException {
851 if (append.numFamilies() == 0) {
852 throw new IOException(
853 "Invalid arguments to append, no columns specified");
854 }
855 return new ServerCallable<Result>(connection, tableName, append.getRow(), operationTimeout) {
856 public Result call() throws IOException {
857 return server.append(
858 location.getRegionInfo().getRegionName(), append);
859 }
860 }.withRetries();
861 }
862
863
864
865
866 @Override
867 public Result increment(final Increment increment) throws IOException {
868 if (!increment.hasFamilies()) {
869 throw new IOException(
870 "Invalid arguments to increment, no columns specified");
871 }
872 return new ServerCallable<Result>(connection, tableName, increment.getRow(), operationTimeout) {
873 public Result call() throws IOException {
874 return server.increment(
875 location.getRegionInfo().getRegionName(), increment);
876 }
877 }.withRetries();
878 }
879
880
881
882
883 @Override
884 public long incrementColumnValue(final byte [] row, final byte [] family,
885 final byte [] qualifier, final long amount)
886 throws IOException {
887 return incrementColumnValue(row, family, qualifier, amount, true);
888 }
889
890
891
892
893 @Override
894 public long incrementColumnValue(final byte [] row, final byte [] family,
895 final byte [] qualifier, final long amount, final boolean writeToWAL)
896 throws IOException {
897 NullPointerException npe = null;
898 if (row == null) {
899 npe = new NullPointerException("row is null");
900 } else if (family == null) {
901 npe = new NullPointerException("column is null");
902 }
903 if (npe != null) {
904 throw new IOException(
905 "Invalid arguments to incrementColumnValue", npe);
906 }
907 return new ServerCallable<Long>(connection, tableName, row, operationTimeout) {
908 public Long call() throws IOException {
909 return server.incrementColumnValue(
910 location.getRegionInfo().getRegionName(), row, family,
911 qualifier, amount, writeToWAL);
912 }
913 }.withRetries();
914 }
915
916
917
918
919 @Override
920 public boolean checkAndPut(final byte [] row,
921 final byte [] family, final byte [] qualifier, final byte [] value,
922 final Put put)
923 throws IOException {
924 return new ServerCallable<Boolean>(connection, tableName, row, operationTimeout) {
925 public Boolean call() throws IOException {
926 return server.checkAndPut(location.getRegionInfo().getRegionName(),
927 row, family, qualifier, value, put) ? Boolean.TRUE : Boolean.FALSE;
928 }
929 }.withRetries();
930 }
931
932
933
934
935
936 @Override
937 public boolean checkAndDelete(final byte [] row,
938 final byte [] family, final byte [] qualifier, final byte [] value,
939 final Delete delete)
940 throws IOException {
941 return new ServerCallable<Boolean>(connection, tableName, row, operationTimeout) {
942 public Boolean call() throws IOException {
943 return server.checkAndDelete(
944 location.getRegionInfo().getRegionName(),
945 row, family, qualifier, value, delete)
946 ? Boolean.TRUE : Boolean.FALSE;
947 }
948 }.withRetries();
949 }
950
951
952
953
954 @Override
955 public boolean exists(final Get get) throws IOException {
956 return new ServerCallable<Boolean>(connection, tableName, get.getRow(), operationTimeout) {
957 public Boolean call() throws IOException {
958 return server.
959 exists(location.getRegionInfo().getRegionName(), get);
960 }
961 }.withRetries();
962 }
963
964
965
966
967 @Override
968 public void flushCommits() throws IOException {
969 try {
970 Object[] results = new Object[writeBuffer.size()];
971 try {
972 this.connection.processBatch(writeBuffer, tableName, pool, results);
973 } catch (InterruptedException e) {
974 throw new IOException(e);
975 } finally {
976
977
978
979
980 for (int i = results.length - 1; i>=0; i--) {
981 if (results[i] instanceof Result) {
982
983 writeBuffer.remove(i);
984 }
985 }
986 }
987 } finally {
988 if (clearBufferOnFail) {
989 writeBuffer.clear();
990 currentWriteBufferSize = 0;
991 } else {
992
993 currentWriteBufferSize = 0;
994 for (Put aPut : writeBuffer) {
995 currentWriteBufferSize += aPut.heapSize();
996 }
997 }
998 }
999 }
1000
1001
1002
1003
1004 @Override
1005 public void close() throws IOException {
1006 if (this.closed) {
1007 return;
1008 }
1009 flushCommits();
1010 if (cleanupPoolOnClose) {
1011 this.pool.shutdown();
1012 }
1013 if (cleanupConnectionOnClose) {
1014 if (this.connection != null) {
1015 this.connection.close();
1016 }
1017 }
1018 this.closed = true;
1019 }
1020
1021
1022 private void validatePut(final Put put) throws IllegalArgumentException{
1023 if (put.isEmpty()) {
1024 throw new IllegalArgumentException("No columns to insert");
1025 }
1026 if (maxKeyValueSize > 0) {
1027 for (List<KeyValue> list : put.getFamilyMap().values()) {
1028 for (KeyValue kv : list) {
1029 if (kv.getLength() > maxKeyValueSize) {
1030 throw new IllegalArgumentException("KeyValue size too large");
1031 }
1032 }
1033 }
1034 }
1035 }
1036
1037
1038
1039
1040 @Override
1041 public RowLock lockRow(final byte [] row)
1042 throws IOException {
1043 return new ServerCallable<RowLock>(connection, tableName, row, operationTimeout) {
1044 public RowLock call() throws IOException {
1045 long lockId =
1046 server.lockRow(location.getRegionInfo().getRegionName(), row);
1047 return new RowLock(row,lockId);
1048 }
1049 }.withRetries();
1050 }
1051
1052
1053
1054
1055 @Override
1056 public void unlockRow(final RowLock rl)
1057 throws IOException {
1058 new ServerCallable<Boolean>(connection, tableName, rl.getRow(), operationTimeout) {
1059 public Boolean call() throws IOException {
1060 server.unlockRow(location.getRegionInfo().getRegionName(),
1061 rl.getLockId());
1062 return null;
1063 }
1064 }.withRetries();
1065 }
1066
1067
1068
1069
1070 @Override
1071 public boolean isAutoFlush() {
1072 return autoFlush;
1073 }
1074
1075
1076
1077
1078
1079
1080
1081 public void setAutoFlush(boolean autoFlush) {
1082 setAutoFlush(autoFlush, autoFlush);
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112 public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
1113 this.autoFlush = autoFlush;
1114 this.clearBufferOnFail = autoFlush || clearBufferOnFail;
1115 }
1116
1117
1118
1119
1120
1121
1122
1123
1124 public long getWriteBufferSize() {
1125 return writeBufferSize;
1126 }
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136 public void setWriteBufferSize(long writeBufferSize) throws IOException {
1137 this.writeBufferSize = writeBufferSize;
1138 if(currentWriteBufferSize > writeBufferSize) {
1139 flushCommits();
1140 }
1141 }
1142
1143
1144
1145
1146
1147 public ArrayList<Put> getWriteBuffer() {
1148 return writeBuffer;
1149 }
1150
1151
1152
1153
1154
1155 ExecutorService getPool() {
1156 return this.pool;
1157 }
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 public static void setRegionCachePrefetch(final byte[] tableName,
1169 final boolean enable) throws IOException {
1170 HConnectionManager.execute(new HConnectable<Void>(HBaseConfiguration
1171 .create()) {
1172 @Override
1173 public Void connect(HConnection connection) throws IOException {
1174 connection.setRegionCachePrefetch(tableName, enable);
1175 return null;
1176 }
1177 });
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 public static void setRegionCachePrefetch(final Configuration conf,
1191 final byte[] tableName, final boolean enable) throws IOException {
1192 HConnectionManager.execute(new HConnectable<Void>(conf) {
1193 @Override
1194 public Void connect(HConnection connection) throws IOException {
1195 connection.setRegionCachePrefetch(tableName, enable);
1196 return null;
1197 }
1198 });
1199 }
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 public static boolean getRegionCachePrefetch(final Configuration conf,
1210 final byte[] tableName) throws IOException {
1211 return HConnectionManager.execute(new HConnectable<Boolean>(conf) {
1212 @Override
1213 public Boolean connect(HConnection connection) throws IOException {
1214 return connection.getRegionCachePrefetch(tableName);
1215 }
1216 });
1217 }
1218
1219
1220
1221
1222
1223
1224
1225
1226 public static boolean getRegionCachePrefetch(final byte[] tableName) throws IOException {
1227 return HConnectionManager.execute(new HConnectable<Boolean>(
1228 HBaseConfiguration.create()) {
1229 @Override
1230 public Boolean connect(HConnection connection) throws IOException {
1231 return connection.getRegionCachePrefetch(tableName);
1232 }
1233 });
1234 }
1235
1236
1237
1238
1239
1240 public void clearRegionCache() {
1241 this.connection.clearRegionCache();
1242 }
1243
1244
1245
1246
1247 @Override
1248 public <T extends CoprocessorProtocol> T coprocessorProxy(
1249 Class<T> protocol, byte[] row) {
1250 return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(),
1251 new Class[]{protocol},
1252 new ExecRPCInvoker(configuration,
1253 connection,
1254 protocol,
1255 tableName,
1256 row));
1257 }
1258
1259
1260
1261
1262 @Override
1263 public <T extends CoprocessorProtocol, R> Map<byte[],R> coprocessorExec(
1264 Class<T> protocol, byte[] startKey, byte[] endKey,
1265 Batch.Call<T,R> callable)
1266 throws IOException, Throwable {
1267
1268 final Map<byte[],R> results = Collections.synchronizedMap(new TreeMap<byte[],R>(
1269 Bytes.BYTES_COMPARATOR));
1270 coprocessorExec(protocol, startKey, endKey, callable,
1271 new Batch.Callback<R>(){
1272 public void update(byte[] region, byte[] row, R value) {
1273 results.put(region, value);
1274 }
1275 });
1276 return results;
1277 }
1278
1279
1280
1281
1282 @Override
1283 public <T extends CoprocessorProtocol, R> void coprocessorExec(
1284 Class<T> protocol, byte[] startKey, byte[] endKey,
1285 Batch.Call<T,R> callable, Batch.Callback<R> callback)
1286 throws IOException, Throwable {
1287
1288
1289 List<byte[]> keys = getStartKeysInRange(startKey, endKey);
1290 connection.processExecs(protocol, keys, tableName, pool, callable,
1291 callback);
1292 }
1293
1294 private List<byte[]> getStartKeysInRange(byte[] start, byte[] end)
1295 throws IOException {
1296 if (start == null) {
1297 start = HConstants.EMPTY_START_ROW;
1298 }
1299 if (end == null) {
1300 end = HConstants.EMPTY_END_ROW;
1301 }
1302 return getKeysAndRegionsInRange(start, end, true).getFirst();
1303 }
1304
1305 public void setOperationTimeout(int operationTimeout) {
1306 this.operationTimeout = operationTimeout;
1307 }
1308
1309 public int getOperationTimeout() {
1310 return operationTimeout;
1311 }
1312
1313 }