From 5a7c9939cbe115c0d12d9cfe8bf9f3b3d11ac69e Mon Sep 17 00:00:00 2001 From: tedyu Date: Fri, 1 Jul 2016 09:43:39 -0700 Subject: [PATCH] HBASE-16157 The incorrect block cache count and size are caused by removing duplicate block key in the LruBlockCache (ChiaPing Tsai) --- .../hadoop/hbase/io/hfile/LruBlockCache.java | 15 ++++++++- .../hbase/io/hfile/TestLruBlockCache.java | 32 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) 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 c380318c48a..8894dcd577a 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 found = map.remove(block.getCacheKey()) != null; + if (!found) { + return 0; + } updateSizeMetrics(block, true); long val = elements.decrementAndGet(); if (LOG.isTraceEnabled()) { @@ -543,6 +546,16 @@ public class LruBlockCache implements ResizableBlockCache, HeapSize { } } + @VisibleForTesting + boolean isEvictionInProgress() { + return evictionInProgress; + } + + @VisibleForTesting + 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 d7f9aba6a91..4d0732eff80 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 @@ -44,7 +44,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 +812,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;