Index: src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java (revision 1243741) +++ src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java (working copy) @@ -28,6 +28,7 @@ import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Map; +import java.util.NavigableMap; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -175,6 +176,28 @@ } } + /** + * Retrieves the value associated with the greatest key strictly less than + * the given key, or null if there is no such key + * @param key the key we're interested in + */ + public synchronized V lowerValueByKey(K key) { + synchronized(sync) { + checkReferences(); + + Map.Entry> entry = + ((NavigableMap>) this.internalMap).lowerEntry(key); + if (entry==null) { + return null; + } + SoftValue value=entry.getValue(); + if (value==null) { + return null; + } + return value.get(); + } + } + public boolean isEmpty() { synchronized(sync) { checkReferences(); Index: src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (revision 1243741) +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (working copy) @@ -32,9 +32,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.NoSuchElementException; import java.util.Set; -import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -520,9 +518,9 @@ * Map of table to table {@link HRegionLocation}s. The table key is made * by doing a {@link Bytes#mapKey(byte[])} of the table's name. */ - private final Map> + private final Map> cachedRegionLocations = - new HashMap>(); + new HashMap>(); // The presence of a server in the map implies it's likely that there is an // entry in cachedRegionLocations that map to this server; but the absence @@ -1058,8 +1056,7 @@ */ HRegionLocation getCachedLocation(final byte [] tableName, final byte [] row) { - SortedMap tableLocations = - getTableLocations(tableName); + SoftValueSortedMap tableLocations = getTableLocations(tableName); // start to examine the cache. we can only do cache actions // if there's something in the cache for this table. @@ -1072,38 +1069,16 @@ return rl; } - // Cut the cache so that we only get the part that could contain - // regions that match our key - SortedMap matchingRegions = - tableLocations.headMap(row); + rl = tableLocations.lowerValueByKey(row); + if (rl==null) { + return null; + } - // if that portion of the map is empty, then we're done. otherwise, - // we need to examine the cached location to verify that it is - // a match by end key as well. - if (!matchingRegions.isEmpty()) { - HRegionLocation possibleRegion = null; - try { - possibleRegion = matchingRegions.get(matchingRegions.lastKey()); - } catch (NoSuchElementException nsee) { - LOG.warn("checkReferences() might have removed the key", nsee); - } - - // there is a possibility that the reference was garbage collected - // in the instant since we checked isEmpty(). - if (possibleRegion != null) { - byte[] endKey = possibleRegion.getRegionInfo().getEndKey(); - - // make sure that the end key is greater than the row we're looking - // for, otherwise the row actually belongs in the next region, not - // this one. the exception case is when the endkey is - // HConstants.EMPTY_START_ROW, signifying that the region we're - // checking is actually the last region in the table. - if (Bytes.equals(endKey, HConstants.EMPTY_END_ROW) || - KeyValue.getRowComparator(tableName).compareRows(endKey, 0, endKey.length, - row, 0, row.length) > 0) { - return possibleRegion; - } - } + byte[] endKey = rl.getRegionInfo().getEndKey(); + if (Bytes.equals(endKey, HConstants.EMPTY_END_ROW) || + KeyValue.getRowComparator(tableName).compareRows( + endKey, 0, endKey.length, row, 0, row.length) > 0) { + return rl; } // Passed all the way through, so we got nothin - complete cache miss @@ -1173,11 +1148,11 @@ * @param tableName * @return Map of cached locations for passed tableName */ - private SortedMap getTableLocations( + private SoftValueSortedMap getTableLocations( final byte [] tableName) { // find the map of cached locations for this table Integer key = Bytes.mapKey(tableName); - SortedMap result; + SoftValueSortedMap result; synchronized (this.cachedRegionLocations) { result = this.cachedRegionLocations.get(key); // if tableLocations for this table isn't built yet, make one