diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ObjectPool.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ObjectPool.java index f736922..6a04812 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ObjectPool.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/ObjectPool.java @@ -22,6 +22,8 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.apache.hadoop.hbase.classification.InterfaceAudience; @@ -52,6 +54,9 @@ public abstract class ObjectPool { /** Does not permit null keys. */ protected final ConcurrentMap> referenceCache; + /** For preventing parallel purge */ + private final Lock purgeLock = new ReentrantLock(); + /** * The default initial capacity, * used when not otherwise specified in a constructor. @@ -117,12 +122,29 @@ public abstract class ObjectPool { } /** - * Removes stale references of shared objects from the pool. - * References newly becoming stale may still remain. - * The implementation of this method is expected to be lightweight - * when there is no stale reference. + * Removes stale references of shared objects from the pool. References newly becoming stale may + * still remain. + *

+ * The implementation of this method is expected to be lightweight when there is no stale + * reference with the Oracle (Sun) implementation of {@code ReferenceQueue}, because + * {@code ReferenceQueue.poll} just checks a volatile instance variable in {@code ReferenceQueue}. */ - public abstract void purge(); + public void purge() { + if (purgeLock.tryLock()) {// no parallel purge + try { + while (true) { + @SuppressWarnings("unchecked") + Reference ref = (Reference) staleRefQueue.poll(); + if (ref == null) { + break; + } + referenceCache.remove(getReferenceKey(ref), ref); + } + } finally { + purgeLock.unlock(); + } + } + } /** * Create a reference associated with the given object @@ -133,6 +155,13 @@ public abstract class ObjectPool { public abstract Reference createReference(K key, V obj); /** + * Get key of the given reference + * @param ref The reference + * @return key of the reference + */ + public abstract K getReferenceKey(Reference ref); + + /** * Returns a shared object associated with the given {@code key}, * which is identified by the {@code equals} method. * @throws NullPointerException if {@code key} is null diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/SoftObjectPool.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/SoftObjectPool.java index 7f27f98..19c65b2 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/SoftObjectPool.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/SoftObjectPool.java @@ -49,22 +49,6 @@ public class SoftObjectPool extends ObjectPool { } @Override - public void purge() { - // This method is lightweight while there is no stale reference - // with the Oracle (Sun) implementation of {@code ReferenceQueue}, - // because {@code ReferenceQueue.poll} just checks a volatile instance - // variable in {@code ReferenceQueue}. - while (true) { - @SuppressWarnings("unchecked") - SoftObjectReference ref = (SoftObjectReference) staleRefQueue.poll(); - if (ref == null) { - break; - } - referenceCache.remove(ref.key, ref); - } - } - - @Override public Reference createReference(K key, V obj) { return new SoftObjectReference(key, obj); } @@ -78,4 +62,9 @@ public class SoftObjectPool extends ObjectPool { } } + @Override + public K getReferenceKey(Reference ref) { + return ((SoftObjectReference) ref).key; + } + } diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/WeakObjectPool.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/WeakObjectPool.java index 8529f01..6714034 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/util/WeakObjectPool.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/util/WeakObjectPool.java @@ -49,22 +49,6 @@ public class WeakObjectPool extends ObjectPool { } @Override - public void purge() { - // This method is lightweight while there is no stale reference - // with the Oracle (Sun) implementation of {@code ReferenceQueue}, - // because {@code ReferenceQueue.poll} just checks a volatile instance - // variable in {@code ReferenceQueue}. - while (true) { - @SuppressWarnings("unchecked") - WeakObjectReference ref = (WeakObjectReference) staleRefQueue.poll(); - if (ref == null) { - break; - } - referenceCache.remove(ref.key, ref); - } - } - - @Override public Reference createReference(K key, V obj) { return new WeakObjectReference(key, obj); } @@ -78,4 +62,9 @@ public class WeakObjectPool extends ObjectPool { } } + @Override + public K getReferenceKey(Reference ref) { + return ((WeakObjectReference)ref).key; + } + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java index 3ca061a..dbaf80f 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java @@ -2982,6 +2982,7 @@ public class HRegionServer extends HasThread implements */ public static void main(String[] args) throws Exception { LOG.info("***** STARTING service '" + HRegionServer.class.getSimpleName() + "' *****"); + // log version VersionInfo.logVersion(); Configuration conf = HBaseConfiguration.create(); @SuppressWarnings("unchecked")