diff --git src/main/java/org/apache/hadoop/hbase/client/HConnection.java src/main/java/org/apache/hadoop/hbase/client/HConnection.java index f3bd9fa..1774a89 100644 --- src/main/java/org/apache/hadoop/hbase/client/HConnection.java +++ 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 src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java index a9a51f9..f2d8d2f 100644 --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java @@ -1172,11 +1172,10 @@ public class HConnectionManager { */ void deleteCachedLocation(final byte [] tableName, final byte [] row) { synchronized (this.cachedRegionLocations) { - Map tableLocations = - getTableLocations(tableName); - // start to examine the cache. we can only do cache actions - // if there's something in the cache for this table. + Map tableLocations = getTableLocations(tableName); if (!tableLocations.isEmpty()) { + // start to examine the cache. we can only do cache actions + // if there's something in the cache for this table. HRegionLocation rl = getCachedLocation(tableName, row); if (rl != null) { tableLocations.remove(rl.getRegionInfo().getStartKey()); @@ -1192,6 +1191,27 @@ 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()) { + // if there's something in the cache for this table. + tableLocations.remove(location.getRegionInfo().getStartKey()); + if (LOG.isDebugEnabled()) { + LOG.debug("Removed " + + location.getRegionInfo().getRegionNameAsString() + + " for tableName=" + Bytes.toString(tableName) + + " from cache"); + } + } + } + } + + @Override public void clearCaches(String sn) { clearCachedLocationForServer(sn); } diff --git src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java index fcf43e7..f238eb0 100644 --- src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java +++ src/main/java/org/apache/hadoop/hbase/client/ServerCallable.java @@ -32,6 +32,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.DoNotRetryIOException; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionLocation; +import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.ipc.HBaseRPC; import org.apache.hadoop.hbase.ipc.HRegionInterface; import org.apache.hadoop.hbase.util.Bytes; @@ -174,6 +175,10 @@ public abstract class ServerCallable implements Callable { if (hrl != null) { getConnection().clearCaches(hrl.getHostnamePort()); } + } 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 = new RetriesExhaustedException.ThrowableWithExtraContext(t,