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 =