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