HBASE-5388 Tune HConnectionManager#getCachedLocation method (Ronghai Ma)

git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1243994 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Zhihong Yu 2012-02-14 15:28:59 +00:00
parent 37735435ec
commit ac0fb8d5ae
2 changed files with 49 additions and 39 deletions

View File

@ -520,9 +520,9 @@ public class HConnectionManager {
* Map of table to table {@link HRegionLocation}s. The table key is made * 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. * 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 = 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 // 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 // entry in cachedRegionLocations that map to this server; but the absence
@ -1058,7 +1058,7 @@ public class HConnectionManager {
*/ */
HRegionLocation getCachedLocation(final byte [] tableName, HRegionLocation getCachedLocation(final byte [] tableName,
final byte [] row) { final byte [] row) {
SortedMap<byte [], HRegionLocation> tableLocations = SoftValueSortedMap<byte [], HRegionLocation> tableLocations =
getTableLocations(tableName); getTableLocations(tableName);
// start to examine the cache. we can only do cache actions // start to examine the cache. we can only do cache actions
@ -1067,43 +1067,26 @@ public class HConnectionManager {
return null; return null;
} }
HRegionLocation rl = tableLocations.get(row); HRegionLocation possibleRegion = tableLocations.get(row);
if (rl != null) { if (possibleRegion != null) {
return rl; return possibleRegion;
} }
// Cut the cache so that we only get the part that could contain possibleRegion = tableLocations.lowerValueByKey(row);
// regions that match our key if (possibleRegion == null) {
SortedMap<byte[], HRegionLocation> matchingRegions = return null;
tableLocations.headMap(row); }
// if that portion of the map is empty, then we're done. otherwise, // make sure that the end key is greater than the row we're looking
// we need to examine the cached location to verify that it is // for, otherwise the row actually belongs in the next region, not
// a match by end key as well. // this one. the exception case is when the endkey is
if (!matchingRegions.isEmpty()) { // HConstants.EMPTY_END_ROW, signifying that the region we're
HRegionLocation possibleRegion = null; // checking is actually the last region in the table.
try { byte[] endKey = possibleRegion.getRegionInfo().getEndKey();
possibleRegion = matchingRegions.get(matchingRegions.lastKey()); if (Bytes.equals(endKey, HConstants.EMPTY_END_ROW) ||
} catch (NoSuchElementException nsee) { KeyValue.getRowComparator(tableName).compareRows(
LOG.warn("checkReferences() might have removed the key", nsee); endKey, 0, endKey.length, row, 0, row.length) > 0) {
} return possibleRegion;
// 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;
}
}
} }
// Passed all the way through, so we got nothin - complete cache miss // Passed all the way through, so we got nothin - complete cache miss
@ -1173,11 +1156,11 @@ public class HConnectionManager {
* @param tableName * @param tableName
* @return Map of cached locations for passed <code>tableName</code> * @return Map of cached locations for passed <code>tableName</code>
*/ */
private SortedMap<byte [], HRegionLocation> getTableLocations( private SoftValueSortedMap<byte [], HRegionLocation> getTableLocations(
final byte [] tableName) { final byte [] tableName) {
// find the map of cached locations for this table // find the map of cached locations for this table
Integer key = Bytes.mapKey(tableName); Integer key = Bytes.mapKey(tableName);
SortedMap<byte [], HRegionLocation> result; SoftValueSortedMap<byte [], HRegionLocation> result;
synchronized (this.cachedRegionLocations) { synchronized (this.cachedRegionLocations) {
result = this.cachedRegionLocations.get(key); result = this.cachedRegionLocations.get(key);
// if tableLocations for this table isn't built yet, make one // if tableLocations for this table isn't built yet, make one

View File

@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.NavigableMap;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
@ -175,6 +176,32 @@ public class SoftValueSortedMap<K,V> implements SortedMap<K,V> {
} }
} }
/*
* 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() { public boolean isEmpty() {
synchronized(sync) { synchronized(sync) {
checkReferences(); checkReferences();