huaxiangsun commented on a change in pull request #2645:
URL: https://github.com/apache/hbase/pull/2645#discussion_r521488955
##########
File path:
hbase-client/src/main/java/org/apache/hadoop/hbase/client/ScannerCallableWithReplicas.java
##########
@@ -209,13 +209,13 @@ public MoreResults moreResultsForScan() {
LOG.debug("Scan with primary region returns " + e.getCause());
}
- // If rl's size is 1 or scan's consitency is strong, it needs to throw
- // out the exception from the primary replica
- if ((regionReplication == 1) || (scan.getConsistency() ==
Consistency.STRONG)) {
+ // If rl's size is 1 or scan's consistency is strong or a specific
replica id has been
+ // specified, it needs to throw out the exception from the first tried
replica
+ if (regionReplication == 1 || scan.getConsistency() ==
Consistency.STRONG ||
+ scan.getReplicaId() >= 0) {
Review comment:
More changes are needed in the following.
`diff --git
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ScannerCallableWithReplicas.java
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ScannerCallableWithReplicas.java
index 5fcc440096..6edaa83d11 100644
---
a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ScannerCallableWithReplicas.java
+++
b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ScannerCallableWithReplicas.java
@@ -18,6 +18,8 @@
package org.apache.hadoop.hbase.client;
+import static
org.apache.hadoop.hbase.client.RegionReplicaUtil.DEFAULT_REPLICA_ID;
+import static
org.apache.hadoop.hbase.client.RegionReplicaUtil.isScanForSpecificReplicaRegion;
import
org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;
import java.io.IOException;
@@ -45,10 +47,11 @@ import org.apache.hadoop.hbase.util.Pair;
/**
* This class has the logic for handling scanners for regions with and
without replicas.
- * 1. A scan is attempted on the default (primary) region
- * 2. The scanner sends all the RPCs to the default region until it is
done, or, there
- * is a timeout on the default (a timeout of zero is disallowed).
- * 3. If there is a timeout in (2) above, scanner(s) is opened on the
non-default replica(s)
+ * 1. A scan is attempted on the default (primary) region, or a specific
region.
+ * 2. The scanner sends all the RPCs to the default/specific region until
it is done, or, there
+ * is a timeout on the default/specific region (a timeout of zero is
disallowed).
+ * 3. If there is a timeout in (2) above, scanner(s) is opened on the
non-default replica(s) only
+ * for Consistency.TIMELINE without specific replica id specified.
* 4. The results from the first successful scanner are taken, and it is
stored which server
* returned the results.
* 5. The next RPCs are done on the above stored server until it is done or
there is a timeout,
@@ -160,7 +163,7 @@ class ScannerCallableWithReplicas implements
RetryingCallable<Result[]> {
RegionLocations rl = null;
try {
rl = RpcRetryingCallerWithReadReplicas.getRegionLocations(true,
- RegionReplicaUtil.DEFAULT_REPLICA_ID, cConnection, tableName,
+ DEFAULT_REPLICA_ID, cConnection, tableName,
currentScannerCallable.getRow());
} catch (RetriesExhaustedException | DoNotRetryIOException e) {
// We cannot get the primary replica region location, it is
possible that the region server
@@ -209,9 +212,10 @@ class ScannerCallableWithReplicas implements
RetryingCallable<Result[]> {
LOG.debug("Scan with primary region returns " + e.getCause());
}
- // If rl's size is 1 or scan's consitency is strong, it needs to throw
- // out the exception from the primary replica
- if ((regionReplication == 1) || (scan.getConsistency() ==
Consistency.STRONG)) {
+ // If rl's size is 1 or scan's consitency is strong, or scan is over
specific replica,
+ // it needs to throw out the exception from the primary replica
+ if ((regionReplication == 1) || (scan.getConsistency() ==
Consistency.STRONG) ||
+ isScanForSpecificReplicaRegion(scan)) {
// Rethrow the first exception
RpcRetryingCallerWithReadReplicas.throwEnrichedException(e,
retries);
}
@@ -225,8 +229,9 @@ class ScannerCallableWithReplicas implements
RetryingCallable<Result[]> {
// submit call for the all of the secondaries at once
int endIndex = regionReplication;
- if (scan.getConsistency() == Consistency.STRONG) {
- // When scan's consistency is strong, do not send to the secondaries
+ if ((scan.getConsistency() == Consistency.STRONG) ||
isScanForSpecificReplicaRegion(scan)){
+ // When scan's consistency is strong or scan is over specific replica
region,
+ // do not send to other replica regions.
endIndex = 1;
} else {
// TODO: this may be an overkill for large region replication
@@ -376,11 +381,13 @@ class ScannerCallableWithReplicas implements
RetryingCallable<Result[]> {
this.callable = callable;
// For the Consistency.STRONG (default case), we reuse the caller
// to keep compatibility with what is done in the past
- // For the Consistency.TIMELINE case, we can't reuse the caller
+ // For the Consistency.TIMELINE case, there are two cases. The first
case is that
+ // caller targets to a specific replica region, it can reuse the
caller.
+ // Otherwise, we can't reuse the caller
// since we could be making parallel RPCs (caller.callWithRetries is
synchronized
// and we can't invoke it multiple times at the same time)
this.caller = ScannerCallableWithReplicas.this.caller;
- if (scan.getConsistency() == Consistency.TIMELINE) {
+ if (!isScanForSpecificReplicaRegion(scan)) {
this.caller =
RpcRetryingCallerFactory.instantiate(ScannerCallableWithReplicas.this.conf)
.<Result[]>newCaller();
}`
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]