diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java index c380318..d23f87a 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/LruBlockCache.java @@ -511,7 +511,10 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize { * @return the heap size of evicted block */ protected long evictBlock(LruCachedBlock block, boolean evictedByEvictionProcess) { - map.remove(block.getCacheKey()); + boolean find = map.remove(block.getCacheKey()) != null; + if (!find) { + return 0; + } updateSizeMetrics(block, true); long val = elements.decrementAndGet(); if (LOG.isTraceEnabled()) { @@ -542,7 +545,18 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize { evictionThread.evict(); } } - + /** + * Used for testing. + */ + boolean isEvictionInProgress() { + return evictionInProgress; + } + /** + * Used for testing. + */ + long getOverhead() { + return overhead; + } /** * Eviction method. */ diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.java index d7f9aba..5806ed7 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/TestLruBlockCache.java @@ -31,6 +31,7 @@ import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.io.HeapSize; import org.apache.hadoop.hbase.io.hfile.LruBlockCache.EvictionThread; import org.apache.hadoop.hbase.util.ClassSize; +import static org.junit.Assert.fail; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -44,7 +45,34 @@ import org.junit.experimental.categories.Category; @Category({IOTests.class, SmallTests.class}) public class TestLruBlockCache { + @Test + public void testCurrentSize() throws Exception { + long maxSize = 100000; + int numBlocks = 9; + int testRuns = 10; + long blockSize = calculateBlockSizeDefault(maxSize, numBlocks); + assertTrue("calculateBlockSize appears broken.", blockSize * numBlocks <= maxSize); + LruBlockCache cache = new LruBlockCache(maxSize, blockSize); + EvictionThread evictionThread = cache.getEvictionThread(); + assertTrue(evictionThread != null); + while (!evictionThread.isEnteringRun()) { + Thread.sleep(1); + } + int blockCount = 0; + String hfileName = "hfile"; + for (int run = 0; run != testRuns; ++run) { + while (!cache.isEvictionInProgress()) { + CachedItem block = new CachedItem(hfileName, (int) blockSize, blockCount++); + boolean inMemory = Math.random() > 0.5; + cache.cacheBlock(block.cacheKey, block, inMemory, false); + } + assertEquals(true, cache.isEvictionInProgress()); + cache.evictBlocksByHfileName(hfileName); + assertEquals(0, cache.getBlockCount()); + assertEquals(cache.getOverhead(), cache.getCurrentSize()); + } + } @Test public void testBackgroundEvictionThread() throws Exception { long maxSize = 100000; @@ -785,6 +813,11 @@ public class TestLruBlockCache { BlockCacheKey cacheKey; int size; + CachedItem(String blockName, int size, int offset) { + this.cacheKey = new BlockCacheKey(blockName, offset); + this.size = size; + } + CachedItem(String blockName, int size) { this.cacheKey = new BlockCacheKey(blockName, 0); this.size = size;