Author: tedyu
Date: Tue Feb 14 15:28:59 2012
New Revision: 1243994

URL: http://svn.apache.org/viewvc?rev=1243994&view=rev
Log:
HBASE-5388 Tune HConnectionManager#getCachedLocation method (Ronghai Ma)

Modified:
    
hbase/trunk/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
    
hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java

Modified: 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java?rev=1243994&r1=1243993&r2=1243994&view=diff
==============================================================================
--- 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
 (original)
+++ 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java
 Tue Feb 14 15:28:59 2012
@@ -520,9 +520,9 @@ public class HConnectionManager {
      * 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<Integer, SortedMap<byte [], HRegionLocation>>
+    private final Map<Integer, SoftValueSortedMap<byte [], HRegionLocation>>
       cachedRegionLocations =
-        new HashMap<Integer, SortedMap<byte [], HRegionLocation>>();
+        new HashMap<Integer, SoftValueSortedMap<byte [], HRegionLocation>>();
 
     // 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,7 +1058,7 @@ public class HConnectionManager {
      */
     HRegionLocation getCachedLocation(final byte [] tableName,
         final byte [] row) {
-      SortedMap<byte [], HRegionLocation> tableLocations =
+      SoftValueSortedMap<byte [], HRegionLocation> tableLocations =
         getTableLocations(tableName);
 
       // start to examine the cache. we can only do cache actions
@@ -1067,43 +1067,26 @@ public class HConnectionManager {
         return null;
       }
 
-      HRegionLocation rl = tableLocations.get(row);
-      if (rl != null) {
-        return rl;
+      HRegionLocation possibleRegion = tableLocations.get(row);
+      if (possibleRegion != null) {
+        return possibleRegion;
       }
 
-      // Cut the cache so that we only get the part that could contain
-      // regions that match our key
-      SortedMap<byte[], HRegionLocation> matchingRegions =
-        tableLocations.headMap(row);
-
-      // 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;
-          }
-        }
+      possibleRegion = tableLocations.lowerValueByKey(row);
+      if (possibleRegion == null) {
+        return null;
+      }
+
+      // 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_END_ROW, signifying that the region we're
+      // checking is actually the last region in the table.
+      byte[] endKey = possibleRegion.getRegionInfo().getEndKey();
+      if (Bytes.equals(endKey, HConstants.EMPTY_END_ROW) ||
+          KeyValue.getRowComparator(tableName).compareRows(
+              endKey, 0, endKey.length, row, 0, row.length) > 0) {
+        return possibleRegion;
       }
 
       // Passed all the way through, so we got nothin - complete cache miss
@@ -1173,11 +1156,11 @@ public class HConnectionManager {
      * @param tableName
      * @return Map of cached locations for passed <code>tableName</code>
      */
-    private SortedMap<byte [], HRegionLocation> getTableLocations(
+    private SoftValueSortedMap<byte [], HRegionLocation> getTableLocations(
         final byte [] tableName) {
       // find the map of cached locations for this table
       Integer key = Bytes.mapKey(tableName);
-      SortedMap<byte [], HRegionLocation> result;
+      SoftValueSortedMap<byte [], HRegionLocation> result;
       synchronized (this.cachedRegionLocations) {
         result = this.cachedRegionLocations.get(key);
         // if tableLocations for this table isn't built yet, make one

Modified: 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java
URL: 
http://svn.apache.org/viewvc/hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java?rev=1243994&r1=1243993&r2=1243994&view=diff
==============================================================================
--- 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java 
(original)
+++ 
hbase/trunk/src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java 
Tue Feb 14 15:28:59 2012
@@ -28,6 +28,7 @@ import java.util.Collections;
 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,32 @@ public class SoftValueSortedMap<K,V> imp
     }
   }
 
+  /*
+   * 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<K,SoftValue<K,V>> entry =
+        ((NavigableMap<K, SoftValue<K,V>>) this.internalMap).lowerEntry(key);
+      if (entry==null) {
+        return null;
+      }
+      SoftValue<K,V> value=entry.getValue();
+      if (value==null) {
+        return null;
+      }
+      if (value.get() == null) {
+        this.internalMap.remove(key);
+        return null;
+      }
+      return value.get();
+    }
+  }
+  
   public boolean isEmpty() {
     synchronized(sync) {
       checkReferences();


Reply via email to