diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnection.java hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnection.java
index fdeef70..9c0a0f4 100644
--- hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnection.java
+++ hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnection.java
@@ -163,6 +163,12 @@ public interface HConnection extends Abortable, Closeable {
public void clearRegionCache(final byte [] tableName);
/**
+ * Deletes cached locations for the specific region.
+ * @param location The location object for the region, to be purged from cache.
+ */
+ public void deleteCachedRegionLocation(final HRegionLocation location);
+
+ /**
* Find the location of the region of tableName that row
* lives in, ignoring any value that might be in the cache.
* @param tableName name of the table row is in
diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
index 15a68d9..4bd2708 100644
--- hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
+++ hbase-client/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
@@ -1893,6 +1893,28 @@ public class HConnectionManager {
}
}
+ @Override
+ public void deleteCachedRegionLocation(final HRegionLocation location) {
+ if (location == null) {
+ return;
+ }
+ synchronized (this.cachedRegionLocations) {
+ byte[] tableName = location.getRegionInfo().getTableName();
+ Map tableLocations = getTableLocations(tableName);
+ if (!tableLocations.isEmpty()) {
+ // Delete if there's something in the cache for this region.
+ HRegionLocation removedLocation =
+ tableLocations.remove(location.getRegionInfo().getStartKey());
+ if (LOG.isDebugEnabled() && removedLocation != null) {
+ LOG.debug("Removed " +
+ location.getRegionInfo().getRegionNameAsString() +
+ " for tableName=" + Bytes.toString(tableName) +
+ " from cache");
+ }
+ }
+ }
+ }
+
/**
* Update the location with the new value (if the exception is a RegionMovedException)
* or delete it from the cache.
diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java hbase-client/src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java
index bbffd97..ae099dd 100644
--- hbase-client/src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java
+++ hbase-client/src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java
@@ -28,6 +28,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.exceptions.DoNotRetryIOException;
+import org.apache.hadoop.hbase.exceptions.NotServingRegionException;
import org.apache.hadoop.hbase.ipc.HBaseClientRPC;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
@@ -181,6 +182,10 @@ public abstract class ServerCallable implements Callable {
// map to that slow/dead server; otherwise, let cache miss and ask
// .META. again to find the new location
getConnection().clearCaches(location.getServerName());
+ } else if (t instanceof NotServingRegionException && numRetries == 1) {
+ // Purge cache entries for this specific region from META cache
+ // since we don't call connect(true) when number of retries is 1.
+ getConnection().deleteCachedRegionLocation(location);
}
RetriesExhaustedException.ThrowableWithExtraContext qt =