1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import java.io.Closeable;
22 import java.io.IOException;
23 import java.io.InterruptedIOException;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.NavigableMap;
30 import java.util.TreeMap;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Future;
35 import java.util.concurrent.SynchronousQueue;
36 import java.util.concurrent.ThreadPoolExecutor;
37 import java.util.concurrent.TimeUnit;
38
39 import com.google.protobuf.InvalidProtocolBufferException;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.apache.hadoop.hbase.classification.InterfaceAudience;
44 import org.apache.hadoop.hbase.classification.InterfaceStability;
45 import org.apache.hadoop.conf.Configuration;
46 import org.apache.hadoop.hbase.Cell;
47 import org.apache.hadoop.hbase.DoNotRetryIOException;
48 import org.apache.hadoop.hbase.HBaseConfiguration;
49 import org.apache.hadoop.hbase.HConstants;
50 import org.apache.hadoop.hbase.HRegionInfo;
51 import org.apache.hadoop.hbase.HRegionLocation;
52 import org.apache.hadoop.hbase.HTableDescriptor;
53 import org.apache.hadoop.hbase.KeyValue;
54 import org.apache.hadoop.hbase.KeyValueUtil;
55 import org.apache.hadoop.hbase.ServerName;
56 import org.apache.hadoop.hbase.TableName;
57 import org.apache.hadoop.hbase.client.coprocessor.Batch;
58 import org.apache.hadoop.hbase.client.coprocessor.Batch.Callback;
59 import org.apache.hadoop.hbase.filter.BinaryComparator;
60 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
61 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
62 import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
63 import org.apache.hadoop.hbase.ipc.RegionCoprocessorRpcChannel;
64 import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
65 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
66 import org.apache.hadoop.hbase.protobuf.RequestConverter;
67 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
68 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MultiRequest;
69 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
70 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateResponse;
71 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
72 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.CompareType;
73 import org.apache.hadoop.hbase.util.Bytes;
74 import org.apache.hadoop.hbase.util.Pair;
75 import org.apache.hadoop.hbase.util.Threads;
76
77 import com.google.protobuf.Descriptors;
78 import com.google.protobuf.Message;
79 import com.google.protobuf.Service;
80 import com.google.protobuf.ServiceException;
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 @InterfaceAudience.Public
124 @InterfaceStability.Stable
125 public class HTable implements HTableInterface {
126 private static final Log LOG = LogFactory.getLog(HTable.class);
127 protected HConnection connection;
128 private final TableName tableName;
129 private volatile Configuration configuration;
130 private TableConfiguration tableConfiguration;
131 protected List<Row> writeAsyncBuffer = new LinkedList<Row>();
132 private long writeBufferSize;
133 private boolean clearBufferOnFail;
134 private boolean autoFlush;
135 protected long currentWriteBufferSize;
136 protected int scannerCaching;
137 private ExecutorService pool;
138 private boolean closed;
139 private int operationTimeout;
140 private final boolean cleanupPoolOnClose;
141 private final boolean cleanupConnectionOnClose;
142
143
144 protected AsyncProcess<Object> ap;
145 private RpcRetryingCallerFactory rpcCallerFactory;
146 private RpcControllerFactory rpcControllerFactory;
147
148
149
150
151
152
153
154
155
156
157
158 public HTable(Configuration conf, final String tableName)
159 throws IOException {
160 this(conf, TableName.valueOf(tableName));
161 }
162
163
164
165
166
167
168
169
170
171
172
173 public HTable(Configuration conf, final byte[] tableName)
174 throws IOException {
175 this(conf, TableName.valueOf(tableName));
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190 public HTable(Configuration conf, final TableName tableName)
191 throws IOException {
192 this.tableName = tableName;
193 this.cleanupPoolOnClose = this.cleanupConnectionOnClose = true;
194 if (conf == null) {
195 this.connection = null;
196 return;
197 }
198 this.connection = HConnectionManager.getConnection(conf);
199 this.configuration = conf;
200
201 this.pool = getDefaultExecutor(conf);
202 this.finishSetup();
203 }
204
205
206
207
208
209
210
211
212
213 public HTable(TableName tableName, HConnection connection) throws IOException {
214 this.tableName = tableName;
215 this.cleanupPoolOnClose = true;
216 this.cleanupConnectionOnClose = false;
217 this.connection = connection;
218 this.configuration = connection.getConfiguration();
219
220 this.pool = getDefaultExecutor(this.configuration);
221 this.finishSetup();
222 }
223
224 public static ThreadPoolExecutor getDefaultExecutor(Configuration conf) {
225 int maxThreads = conf.getInt("hbase.htable.threads.max", Integer.MAX_VALUE);
226 if (maxThreads == 0) {
227 maxThreads = 1;
228 }
229 long keepAliveTime = conf.getLong("hbase.htable.threads.keepalivetime", 60);
230
231
232
233
234
235 ThreadPoolExecutor pool = new ThreadPoolExecutor(1, maxThreads, keepAliveTime, TimeUnit.SECONDS,
236 new SynchronousQueue<Runnable>(), Threads.newDaemonThreadFactory("htable"));
237 ((ThreadPoolExecutor) pool).allowCoreThreadTimeOut(true);
238 return pool;
239 }
240
241
242
243
244
245
246
247
248
249
250
251
252
253 public HTable(Configuration conf, final byte[] tableName, final ExecutorService pool)
254 throws IOException {
255 this(conf, TableName.valueOf(tableName), pool);
256 }
257
258
259
260
261
262
263
264
265
266
267
268
269
270 public HTable(Configuration conf, final TableName tableName, final ExecutorService pool)
271 throws IOException {
272 this.connection = HConnectionManager.getConnection(conf);
273 this.configuration = conf;
274 this.pool = pool;
275 this.tableName = tableName;
276 this.cleanupPoolOnClose = false;
277 this.cleanupConnectionOnClose = true;
278
279 this.finishSetup();
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293 public HTable(final byte[] tableName, final HConnection connection,
294 final ExecutorService pool) throws IOException {
295 this(TableName.valueOf(tableName), connection, pool);
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309 public HTable(TableName tableName, final HConnection connection,
310 final ExecutorService pool) throws IOException {
311 this(tableName, connection, null, null, null, pool);
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 public HTable(TableName tableName, final HConnection connection,
329 final TableConfiguration tableConfig,
330 final RpcRetryingCallerFactory rpcCallerFactory,
331 final RpcControllerFactory rpcControllerFactory,
332 final ExecutorService pool) throws IOException {
333 if (connection == null || connection.isClosed()) {
334 throw new IllegalArgumentException("Connection is null or closed.");
335 }
336 this.tableName = tableName;
337 this.connection = connection;
338 this.configuration = connection.getConfiguration();
339 this.tableConfiguration = tableConfig;
340 this.cleanupPoolOnClose = this.cleanupConnectionOnClose = false;
341 this.pool = pool;
342
343 this.rpcCallerFactory = rpcCallerFactory;
344 this.rpcControllerFactory = rpcControllerFactory;
345
346 this.finishSetup();
347 }
348
349
350
351
352 protected HTable(){
353 tableName = null;
354 tableConfiguration = new TableConfiguration();
355 cleanupPoolOnClose = false;
356 cleanupConnectionOnClose = false;
357 }
358
359
360
361
362 public static int getMaxKeyValueSize(Configuration conf) {
363 return conf.getInt("hbase.client.keyvalue.maxsize", -1);
364 }
365
366
367
368
369 private void finishSetup() throws IOException {
370 if (tableConfiguration == null) {
371 tableConfiguration = new TableConfiguration(configuration);
372 }
373 this.operationTimeout = tableName.isSystemTable() ?
374 tableConfiguration.getMetaOperationTimeout() : tableConfiguration.getOperationTimeout();
375 this.writeBufferSize = tableConfiguration.getWriteBufferSize();
376 this.clearBufferOnFail = true;
377 this.autoFlush = true;
378 this.currentWriteBufferSize = 0;
379 this.scannerCaching = tableConfiguration.getScannerCaching();
380
381 if (this.rpcCallerFactory == null) {
382 this.rpcCallerFactory = RpcRetryingCallerFactory.instantiate(configuration,
383 this.connection.getStatisticsTracker());
384 }
385 if (this.rpcControllerFactory == null) {
386 this.rpcControllerFactory = RpcControllerFactory.instantiate(configuration);
387 }
388
389 ap = new AsyncProcess<Object>(connection, tableName, pool, null, configuration,
390 rpcCallerFactory, rpcControllerFactory);
391
392 this.closed = false;
393 }
394
395
396
397
398 @Override
399 public Configuration getConfiguration() {
400 return configuration;
401 }
402
403
404
405
406
407
408
409
410
411
412 @Deprecated
413 public static boolean isTableEnabled(String tableName) throws IOException {
414 return isTableEnabled(TableName.valueOf(tableName));
415 }
416
417
418
419
420
421
422
423
424
425
426 @Deprecated
427 public static boolean isTableEnabled(byte[] tableName) throws IOException {
428 return isTableEnabled(TableName.valueOf(tableName));
429 }
430
431
432
433
434
435
436
437
438
439
440 @Deprecated
441 public static boolean isTableEnabled(TableName tableName) throws IOException {
442 return isTableEnabled(HBaseConfiguration.create(), tableName);
443 }
444
445
446
447
448
449
450
451
452
453 @Deprecated
454 public static boolean isTableEnabled(Configuration conf, String tableName)
455 throws IOException {
456 return isTableEnabled(conf, TableName.valueOf(tableName));
457 }
458
459
460
461
462
463
464
465
466
467 @Deprecated
468 public static boolean isTableEnabled(Configuration conf, byte[] tableName)
469 throws IOException {
470 return isTableEnabled(conf, TableName.valueOf(tableName));
471 }
472
473
474
475
476
477
478
479
480
481 @Deprecated
482 public static boolean isTableEnabled(Configuration conf,
483 final TableName tableName) throws IOException {
484 return HConnectionManager.execute(new HConnectable<Boolean>(conf) {
485 @Override
486 public Boolean connect(HConnection connection) throws IOException {
487 return connection.isTableEnabled(tableName);
488 }
489 });
490 }
491
492
493
494
495
496
497
498 public HRegionLocation getRegionLocation(final String row)
499 throws IOException {
500 return connection.getRegionLocation(tableName, Bytes.toBytes(row), false);
501 }
502
503
504
505
506
507
508
509 public HRegionLocation getRegionLocation(final byte [] row)
510 throws IOException {
511 return connection.getRegionLocation(tableName, row, false);
512 }
513
514
515
516
517
518
519
520
521 public HRegionLocation getRegionLocation(final byte [] row, boolean reload)
522 throws IOException {
523 return connection.getRegionLocation(tableName, row, reload);
524 }
525
526
527
528
529 @Override
530 public byte [] getTableName() {
531 return this.tableName.getName();
532 }
533
534 @Override
535 public TableName getName() {
536 return tableName;
537 }
538
539
540
541
542
543
544
545
546 @Deprecated
547 public HConnection getConnection() {
548 return this.connection;
549 }
550
551
552
553
554
555
556
557 @Deprecated
558 public int getScannerCaching() {
559 return scannerCaching;
560 }
561
562
563
564
565
566 @Deprecated
567 public List<Row> getWriteBuffer() {
568 return writeAsyncBuffer;
569 }
570
571
572
573
574
575
576
577
578
579
580
581
582 @Deprecated
583 public void setScannerCaching(int scannerCaching) {
584 this.scannerCaching = scannerCaching;
585 }
586
587
588
589
590 @Override
591 public HTableDescriptor getTableDescriptor() throws IOException {
592 return new UnmodifyableHTableDescriptor(
593 this.connection.getHTableDescriptor(this.tableName));
594 }
595
596
597
598
599
600
601
602
603 public byte [][] getStartKeys() throws IOException {
604 return getStartEndKeys().getFirst();
605 }
606
607
608
609
610
611
612
613
614 public byte[][] getEndKeys() throws IOException {
615 return getStartEndKeys().getSecond();
616 }
617
618
619
620
621
622
623
624
625
626 public Pair<byte[][],byte[][]> getStartEndKeys() throws IOException {
627 NavigableMap<HRegionInfo, ServerName> regions = getRegionLocations();
628 final List<byte[]> startKeyList = new ArrayList<byte[]>(regions.size());
629 final List<byte[]> endKeyList = new ArrayList<byte[]>(regions.size());
630
631 for (HRegionInfo region : regions.keySet()) {
632 startKeyList.add(region.getStartKey());
633 endKeyList.add(region.getEndKey());
634 }
635
636 return new Pair<byte [][], byte [][]>(
637 startKeyList.toArray(new byte[startKeyList.size()][]),
638 endKeyList.toArray(new byte[endKeyList.size()][]));
639 }
640
641
642
643
644
645
646
647
648 public NavigableMap<HRegionInfo, ServerName> getRegionLocations() throws IOException {
649
650 return MetaScanner.allTableRegions(getConfiguration(), this.connection, getName(), false);
651 }
652
653
654
655
656
657
658
659
660
661
662 public List<HRegionLocation> getRegionsInRange(final byte [] startKey,
663 final byte [] endKey) throws IOException {
664 return getRegionsInRange(startKey, endKey, false);
665 }
666
667
668
669
670
671
672
673
674
675
676
677 public List<HRegionLocation> getRegionsInRange(final byte [] startKey,
678 final byte [] endKey, final boolean reload) throws IOException {
679 return getKeysAndRegionsInRange(startKey, endKey, false, reload).getSecond();
680 }
681
682
683
684
685
686
687
688
689
690
691
692
693 private Pair<List<byte[]>, List<HRegionLocation>> getKeysAndRegionsInRange(
694 final byte[] startKey, final byte[] endKey, final boolean includeEndKey)
695 throws IOException {
696 return getKeysAndRegionsInRange(startKey, endKey, includeEndKey, false);
697 }
698
699
700
701
702
703
704
705
706
707
708
709
710
711 private Pair<List<byte[]>, List<HRegionLocation>> getKeysAndRegionsInRange(
712 final byte[] startKey, final byte[] endKey, final boolean includeEndKey,
713 final boolean reload) throws IOException {
714 final boolean endKeyIsEndOfTable = Bytes.equals(endKey,HConstants.EMPTY_END_ROW);
715 if ((Bytes.compareTo(startKey, endKey) > 0) && !endKeyIsEndOfTable) {
716 throw new IllegalArgumentException(
717 "Invalid range: " + Bytes.toStringBinary(startKey) +
718 " > " + Bytes.toStringBinary(endKey));
719 }
720 List<byte[]> keysInRange = new ArrayList<byte[]>();
721 List<HRegionLocation> regionsInRange = new ArrayList<HRegionLocation>();
722 byte[] currentKey = startKey;
723 do {
724 HRegionLocation regionLocation = getRegionLocation(currentKey, reload);
725 keysInRange.add(currentKey);
726 regionsInRange.add(regionLocation);
727 currentKey = regionLocation.getRegionInfo().getEndKey();
728 } while (!Bytes.equals(currentKey, HConstants.EMPTY_END_ROW)
729 && (endKeyIsEndOfTable || Bytes.compareTo(currentKey, endKey) < 0
730 || (includeEndKey && Bytes.compareTo(currentKey, endKey) == 0)));
731 return new Pair<List<byte[]>, List<HRegionLocation>>(keysInRange,
732 regionsInRange);
733 }
734
735
736
737
738 @Override
739 public Result getRowOrBefore(final byte[] row, final byte[] family)
740 throws IOException {
741 RegionServerCallable<Result> callable = new RegionServerCallable<Result>(this.connection,
742 tableName, row) {
743 public Result call() throws IOException {
744 return ProtobufUtil.getRowOrBefore(getStub(), getLocation().getRegionInfo()
745 .getRegionName(), row, family, rpcControllerFactory.newController());
746 }
747 };
748 return rpcCallerFactory.<Result> newCaller().callWithRetries(callable, this.operationTimeout);
749 }
750
751
752
753
754 @Override
755 public ResultScanner getScanner(final Scan scan) throws IOException {
756 if (scan.getBatch() > 0 && scan.isSmall()) {
757 throw new IllegalArgumentException("Small scan should not be used with batching");
758 }
759 if (scan.getCaching() <= 0) {
760 scan.setCaching(getScannerCaching());
761 }
762
763 if (scan.isReversed()) {
764 if (scan.isSmall()) {
765 return new ClientSmallReversedScanner(getConfiguration(), scan, getName(),
766 this.connection);
767 } else {
768 return new ReversedClientScanner(getConfiguration(), scan, getName(), this.connection);
769 }
770 }
771
772 if (scan.isSmall()) {
773 return new ClientSmallScanner(getConfiguration(), scan, getName(), this.connection);
774 } else {
775 return new ClientScanner(getConfiguration(), scan, getName(), this.connection);
776 }
777 }
778
779
780
781
782 @Override
783 public ResultScanner getScanner(byte [] family) throws IOException {
784 Scan scan = new Scan();
785 scan.addFamily(family);
786 return getScanner(scan);
787 }
788
789
790
791
792 @Override
793 public ResultScanner getScanner(byte [] family, byte [] qualifier)
794 throws IOException {
795 Scan scan = new Scan();
796 scan.addColumn(family, qualifier);
797 return getScanner(scan);
798 }
799
800
801
802
803 @Override
804 public Result get(final Get get) throws IOException {
805
806
807
808 final PayloadCarryingRpcController controller = rpcControllerFactory.newController();
809 controller.setPriority(tableName);
810 RegionServerCallable<Result> callable =
811 new RegionServerCallable<Result>(this.connection, getName(), get.getRow()) {
812 public Result call() throws IOException {
813 return ProtobufUtil.get(getStub(), getLocation().getRegionInfo().getRegionName(), get,
814 controller);
815 }
816 };
817 return rpcCallerFactory.<Result> newCaller().callWithRetries(callable, this.operationTimeout);
818 }
819
820
821
822
823 @Override
824 public Result[] get(List<Get> gets) throws IOException {
825 if (gets.size() == 1) {
826 return new Result[]{get(gets.get(0))};
827 }
828 try {
829 Object [] r1 = batch((List)gets);
830
831
832 Result [] results = new Result[r1.length];
833 int i=0;
834 for (Object o : r1) {
835
836 results[i++] = (Result) o;
837 }
838
839 return results;
840 } catch (InterruptedException e) {
841 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
842 }
843 }
844
845
846
847
848 @Override
849 public void batch(final List<?extends Row> actions, final Object[] results)
850 throws InterruptedException, IOException {
851 batchCallback(actions, results, null);
852 }
853
854
855
856
857
858
859 @Override
860 public Object[] batch(final List<? extends Row> actions)
861 throws InterruptedException, IOException {
862 return batchCallback(actions, null);
863 }
864
865
866
867
868 @Override
869 public <R> void batchCallback(
870 final List<? extends Row> actions, final Object[] results, final Batch.Callback<R> callback)
871 throws IOException, InterruptedException {
872 connection.processBatchCallback(actions, tableName, pool, results, callback);
873 }
874
875
876
877
878
879
880
881
882 @Override
883 public <R> Object[] batchCallback(
884 final List<? extends Row> actions, final Batch.Callback<R> callback) throws IOException,
885 InterruptedException {
886 Object[] results = new Object[actions.size()];
887 batchCallback(actions, results, callback);
888 return results;
889 }
890
891
892
893
894 @Override
895 public void delete(final Delete delete)
896 throws IOException {
897 RegionServerCallable<Boolean> callable = new RegionServerCallable<Boolean>(connection,
898 tableName, delete.getRow()) {
899 public Boolean call() throws IOException {
900 try {
901 MutateRequest request = RequestConverter.buildMutateRequest(
902 getLocation().getRegionInfo().getRegionName(), delete);
903 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
904 controller.setPriority(tableName);
905 MutateResponse response = getStub().mutate(controller, request);
906 return Boolean.valueOf(response.getProcessed());
907 } catch (ServiceException se) {
908 throw ProtobufUtil.getRemoteException(se);
909 }
910 }
911 };
912 rpcCallerFactory.<Boolean> newCaller().callWithRetries(callable, this.operationTimeout);
913 }
914
915
916
917
918 @Override
919 public void delete(final List<Delete> deletes)
920 throws IOException {
921 Object[] results = new Object[deletes.size()];
922 try {
923 batch(deletes, results);
924 } catch (InterruptedException e) {
925 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
926 } finally {
927
928
929
930 for (int i = results.length - 1; i>=0; i--) {
931
932 if (results[i] instanceof Result) {
933 deletes.remove(i);
934 }
935 }
936 }
937 }
938
939
940
941
942 @Override
943 public void put(final Put put)
944 throws InterruptedIOException, RetriesExhaustedWithDetailsException {
945 doPut(put);
946 if (autoFlush) {
947 flushCommits();
948 }
949 }
950
951
952
953
954 @Override
955 public void put(final List<Put> puts)
956 throws InterruptedIOException, RetriesExhaustedWithDetailsException {
957 for (Put put : puts) {
958 doPut(put);
959 }
960 if (autoFlush) {
961 flushCommits();
962 }
963 }
964
965
966
967
968
969
970
971
972 private void doPut(Put put) throws InterruptedIOException, RetriesExhaustedWithDetailsException {
973 if (ap.hasError()){
974 writeAsyncBuffer.add(put);
975 backgroundFlushCommits(true);
976 }
977
978 validatePut(put);
979
980 currentWriteBufferSize += put.heapSize();
981 writeAsyncBuffer.add(put);
982
983 while (currentWriteBufferSize > writeBufferSize) {
984 backgroundFlushCommits(false);
985 }
986 }
987
988
989
990
991
992
993
994
995
996 private void backgroundFlushCommits(boolean synchronous) throws
997 InterruptedIOException, RetriesExhaustedWithDetailsException {
998
999 try {
1000 do {
1001 ap.submit(writeAsyncBuffer, true);
1002 } while (synchronous && !writeAsyncBuffer.isEmpty());
1003
1004 if (synchronous) {
1005 ap.waitUntilDone();
1006 }
1007
1008 if (ap.hasError()) {
1009 LOG.debug(tableName + ": One or more of the operations have failed -" +
1010 " waiting for all operation in progress to finish (successfully or not)");
1011 while (!writeAsyncBuffer.isEmpty()) {
1012 ap.submit(writeAsyncBuffer, true);
1013 }
1014 ap.waitUntilDone();
1015
1016 if (!clearBufferOnFail) {
1017
1018
1019 writeAsyncBuffer.addAll(ap.getFailedOperations());
1020 }
1021 RetriesExhaustedWithDetailsException e = ap.getErrors();
1022 ap.clearErrors();
1023 throw e;
1024 }
1025 } finally {
1026 currentWriteBufferSize = 0;
1027 for (Row mut : writeAsyncBuffer) {
1028 if (mut instanceof Mutation) {
1029 currentWriteBufferSize += ((Mutation) mut).heapSize();
1030 }
1031 }
1032 }
1033 }
1034
1035
1036
1037
1038 @Override
1039 public void mutateRow(final RowMutations rm) throws IOException {
1040 RegionServerCallable<Void> callable =
1041 new RegionServerCallable<Void>(connection, getName(), rm.getRow()) {
1042 public Void call() throws IOException {
1043 try {
1044 RegionAction.Builder regionMutationBuilder = RequestConverter.buildRegionAction(
1045 getLocation().getRegionInfo().getRegionName(), rm);
1046 regionMutationBuilder.setAtomic(true);
1047 MultiRequest request =
1048 MultiRequest.newBuilder().addRegionAction(regionMutationBuilder.build()).build();
1049 PayloadCarryingRpcController pcrc = rpcControllerFactory.newController();
1050 pcrc.setPriority(tableName);
1051 getStub().multi(pcrc, request);
1052 } catch (ServiceException se) {
1053 throw ProtobufUtil.getRemoteException(se);
1054 }
1055 return null;
1056 }
1057 };
1058 rpcCallerFactory.<Void> newCaller().callWithRetries(callable, this.operationTimeout);
1059 }
1060
1061
1062
1063
1064 @Override
1065 public Result append(final Append append) throws IOException {
1066 if (append.numFamilies() == 0) {
1067 throw new IOException(
1068 "Invalid arguments to append, no columns specified");
1069 }
1070
1071 NonceGenerator ng = this.connection.getNonceGenerator();
1072 final long nonceGroup = ng.getNonceGroup(), nonce = ng.newNonce();
1073 RegionServerCallable<Result> callable =
1074 new RegionServerCallable<Result>(this.connection, getName(), append.getRow()) {
1075 public Result call() throws IOException {
1076 try {
1077 MutateRequest request = RequestConverter.buildMutateRequest(
1078 getLocation().getRegionInfo().getRegionName(), append, nonceGroup, nonce);
1079 PayloadCarryingRpcController rpcController = rpcControllerFactory.newController();
1080 rpcController.setPriority(getTableName());
1081 MutateResponse response = getStub().mutate(rpcController, request);
1082 if (!response.hasResult()) return null;
1083 return ProtobufUtil.toResult(response.getResult(), rpcController.cellScanner());
1084 } catch (ServiceException se) {
1085 throw ProtobufUtil.getRemoteException(se);
1086 }
1087 }
1088 };
1089 return rpcCallerFactory.<Result> newCaller().callWithRetries(callable, this.operationTimeout);
1090 }
1091
1092
1093
1094
1095 @Override
1096 public Result increment(final Increment increment) throws IOException {
1097 if (!increment.hasFamilies()) {
1098 throw new IOException(
1099 "Invalid arguments to increment, no columns specified");
1100 }
1101 NonceGenerator ng = this.connection.getNonceGenerator();
1102 final long nonceGroup = ng.getNonceGroup(), nonce = ng.newNonce();
1103 RegionServerCallable<Result> callable = new RegionServerCallable<Result>(this.connection,
1104 getName(), increment.getRow()) {
1105 public Result call() throws IOException {
1106 try {
1107 MutateRequest request = RequestConverter.buildMutateRequest(
1108 getLocation().getRegionInfo().getRegionName(), increment, nonceGroup, nonce);
1109 PayloadCarryingRpcController rpcController = rpcControllerFactory.newController();
1110 rpcController.setPriority(getTableName());
1111 MutateResponse response = getStub().mutate(rpcController, request);
1112 return ProtobufUtil.toResult(response.getResult(), rpcController.cellScanner());
1113 } catch (ServiceException se) {
1114 throw ProtobufUtil.getRemoteException(se);
1115 }
1116 }
1117 };
1118 return rpcCallerFactory.<Result> newCaller().callWithRetries(callable, this.operationTimeout);
1119 }
1120
1121
1122
1123
1124 @Override
1125 public long incrementColumnValue(final byte [] row, final byte [] family,
1126 final byte [] qualifier, final long amount)
1127 throws IOException {
1128 return incrementColumnValue(row, family, qualifier, amount, Durability.SYNC_WAL);
1129 }
1130
1131
1132
1133
1134 @Deprecated
1135 @Override
1136 public long incrementColumnValue(final byte [] row, final byte [] family,
1137 final byte [] qualifier, final long amount, final boolean writeToWAL)
1138 throws IOException {
1139 return incrementColumnValue(row, family, qualifier, amount,
1140 writeToWAL? Durability.SKIP_WAL: Durability.USE_DEFAULT);
1141 }
1142
1143
1144
1145
1146 @Override
1147 public long incrementColumnValue(final byte [] row, final byte [] family,
1148 final byte [] qualifier, final long amount, final Durability durability)
1149 throws IOException {
1150 NullPointerException npe = null;
1151 if (row == null) {
1152 npe = new NullPointerException("row is null");
1153 } else if (family == null) {
1154 npe = new NullPointerException("family is null");
1155 } else if (qualifier == null) {
1156 npe = new NullPointerException("qualifier is null");
1157 }
1158 if (npe != null) {
1159 throw new IOException(
1160 "Invalid arguments to incrementColumnValue", npe);
1161 }
1162
1163 NonceGenerator ng = this.connection.getNonceGenerator();
1164 final long nonceGroup = ng.getNonceGroup(), nonce = ng.newNonce();
1165 RegionServerCallable<Long> callable =
1166 new RegionServerCallable<Long>(connection, getName(), row) {
1167 public Long call() throws IOException {
1168 try {
1169 MutateRequest request = RequestConverter.buildIncrementRequest(
1170 getLocation().getRegionInfo().getRegionName(), row, family,
1171 qualifier, amount, durability, nonceGroup, nonce);
1172 PayloadCarryingRpcController rpcController = rpcControllerFactory.newController();
1173 rpcController.setPriority(getTableName());
1174 MutateResponse response = getStub().mutate(rpcController, request);
1175 Result result =
1176 ProtobufUtil.toResult(response.getResult(), rpcController.cellScanner());
1177 return Long.valueOf(Bytes.toLong(result.getValue(family, qualifier)));
1178 } catch (ServiceException se) {
1179 throw ProtobufUtil.getRemoteException(se);
1180 }
1181 }
1182 };
1183 return rpcCallerFactory.<Long> newCaller().callWithRetries(callable, this.operationTimeout);
1184 }
1185
1186
1187
1188
1189 @Override
1190 public boolean checkAndPut(final byte [] row,
1191 final byte [] family, final byte [] qualifier, final byte [] value,
1192 final Put put)
1193 throws IOException {
1194 RegionServerCallable<Boolean> callable =
1195 new RegionServerCallable<Boolean>(connection, getName(), row) {
1196 public Boolean call() throws IOException {
1197 try {
1198 MutateRequest request = RequestConverter.buildMutateRequest(
1199 getLocation().getRegionInfo().getRegionName(), row, family, qualifier,
1200 new BinaryComparator(value), CompareType.EQUAL, put);
1201 PayloadCarryingRpcController rpcController = rpcControllerFactory.newController();
1202 rpcController.setPriority(getTableName());
1203 MutateResponse response = getStub().mutate(rpcController, request);
1204 return Boolean.valueOf(response.getProcessed());
1205 } catch (ServiceException se) {
1206 throw ProtobufUtil.getRemoteException(se);
1207 }
1208 }
1209 };
1210 return rpcCallerFactory.<Boolean> newCaller().callWithRetries(callable, this.operationTimeout);
1211 }
1212
1213
1214
1215
1216
1217 @Override
1218 public boolean checkAndDelete(final byte [] row,
1219 final byte [] family, final byte [] qualifier, final byte [] value,
1220 final Delete delete)
1221 throws IOException {
1222 RegionServerCallable<Boolean> callable =
1223 new RegionServerCallable<Boolean>(connection, getName(), row) {
1224 public Boolean call() throws IOException {
1225 try {
1226 MutateRequest request = RequestConverter.buildMutateRequest(
1227 getLocation().getRegionInfo().getRegionName(), row, family, qualifier,
1228 new BinaryComparator(value), CompareType.EQUAL, delete);
1229 PayloadCarryingRpcController rpcController = rpcControllerFactory.newController();
1230 rpcController.setPriority(getTableName());
1231 MutateResponse response = getStub().mutate(rpcController, request);
1232 return Boolean.valueOf(response.getProcessed());
1233 } catch (ServiceException se) {
1234 throw ProtobufUtil.getRemoteException(se);
1235 }
1236 }
1237 };
1238 return rpcCallerFactory.<Boolean> newCaller().callWithRetries(callable, this.operationTimeout);
1239 }
1240
1241
1242
1243
1244 @Override
1245 public boolean checkAndMutate(final byte [] row, final byte [] family, final byte [] qualifier,
1246 final CompareOp compareOp, final byte [] value, final RowMutations rm)
1247 throws IOException {
1248 RegionServerCallable<Boolean> callable =
1249 new RegionServerCallable<Boolean>(connection, getName(), row) {
1250 @Override
1251 public Boolean call() throws IOException {
1252 PayloadCarryingRpcController controller = rpcControllerFactory.newController();
1253 controller.setPriority(tableName);
1254 try {
1255 CompareType compareType = CompareType.valueOf(compareOp.name());
1256 MultiRequest request = RequestConverter.buildMutateRequest(
1257 getLocation().getRegionInfo().getRegionName(), row, family, qualifier,
1258 new BinaryComparator(value), compareType, rm);
1259 ClientProtos.MultiResponse response = getStub().multi(controller, request);
1260 return Boolean.valueOf(response.getProcessed());
1261 } catch (ServiceException se) {
1262 throw ProtobufUtil.getRemoteException(se);
1263 }
1264 }
1265 };
1266 return rpcCallerFactory.<Boolean> newCaller().callWithRetries(callable, this.operationTimeout);
1267 }
1268
1269
1270
1271
1272 @Override
1273 public boolean exists(final Get get) throws IOException {
1274 get.setCheckExistenceOnly(true);
1275 Result r = get(get);
1276 assert r.getExists() != null;
1277 return r.getExists();
1278 }
1279
1280
1281
1282
1283 @Override
1284 public Boolean[] exists(final List<Get> gets) throws IOException {
1285 if (gets.isEmpty()) return new Boolean[]{};
1286 if (gets.size() == 1) return new Boolean[]{exists(gets.get(0))};
1287
1288 for (Get g: gets){
1289 g.setCheckExistenceOnly(true);
1290 }
1291
1292 Object[] r1;
1293 try {
1294 r1 = batch(gets);
1295 } catch (InterruptedException e) {
1296 throw (InterruptedIOException)new InterruptedIOException().initCause(e);
1297 }
1298
1299
1300 Boolean[] results = new Boolean[r1.length];
1301 int i = 0;
1302 for (Object o : r1) {
1303
1304 results[i++] = ((Result)o).getExists();
1305 }
1306
1307 return results;
1308 }
1309
1310
1311
1312
1313 @Override
1314 public void flushCommits() throws InterruptedIOException, RetriesExhaustedWithDetailsException {
1315
1316
1317 backgroundFlushCommits(true);
1318 }
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 public <R> void processBatchCallback(
1332 final List<? extends Row> list, final Object[] results, final Batch.Callback<R> callback)
1333 throws IOException, InterruptedException {
1334 this.batchCallback(list, results, callback);
1335 }
1336
1337
1338
1339
1340
1341
1342 public void processBatch(final List<? extends Row> list, final Object[] results)
1343 throws IOException, InterruptedException {
1344
1345 this.processBatchCallback(list, results, null);
1346 }
1347
1348
1349 @Override
1350 public void close() throws IOException {
1351 if (this.closed) {
1352 return;
1353 }
1354 flushCommits();
1355 if (cleanupPoolOnClose) {
1356 this.pool.shutdown();
1357 }
1358 if (cleanupConnectionOnClose) {
1359 if (this.connection != null) {
1360 this.connection.close();
1361 }
1362 }
1363 this.closed = true;
1364 }
1365
1366
1367 public void validatePut(final Put put) throws IllegalArgumentException {
1368 validatePut(put, tableConfiguration.getMaxKeyValueSize());
1369 }
1370
1371
1372 public static void validatePut(Put put, int maxKeyValueSize) throws IllegalArgumentException {
1373 if (put.isEmpty()) {
1374 throw new IllegalArgumentException("No columns to insert");
1375 }
1376 if (maxKeyValueSize > 0) {
1377 for (List<Cell> list : put.getFamilyCellMap().values()) {
1378 for (Cell cell : list) {
1379
1380 KeyValue kv = KeyValueUtil.ensureKeyValue(cell);
1381 if (kv.getLength() > maxKeyValueSize) {
1382 throw new IllegalArgumentException("KeyValue size too large");
1383 }
1384 }
1385 }
1386 }
1387 }
1388
1389
1390
1391
1392 @Override
1393 public boolean isAutoFlush() {
1394 return autoFlush;
1395 }
1396
1397
1398
1399
1400 @Deprecated
1401 @Override
1402 public void setAutoFlush(boolean autoFlush) {
1403 setAutoFlush(autoFlush, autoFlush);
1404 }
1405
1406
1407
1408
1409 @Override
1410 public void setAutoFlushTo(boolean autoFlush) {
1411 setAutoFlush(autoFlush, clearBufferOnFail);
1412 }
1413
1414
1415
1416
1417 @Override
1418 public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
1419 this.autoFlush = autoFlush;
1420 this.clearBufferOnFail = autoFlush || clearBufferOnFail;
1421 }
1422
1423
1424
1425
1426
1427
1428
1429
1430 @Override
1431 public long getWriteBufferSize() {
1432 return writeBufferSize;
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443 public void setWriteBufferSize(long writeBufferSize) throws IOException {
1444 this.writeBufferSize = writeBufferSize;
1445 if(currentWriteBufferSize > writeBufferSize) {
1446 flushCommits();
1447 }
1448 }
1449
1450
1451
1452
1453
1454 ExecutorService getPool() {
1455 return this.pool;
1456 }
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 public static void setRegionCachePrefetch(final byte[] tableName,
1468 final boolean enable) throws IOException {
1469 setRegionCachePrefetch(TableName.valueOf(tableName), enable);
1470 }
1471
1472 public static void setRegionCachePrefetch(
1473 final TableName tableName,
1474 final boolean enable) throws IOException {
1475 HConnectionManager.execute(new HConnectable<Void>(HBaseConfiguration.create()) {
1476 @Override
1477 public Void connect(HConnection connection) throws IOException {
1478 connection.setRegionCachePrefetch(tableName, enable);
1479 return null;
1480 }
1481 });
1482 }
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 public static void setRegionCachePrefetch(final Configuration conf,
1495 final byte[] tableName, final boolean enable) throws IOException {
1496 setRegionCachePrefetch(conf, TableName.valueOf(tableName), enable);
1497 }
1498
1499 public static void setRegionCachePrefetch(final Configuration conf,
1500 final TableName tableName,
1501 final boolean enable) throws IOException {
1502 HConnectionManager.execute(new HConnectable<Void>(conf) {
1503 @Override
1504 public Void connect(HConnection connection) throws IOException {
1505 connection.setRegionCachePrefetch(tableName, enable);
1506 return null;
1507 }
1508 });
1509 }
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519 public static boolean getRegionCachePrefetch(final Configuration conf,
1520 final byte[] tableName) throws IOException {
1521 return getRegionCachePrefetch(conf, TableName.valueOf(tableName));
1522 }
1523
1524 public static boolean getRegionCachePrefetch(final Configuration conf,
1525 final TableName tableName) throws IOException {
1526 return HConnectionManager.execute(new HConnectable<Boolean>(conf) {
1527 @Override
1528 public Boolean connect(HConnection connection) throws IOException {
1529 return connection.getRegionCachePrefetch(tableName);
1530 }
1531 });
1532 }
1533
1534
1535
1536
1537
1538
1539
1540
1541 public static boolean getRegionCachePrefetch(final byte[] tableName) throws IOException {
1542 return getRegionCachePrefetch(TableName.valueOf(tableName));
1543 }
1544
1545 public static boolean getRegionCachePrefetch(
1546 final TableName tableName) throws IOException {
1547 return HConnectionManager.execute(new HConnectable<Boolean>(
1548 HBaseConfiguration.create()) {
1549 @Override
1550 public Boolean connect(HConnection connection) throws IOException {
1551 return connection.getRegionCachePrefetch(tableName);
1552 }
1553 });
1554 }
1555
1556
1557
1558
1559
1560 public void clearRegionCache() {
1561 this.connection.clearRegionCache();
1562 }
1563
1564
1565
1566
1567 public CoprocessorRpcChannel coprocessorService(byte[] row) {
1568 return new RegionCoprocessorRpcChannel(connection, tableName, row, rpcCallerFactory,
1569 rpcControllerFactory);
1570 }
1571
1572
1573
1574
1575 @Override
1576 public <T extends Service, R> Map<byte[],R> coprocessorService(final Class<T> service,
1577 byte[] startKey, byte[] endKey, final Batch.Call<T,R> callable)
1578 throws ServiceException, Throwable {
1579 final Map<byte[],R> results = Collections.synchronizedMap(
1580 new TreeMap<byte[], R>(Bytes.BYTES_COMPARATOR));
1581 coprocessorService(service, startKey, endKey, callable, new Batch.Callback<R>() {
1582 public void update(byte[] region, byte[] row, R value) {
1583 if (region != null) {
1584 results.put(region, value);
1585 }
1586 }
1587 });
1588 return results;
1589 }
1590
1591
1592
1593
1594 @Override
1595 public <T extends Service, R> void coprocessorService(final Class<T> service,
1596 byte[] startKey, byte[] endKey, final Batch.Call<T,R> callable,
1597 final Batch.Callback<R> callback) throws ServiceException, Throwable {
1598
1599
1600 List<byte[]> keys = getStartKeysInRange(startKey, endKey);
1601
1602 Map<byte[],Future<R>> futures =
1603 new TreeMap<byte[],Future<R>>(Bytes.BYTES_COMPARATOR);
1604 for (final byte[] r : keys) {
1605 final RegionCoprocessorRpcChannel channel =
1606 new RegionCoprocessorRpcChannel(connection, tableName, r, rpcCallerFactory,
1607 rpcControllerFactory);
1608 Future<R> future = pool.submit(
1609 new Callable<R>() {
1610 public R call() throws Exception {
1611 T instance = ProtobufUtil.newServiceStub(service, channel);
1612 R result = callable.call(instance);
1613 byte[] region = channel.getLastRegion();
1614 if (callback != null) {
1615 callback.update(region, r, result);
1616 }
1617 return result;
1618 }
1619 });
1620 futures.put(r, future);
1621 }
1622 for (Map.Entry<byte[],Future<R>> e : futures.entrySet()) {
1623 try {
1624 e.getValue().get();
1625 } catch (ExecutionException ee) {
1626 LOG.warn("Error calling coprocessor service " + service.getName() + " for row "
1627 + Bytes.toStringBinary(e.getKey()), ee);
1628 throw ee.getCause();
1629 } catch (InterruptedException ie) {
1630 throw new InterruptedIOException("Interrupted calling coprocessor service " + service.getName()
1631 + " for row " + Bytes.toStringBinary(e.getKey()))
1632 .initCause(ie);
1633 }
1634 }
1635 }
1636
1637 private List<byte[]> getStartKeysInRange(byte[] start, byte[] end)
1638 throws IOException {
1639 if (start == null) {
1640 start = HConstants.EMPTY_START_ROW;
1641 }
1642 if (end == null) {
1643 end = HConstants.EMPTY_END_ROW;
1644 }
1645 return getKeysAndRegionsInRange(start, end, true).getFirst();
1646 }
1647
1648 public void setOperationTimeout(int operationTimeout) {
1649 this.operationTimeout = operationTimeout;
1650 }
1651
1652 public int getOperationTimeout() {
1653 return operationTimeout;
1654 }
1655
1656 @Override
1657 public String toString() {
1658 return tableName + ";" + connection;
1659 }
1660
1661
1662
1663
1664
1665
1666 public static void main(String[] args) throws IOException {
1667 HTable t = new HTable(HBaseConfiguration.create(), args[0]);
1668 try {
1669 System.out.println(t.get(new Get(Bytes.toBytes(args[1]))));
1670 } finally {
1671 t.close();
1672 }
1673 }
1674
1675
1676
1677
1678 @Override
1679 public <R extends Message> Map<byte[], R> batchCoprocessorService(
1680 Descriptors.MethodDescriptor methodDescriptor, Message request,
1681 byte[] startKey, byte[] endKey, R responsePrototype) throws ServiceException, Throwable {
1682 final Map<byte[], R> results = Collections.synchronizedMap(new TreeMap<byte[], R>(
1683 Bytes.BYTES_COMPARATOR));
1684 batchCoprocessorService(methodDescriptor, request, startKey, endKey, responsePrototype,
1685 new Callback<R>() {
1686
1687 @Override
1688 public void update(byte[] region, byte[] row, R result) {
1689 if (region != null) {
1690 results.put(region, result);
1691 }
1692 }
1693 });
1694 return results;
1695 }
1696
1697
1698
1699
1700 @Override
1701 public <R extends Message> void batchCoprocessorService(
1702 final Descriptors.MethodDescriptor methodDescriptor, final Message request,
1703 byte[] startKey, byte[] endKey, final R responsePrototype, final Callback<R> callback)
1704 throws ServiceException, Throwable {
1705
1706
1707 Pair<List<byte[]>, List<HRegionLocation>> keysAndRegions =
1708 getKeysAndRegionsInRange(startKey, endKey, true);
1709 List<byte[]> keys = keysAndRegions.getFirst();
1710 List<HRegionLocation> regions = keysAndRegions.getSecond();
1711
1712
1713 if (keys.isEmpty()) {
1714 LOG.info("No regions were selected by key range start=" + Bytes.toStringBinary(startKey) +
1715 ", end=" + Bytes.toStringBinary(endKey));
1716 return;
1717 }
1718
1719 List<RegionCoprocessorServiceExec> execs = new ArrayList<RegionCoprocessorServiceExec>();
1720 final Map<byte[], RegionCoprocessorServiceExec> execsByRow =
1721 new TreeMap<byte[], RegionCoprocessorServiceExec>(Bytes.BYTES_COMPARATOR);
1722 for (int i = 0; i < keys.size(); i++) {
1723 final byte[] rowKey = keys.get(i);
1724 final byte[] region = regions.get(i).getRegionInfo().getRegionName();
1725 RegionCoprocessorServiceExec exec =
1726 new RegionCoprocessorServiceExec(region, rowKey, methodDescriptor, request);
1727 execs.add(exec);
1728 execsByRow.put(rowKey, exec);
1729 }
1730
1731
1732
1733 final List<Throwable> callbackErrorExceptions = new ArrayList<Throwable>();
1734 final List<Row> callbackErrorActions = new ArrayList<Row>();
1735 final List<String> callbackErrorServers = new ArrayList<String>();
1736
1737 AsyncProcess<ClientProtos.CoprocessorServiceResult> asyncProcess =
1738 new AsyncProcess<ClientProtos.CoprocessorServiceResult>(connection, tableName, pool,
1739 new AsyncProcess.AsyncProcessCallback<ClientProtos.CoprocessorServiceResult>() {
1740 @SuppressWarnings("unchecked")
1741 @Override
1742 public void success(int originalIndex, byte[] region, Row row,
1743 ClientProtos.CoprocessorServiceResult serviceResult) {
1744 if (LOG.isTraceEnabled()) {
1745 LOG.trace("Received result for endpoint " + methodDescriptor.getFullName() +
1746 " call #" + originalIndex + ": region=" + Bytes.toStringBinary(region) +
1747 ", row=" + Bytes.toStringBinary(row.getRow()) +
1748 ", value=" + serviceResult.getValue().getValue());
1749 }
1750 try {
1751 callback.update(region, row.getRow(),
1752 (R) responsePrototype.newBuilderForType().mergeFrom(
1753 serviceResult.getValue().getValue()).build());
1754 } catch (InvalidProtocolBufferException e) {
1755 LOG.error("Unexpected response type from endpoint " + methodDescriptor.getFullName(),
1756 e);
1757 callbackErrorExceptions.add(e);
1758 callbackErrorActions.add(row);
1759 callbackErrorServers.add("null");
1760 }
1761 }
1762
1763 @Override
1764 public boolean failure(int originalIndex, byte[] region, Row row, Throwable t) {
1765 RegionCoprocessorServiceExec exec = (RegionCoprocessorServiceExec) row;
1766 LOG.error("Failed calling endpoint " + methodDescriptor.getFullName() + ": region="
1767 + Bytes.toStringBinary(exec.getRegion()), t);
1768 return true;
1769 }
1770
1771 @Override
1772 public boolean retriableFailure(int originalIndex, Row row, byte[] region,
1773 Throwable exception) {
1774 RegionCoprocessorServiceExec exec = (RegionCoprocessorServiceExec) row;
1775 LOG.error("Failed calling endpoint " + methodDescriptor.getFullName() + ": region="
1776 + Bytes.toStringBinary(exec.getRegion()), exception);
1777 return !(exception instanceof DoNotRetryIOException);
1778 }
1779 },
1780 configuration, rpcCallerFactory, rpcControllerFactory);
1781
1782 asyncProcess.submitAll(execs);
1783 asyncProcess.waitUntilDone();
1784
1785 if (asyncProcess.hasError()) {
1786 throw asyncProcess.getErrors();
1787 } else if (!callbackErrorExceptions.isEmpty()) {
1788 throw new RetriesExhaustedWithDetailsException(callbackErrorExceptions, callbackErrorActions,
1789 callbackErrorServers);
1790 }
1791 }
1792 }