Index: src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java (revision 1222857) +++ src/main/java/org/apache/hadoop/hbase/util/SoftValueSortedMap.java (working copy) @@ -1,6 +1,4 @@ /** - * Copyright 2010 The Apache Software Foundation - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -19,6 +17,7 @@ */ package org.apache.hadoop.hbase.util; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.ArrayList; @@ -26,10 +25,11 @@ import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Map; +import java.util.NavigableMap; +import java.util.NavigableSet; import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.TreeSet; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; /** * A SortedMap implementation that uses Soft Reference values @@ -39,13 +39,13 @@ * @param key class * @param value class */ -public class SoftValueSortedMap implements SortedMap { - private final SortedMap> internalMap; - private final ReferenceQueue rq = new ReferenceQueue(); +public class SoftValueSortedMap implements NavigableMap { + private final ConcurrentNavigableMap> internalMap; + private final ReferenceQueue rq = new ReferenceQueue(); /** Constructor */ public SoftValueSortedMap() { - this(new TreeMap>()); + this(new ConcurrentSkipListMap>()); } /** @@ -53,13 +53,13 @@ * @param c comparator */ public SoftValueSortedMap(final Comparator c) { - this(new TreeMap>(c)); + this(new ConcurrentSkipListMap>(c)); } /** For headMap and tailMap support * @param original object to wrap */ - private SoftValueSortedMap(SortedMap> original) { + private SoftValueSortedMap(ConcurrentNavigableMap> original) { this.internalMap = original; } @@ -69,30 +69,26 @@ * Internally these call checkReferences on each access. * @return How many references cleared. */ + @SuppressWarnings("unchecked") private int checkReferences() { int i = 0; - for (Object obj; (obj = this.rq.poll()) != null;) { + for (Reference ref; (ref = this.rq.poll()) != null;) { i++; - //noinspection unchecked - this.internalMap.remove(((SoftValue)obj).key); + this.internalMap.remove(((SoftValue)ref).key); } return i; } - public synchronized V put(K key, V value) { + @Override + public V put(K key, V value) { checkReferences(); SoftValue oldValue = this.internalMap.put(key, new SoftValue(key, value, this.rq)); return oldValue == null ? null : oldValue.get(); } - @SuppressWarnings("unchecked") - public synchronized void putAll(Map map) { - throw new RuntimeException("Not implemented"); - } - - @SuppressWarnings({"SuspiciousMethodCalls"}) - public synchronized V get(Object key) { + @Override + public V get(Object key) { checkReferences(); SoftValue value = this.internalMap.get(key); if (value == null) { @@ -105,74 +101,85 @@ return value.get(); } - public synchronized V remove(Object key) { + @Override + public V remove(Object key) { checkReferences(); SoftValue value = this.internalMap.remove(key); return value == null ? null : value.get(); } - public synchronized boolean containsKey(Object key) { + @Override + public boolean containsKey(Object key) { checkReferences(); return this.internalMap.containsKey(key); } - public synchronized boolean containsValue(Object value) { -/* checkReferences(); - return internalMap.containsValue(value);*/ + @Override + public boolean containsValue(Object value) { throw new UnsupportedOperationException("Don't support containsValue!"); } - public synchronized K firstKey() { + @Override + public K firstKey() { checkReferences(); return internalMap.firstKey(); } - public synchronized K lastKey() { + @Override + public K lastKey() { checkReferences(); return internalMap.lastKey(); } - public synchronized SoftValueSortedMap headMap(K key) { + @Override + public SoftValueSortedMap headMap(K key) { checkReferences(); return new SoftValueSortedMap(this.internalMap.headMap(key)); } - public synchronized SoftValueSortedMap tailMap(K key) { + @Override + public SoftValueSortedMap tailMap(K key) { checkReferences(); return new SoftValueSortedMap(this.internalMap.tailMap(key)); } - public synchronized SoftValueSortedMap subMap(K fromKey, K toKey) { + @Override + public SoftValueSortedMap subMap(K fromKey, K toKey) { checkReferences(); return new SoftValueSortedMap(this.internalMap.subMap(fromKey, toKey)); } - public synchronized boolean isEmpty() { + @Override + public boolean isEmpty() { checkReferences(); return this.internalMap.isEmpty(); } - public synchronized int size() { + @Override + public int size() { checkReferences(); return this.internalMap.size(); } - public synchronized void clear() { + @Override + public void clear() { checkReferences(); this.internalMap.clear(); } - public synchronized Set keySet() { + @Override + public Set keySet() { checkReferences(); return this.internalMap.keySet(); } - @SuppressWarnings("unchecked") - public synchronized Comparator comparator() { + @Override + public Comparator comparator() { return this.internalMap.comparator(); } - public synchronized Set> entrySet() { + @Override + public Set> entrySet() { checkReferences(); Set>> entries = this.internalMap.entrySet(); Set> realEntries = new LinkedHashSet>(); @@ -182,7 +189,8 @@ return realEntries; } - public synchronized Collection values() { + @Override + public Collection values() { checkReferences(); Collection> softValues = this.internalMap.values(); ArrayList hardValues = new ArrayList(); @@ -195,7 +203,7 @@ private static class SoftValue extends SoftReference implements Map.Entry { final K key; - SoftValue(K key, V value, ReferenceQueue q) { + SoftValue(K key, V value, ReferenceQueue q) { super(value, q); this.key = key; } @@ -212,4 +220,118 @@ throw new RuntimeException("Not implemented"); } } + + @Override + public void putAll(Map m) { + throw new RuntimeException("Not implemented"); + } + + @Override + public java.util.Map.Entry lowerEntry(K key) { + checkReferences(); + return internalMap.lowerEntry(key).getValue(); + } + + @Override + public K lowerKey(K key) { + checkReferences(); + return internalMap.lowerKey(key); + } + + @Override + public java.util.Map.Entry floorEntry(K key) { + checkReferences(); + return internalMap.floorEntry(key).getValue(); + } + + @Override + public K floorKey(K key) { + checkReferences(); + return internalMap.floorKey(key); + } + + @Override + public java.util.Map.Entry ceilingEntry(K key) { + checkReferences(); + return internalMap.ceilingEntry(key).getValue(); + } + + @Override + public K ceilingKey(K key) { + checkReferences(); + return internalMap.ceilingKey(key); + } + + @Override + public java.util.Map.Entry higherEntry(K key) { + checkReferences(); + return internalMap.higherEntry(key).getValue(); + } + + @Override + public K higherKey(K key) { + checkReferences(); + return internalMap.higherKey(key); + } + + @Override + public java.util.Map.Entry firstEntry() { + checkReferences(); + return internalMap.firstEntry().getValue(); + } + + @Override + public java.util.Map.Entry lastEntry() { + checkReferences(); + return internalMap.lastEntry().getValue(); + } + + @Override + public java.util.Map.Entry pollFirstEntry() { + checkReferences(); + return internalMap.pollFirstEntry().getValue(); + } + + @Override + public java.util.Map.Entry pollLastEntry() { + checkReferences(); + return internalMap.pollLastEntry().getValue(); + } + + @Override + public NavigableMap descendingMap() { + checkReferences(); + return new SoftValueSortedMap(internalMap.descendingMap()); + } + + @Override + public NavigableSet navigableKeySet() { + checkReferences(); + return internalMap.navigableKeySet(); + } + + @Override + public NavigableSet descendingKeySet() { + checkReferences(); + return internalMap.descendingKeySet(); + } + + @Override + public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, + boolean toInclusive) { + checkReferences(); + return new SoftValueSortedMap(internalMap.subMap(fromKey, fromInclusive, toKey, toInclusive)); + } + + @Override + public NavigableMap headMap(K toKey, boolean inclusive) { + checkReferences(); + return new SoftValueSortedMap(this.internalMap.headMap(toKey, inclusive)); + } + + @Override + public NavigableMap tailMap(K fromKey, boolean inclusive) { + checkReferences(); + return new SoftValueSortedMap(this.internalMap.tailMap(fromKey, inclusive)); + } } Index: src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (revision 1222857) +++ src/main/java/org/apache/hadoop/hbase/client/HConnectionManager.java (working copy) @@ -34,8 +34,10 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.NavigableMap; 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; @@ -1068,7 +1070,7 @@ */ HRegionLocation getCachedLocation(final byte [] tableName, final byte [] row) { - SoftValueSortedMap tableLocations = + NavigableMap tableLocations = getTableLocations(tableName); // start to examine the cache. we can only do cache actions @@ -1084,7 +1086,7 @@ // Cut the cache so that we only get the part that could contain // regions that match our key - SoftValueSortedMap matchingRegions = + SortedMap matchingRegions = tableLocations.headMap(row); // if that portion of the map is empty, then we're done. otherwise, @@ -1127,7 +1129,7 @@ */ void deleteCachedLocation(final byte [] tableName, final byte [] row) { synchronized (this.cachedRegionLocations) { - SoftValueSortedMap tableLocations = + 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. @@ -1159,7 +1161,7 @@ if (!cachedServers.contains(server)) { return; } - for (SoftValueSortedMap tableLocations : + for (Map tableLocations : cachedRegionLocations.values()) { for (Entry e : tableLocations.entrySet()) { if (e.getValue().getServerAddress().toString().equals(server)) { @@ -1179,7 +1181,7 @@ * @param tableName * @return Map of cached locations for passed tableName */ - private SoftValueSortedMap getTableLocations( + private NavigableMap getTableLocations( final byte [] tableName) { // find the map of cached locations for this table Integer key = Bytes.mapKey(tableName); @@ -1217,7 +1219,7 @@ private void cacheLocation(final byte [] tableName, final HRegionLocation location) { byte [] startKey = location.getRegionInfo().getStartKey(); - SoftValueSortedMap tableLocations = + Map tableLocations = getTableLocations(tableName); boolean hasNewCache = false; synchronized (this.cachedRegionLocations) { @@ -1685,7 +1687,7 @@ int getNumberOfCachedRegionLocations(final byte[] tableName) { Integer key = Bytes.mapKey(tableName); synchronized (this.cachedRegionLocations) { - SoftValueSortedMap tableLocs = + Map tableLocs = this.cachedRegionLocations.get(key); if (tableLocs == null) {