diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.java index 5e97b80..1472b81 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.java @@ -45,6 +45,7 @@ class DefaultHeapMemoryTuner implements HeapMemoryTuner { public static final String STEP_KEY = "hbase.regionserver.heapmemory.autotuner.step"; public static final float DEFAULT_STEP_VALUE = 0.02f; // 2% + public static final float tolerance = 0.00f; private static final TunerResult TUNER_RESULT = new TunerResult(true); private static final TunerResult NO_OP_TUNER_RESULT = new TunerResult(false); @@ -57,30 +58,70 @@ class DefaultHeapMemoryTuner implements HeapMemoryTuner { private float blockCachePercentMinRange; private float blockCachePercentMaxRange; + private boolean stepDirectionIndicator; // true if last time tuner increased block cache size + private boolean isFirstTuning = true; + private long prevFlushCount = 0; + private long prevEvictCount = 0; + private long prevCacheMissCount = 0; + @Override public TunerResult tune(TunerContext context) { long blockedFlushCount = context.getBlockedFlushCount(); long unblockedFlushCount = context.getUnblockedFlushCount(); long evictCount = context.getEvictCount(); - boolean memstoreSufficient = blockedFlushCount == 0 && unblockedFlushCount == 0; - boolean blockCacheSufficient = evictCount == 0; + long cacheMissCount = context.getCacheMissCount(); + // We can consider memstore or block cache to be sufficient if + // we are using less than half of what have been already provided + boolean memstoreSufficient = (blockedFlushCount == 0 && unblockedFlushCount == 0) + || context.getCurMemStoreUsed()*2 < context.getCurMemStoreSize(); + boolean blockCacheSufficient = evictCount == 0 || + context.getCurBlockCacheUsed()*2 < context.getCurBlockCacheSize(); if (memstoreSufficient && blockCacheSufficient) { + prevFlushCount = blockedFlushCount + unblockedFlushCount; + prevEvictCount = evictCount; + prevCacheMissCount = cacheMissCount; return NO_OP_TUNER_RESULT; } float newMemstoreSize; float newBlockCacheSize; if (memstoreSufficient) { // Increase the block cache size and corresponding decrease in memstore size - newBlockCacheSize = context.getCurBlockCacheSize() + step; - newMemstoreSize = context.getCurMemStoreSize() - step; + stepDirectionIndicator = true; } else if (blockCacheSufficient) { // Increase the memstore size and corresponding decrease in block cache size - newBlockCacheSize = context.getCurBlockCacheSize() - step; - newMemstoreSize = context.getCurMemStoreSize() + step; + stepDirectionIndicator = false; } else { - return NO_OP_TUNER_RESULT; - // As of now not making any tuning in write/read heavy scenario. + float percentChangeInEvictCount = (float)(evictCount-prevEvictCount)/(float)(evictCount); + float percentChangeInFlushes = (float)(blockedFlushCount + unblockedFlushCount - + prevFlushCount)/(float)(blockedFlushCount + unblockedFlushCount); + float percentChangeInMisses = (float)(cacheMissCount-prevCacheMissCount) + /(float)(cacheMissCount); + if (!isFirstTuning) { + // Negative percent changes are desirable + // if it is positive , we should revert the previous step + if (percentChangeInEvictCount + percentChangeInFlushes > tolerance) { + // revert last step as it was not useful + stepDirectionIndicator = !stepDirectionIndicator; + } else { + // last step was useful, taking step based on current stats + if (cacheMissCount == 0) { + stepDirectionIndicator = false; + } else { + // try to balance changes in number of cache misses and flushes + stepDirectionIndicator = percentChangeInMisses > percentChangeInFlushes; + } + } + } else { + stepDirectionIndicator = percentChangeInMisses > percentChangeInFlushes; + } } + if (stepDirectionIndicator) { + newBlockCacheSize = context.getCurBlockCacheSize() + step; + newMemstoreSize = context.getCurMemStoreSize() - step; + } else { + newBlockCacheSize = context.getCurBlockCacheSize() - step; + newMemstoreSize = context.getCurMemStoreSize() + step; + } if (newMemstoreSize > globalMemStorePercentMaxRange) { newMemstoreSize = globalMemStorePercentMaxRange; } else if (newMemstoreSize < globalMemStorePercentMinRange) { @@ -93,6 +134,10 @@ class DefaultHeapMemoryTuner implements HeapMemoryTuner { } TUNER_RESULT.setBlockCacheSize(newBlockCacheSize); TUNER_RESULT.setMemstoreSize(newMemstoreSize); + prevFlushCount = blockedFlushCount + unblockedFlushCount; + prevEvictCount = evictCount; + prevCacheMissCount = cacheMissCount; + isFirstTuning = false; return TUNER_RESULT; } 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 fb998ea..de3e347 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 @@ -1378,7 +1378,8 @@ public class HRegionServer extends HasThread implements } private void startHeapMemoryManager() { - this.hMemManager = HeapMemoryManager.create(this.conf, this.cacheFlusher, this); + this.hMemManager = HeapMemoryManager.create(this.conf, this.cacheFlusher, + this, this.regionServerAccounting); if (this.hMemManager != null) { this.hMemManager.start(getChoreService()); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java index 5448025..5272ebf 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HeapMemoryManager.java @@ -76,6 +76,7 @@ public class HeapMemoryManager { private final ResizableBlockCache blockCache; private final FlushRequester memStoreFlusher; private final Server server; + private final RegionServerAccounting regionServerAccounting; private HeapMemoryTunerChore heapMemTunerChore = null; private final boolean tunerOn; @@ -85,21 +86,23 @@ public class HeapMemoryManager { private long maxHeapSize = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax(); public static HeapMemoryManager create(Configuration conf, FlushRequester memStoreFlusher, - Server server) { + Server server, RegionServerAccounting regionServerAccounting) { BlockCache blockCache = CacheConfig.instantiateBlockCache(conf); if (blockCache instanceof ResizableBlockCache) { - return new HeapMemoryManager((ResizableBlockCache) blockCache, memStoreFlusher, server); + return new HeapMemoryManager((ResizableBlockCache) blockCache, memStoreFlusher, server, + regionServerAccounting); } return null; } @VisibleForTesting HeapMemoryManager(ResizableBlockCache blockCache, FlushRequester memStoreFlusher, - Server server) { + Server server, RegionServerAccounting regionServerAccounting) { Configuration conf = server.getConfiguration(); this.blockCache = blockCache; this.memStoreFlusher = memStoreFlusher; this.server = server; + this.regionServerAccounting = regionServerAccounting; this.tunerOn = doInit(conf); this.defaultChorePeriod = conf.getInt(HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD); @@ -217,6 +220,7 @@ public class HeapMemoryManager { private AtomicLong blockedFlushCount = new AtomicLong(); private AtomicLong unblockedFlushCount = new AtomicLong(); private long evictCount = 0L; + private long cacheMissCount = 0L; private TunerContext tunerContext = new TunerContext(); private boolean alarming = false; @@ -264,11 +268,21 @@ public class HeapMemoryManager { } private void tune() { - long curEvictCount = blockCache.getStats().getEvictedCount(); + // TODO check if we can increase the memory boundaries + // while remaining in the limits + long curEvictCount; + long curCacheMisCount; + curEvictCount = blockCache.getStats().getEvictedCount(); tunerContext.setEvictCount(curEvictCount - evictCount); evictCount = curEvictCount; + curCacheMisCount = blockCache.getStats().getMissCachingCount(); + tunerContext.setCacheMissCount(curCacheMisCount-cacheMissCount); + cacheMissCount = curCacheMisCount; tunerContext.setBlockedFlushCount(blockedFlushCount.getAndSet(0)); tunerContext.setUnblockedFlushCount(unblockedFlushCount.getAndSet(0)); + tunerContext.setCurBlockCacheUsed((float)blockCache.getCurrentSize() / maxHeapSize); + tunerContext.setCurMemStoreUsed( + (float)regionServerAccounting.getGlobalMemstoreSize() / maxHeapSize); tunerContext.setCurBlockCacheSize(blockCachePercent); tunerContext.setCurMemStoreSize(globalMemStorePercent); TunerResult result = null; @@ -321,6 +335,8 @@ public class HeapMemoryManager { globalMemStorePercent = memstoreSize; memStoreFlusher.setGlobalMemstoreLimit(newMemstoreSize); } + } else { + LOG.info("No changes made by HeapMemoryTuner."); } } @@ -349,6 +365,9 @@ public class HeapMemoryManager { private long blockedFlushCount; private long unblockedFlushCount; private long evictCount; + private long cacheMissCount; + private float curBlockCacheUsed; + private float curMemStoreUsed; private float curMemStoreSize; private float curBlockCacheSize; @@ -391,6 +410,30 @@ public class HeapMemoryManager { public void setCurBlockCacheSize(float curBlockCacheSize) { this.curBlockCacheSize = curBlockCacheSize; } + + public long getCacheMissCount() { + return cacheMissCount; + } + + public void setCacheMissCount(long cacheMissCount) { + this.cacheMissCount = cacheMissCount; + } + + public float getCurBlockCacheUsed() { + return curBlockCacheUsed; + } + + public void setCurBlockCacheUsed(float curBlockCacheUsed) { + this.curBlockCacheUsed = curBlockCacheUsed; + } + + public float getCurMemStoreUsed() { + return curMemStoreUsed; + } + + public void setCurMemStoreUsed(float d) { + this.curMemStoreUsed = d; + } } /** diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.java index 2965071..f89df1c 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHeapMemoryManager.java @@ -61,7 +61,7 @@ public class TestHeapMemoryManager { conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.75f); conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f); HeapMemoryManager manager = new HeapMemoryManager(new BlockCacheStub(0), - new MemstoreFlusherStub(0), new RegionServerStub(conf)); + new MemstoreFlusherStub(0), new RegionServerStub(conf), new RegionServerAccountingStub()); assertFalse(manager.isTunerOn()); } @@ -71,7 +71,7 @@ public class TestHeapMemoryManager { conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.05f); HeapMemoryManager manager = new HeapMemoryManager(new BlockCacheStub(0), - new MemstoreFlusherStub(0), new RegionServerStub(conf)); + new MemstoreFlusherStub(0), new RegionServerStub(conf), new RegionServerAccountingStub()); assertFalse(manager.isTunerOn()); } @@ -83,7 +83,8 @@ public class TestHeapMemoryManager { conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.06f); try { - new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(conf)); + new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), new RegionServerAccountingStub()); fail(); } catch (RuntimeException e) { } @@ -91,16 +92,84 @@ public class TestHeapMemoryManager { conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.2f); conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f); try { - new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub(conf)); + new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), new RegionServerAccountingStub()); fail(); } catch (RuntimeException e) { } } + + @Test + public void testWhenClusterIsWriteHeavyWithEmptyMemstore() throws Exception { + BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4)); + MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4)); + RegionServerAccountingStub regionServerAccounting = new RegionServerAccountingStub(); + // Empty block cache and memstore + blockCache.setTestBlockSize(0); + regionServerAccounting.setTestMemstoreSize(0); + Configuration conf = HBaseConfiguration.create(); + conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); + conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f); + conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f); + conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f); + conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000); + // Let the system start with default values for memstore heap and block cache size. + HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), regionServerAccounting); + long oldMemstoreHeapSize = memStoreFlusher.memstoreSize; + long oldBlockCacheSize = blockCache.maxSize; + final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); + heapMemoryManager.start(choreService); + memStoreFlusher.flushType = FlushType.ABOVE_HIGHER_MARK; + memStoreFlusher.requestFlush(null, false); + memStoreFlusher.requestFlush(null, false); + memStoreFlusher.requestFlush(null, false); + memStoreFlusher.flushType = FlushType.ABOVE_LOWER_MARK; + memStoreFlusher.requestFlush(null, false); + Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up + // No changes should be made by tuner as we already have lot of empty space + assertEquals(oldMemstoreHeapSize, memStoreFlusher.memstoreSize); + assertEquals(oldBlockCacheSize, blockCache.maxSize); + } @Test + public void testWhenClusterIsReadHeavyWithEmptyBlockCache() throws Exception { + BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4)); + MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4)); + RegionServerAccountingStub regionServerAccounting = new RegionServerAccountingStub(); + // Empty block cache and memstore + blockCache.setTestBlockSize(0); + regionServerAccounting.setTestMemstoreSize(0); + Configuration conf = HBaseConfiguration.create(); + conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); + conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f); + conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.7f); + conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MIN_RANGE_KEY, 0.05f); + conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000); + // Let the system start with default values for memstore heap and block cache size. + HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), regionServerAccounting); + long oldMemstoreHeapSize = memStoreFlusher.memstoreSize; + long oldBlockCacheSize = blockCache.maxSize; + final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); + heapMemoryManager.start(choreService); + blockCache.evictBlock(null); + blockCache.evictBlock(null); + blockCache.evictBlock(null); + Thread.sleep(1500); // Allow the tuner to run once and do necessary memory up + // No changes should be made by tuner as we already have lot of empty space + assertEquals(oldMemstoreHeapSize, memStoreFlusher.memstoreSize); + assertEquals(oldBlockCacheSize, blockCache.maxSize); + } + + @Test public void testWhenClusterIsWriteHeavy() throws Exception { BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4)); MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4)); + RegionServerAccountingStub regionServerAccounting = new RegionServerAccountingStub(); + // Empty block cache and but nearly filled memstore + blockCache.setTestBlockSize(0); + regionServerAccounting.setTestMemstoreSize((long) (maxHeapSize * 0.4 * 0.8)); Configuration conf = HBaseConfiguration.create(); conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f); @@ -109,7 +178,7 @@ public class TestHeapMemoryManager { conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000); // Let the system start with default values for memstore heap and block cache size. HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, - new RegionServerStub(conf)); + new RegionServerStub(conf), regionServerAccounting); long oldMemstoreHeapSize = memStoreFlusher.memstoreSize; long oldBlockCacheSize = blockCache.maxSize; final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); @@ -142,6 +211,10 @@ public class TestHeapMemoryManager { public void testWhenClusterIsReadHeavy() throws Exception { BlockCacheStub blockCache = new BlockCacheStub((long) (maxHeapSize * 0.4)); MemstoreFlusherStub memStoreFlusher = new MemstoreFlusherStub((long) (maxHeapSize * 0.4)); + RegionServerAccountingStub regionServerAccounting = new RegionServerAccountingStub(); + // Empty memstore and but nearly filled block cache + blockCache.setTestBlockSize((long) (maxHeapSize * 0.4 * 0.8)); + regionServerAccounting.setTestMemstoreSize(0); Configuration conf = HBaseConfiguration.create(); conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.75f); conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MIN_RANGE_KEY, 0.10f); @@ -150,7 +223,7 @@ public class TestHeapMemoryManager { conf.setLong(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 1000); // Let the system start with default values for memstore heap and block cache size. HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, - new RegionServerStub(conf)); + new RegionServerStub(conf), new RegionServerAccountingStub()); long oldMemstoreHeapSize = memStoreFlusher.memstoreSize; long oldBlockCacheSize = blockCache.maxSize; final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); @@ -188,7 +261,7 @@ public class TestHeapMemoryManager { HeapMemoryTuner.class); // Let the system start with default values for memstore heap and block cache size. HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, - new RegionServerStub(conf)); + new RegionServerStub(conf), new RegionServerAccountingStub()); final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); heapMemoryManager.start(choreService); // Now we wants to be in write mode. Set bigger memstore size from CustomHeapMemoryTuner @@ -218,7 +291,7 @@ public class TestHeapMemoryManager { conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class, HeapMemoryTuner.class); HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, - new RegionServerStub(conf)); + new RegionServerStub(conf), new RegionServerAccountingStub()); final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); heapMemoryManager.start(choreService); CustomHeapMemoryTuner.memstoreSize = 0.78f; @@ -243,7 +316,7 @@ public class TestHeapMemoryManager { conf.setClass(HeapMemoryManager.HBASE_RS_HEAP_MEMORY_TUNER_CLASS, CustomHeapMemoryTuner.class, HeapMemoryTuner.class); HeapMemoryManager heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, - new RegionServerStub(conf)); + new RegionServerStub(conf), new RegionServerAccountingStub()); long oldMemstoreSize = memStoreFlusher.memstoreSize; long oldBlockCacheSize = blockCache.maxSize; final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); @@ -276,8 +349,8 @@ public class TestHeapMemoryManager { HeapMemoryTuner.class); try { - heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub( - conf)); + heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), new RegionServerAccountingStub()); fail("Should have failed as the collective heap memory need is above 80%"); } catch (Exception e) { } @@ -285,8 +358,8 @@ public class TestHeapMemoryManager { // Change the max/min ranges for memstore and bock cache so as to pass the criteria check conf.setFloat(HeapMemoryManager.MEMSTORE_SIZE_MAX_RANGE_KEY, 0.6f); conf.setFloat(HeapMemoryManager.BLOCK_CACHE_SIZE_MAX_RANGE_KEY, 0.6f); - heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, new RegionServerStub( - conf)); + heapMemoryManager = new HeapMemoryManager(blockCache, memStoreFlusher, + new RegionServerStub(conf), new RegionServerAccountingStub()); long oldMemstoreSize = memStoreFlusher.memstoreSize; long oldBlockCacheSize = blockCache.maxSize; final ChoreService choreService = new ChoreService("TEST_SERVER_NAME"); @@ -322,6 +395,7 @@ public class TestHeapMemoryManager { private static class BlockCacheStub implements ResizableBlockCache { CacheStats stats = new CacheStats("test"); long maxSize = 0; + private long testBlockSize = 0; public BlockCacheStub(long size){ this.maxSize = size; @@ -378,7 +452,7 @@ public class TestHeapMemoryManager { @Override public long getCurrentSize() { - return 0; + return this.testBlockSize; } @Override @@ -400,6 +474,10 @@ public class TestHeapMemoryManager { public BlockCache[] getBlockCaches() { return null; } + + public void setTestBlockSize(long testBlockSize) { + this.testBlockSize = testBlockSize; + } } private static class MemstoreFlusherStub implements FlushRequester { @@ -526,4 +604,15 @@ public class TestHeapMemoryManager { return result; } } + + private static class RegionServerAccountingStub extends RegionServerAccounting { + private long testMemstoreSize = 0; + @Override + public long getGlobalMemstoreSize() { + return testMemstoreSize; + } + public void setTestMemstoreSize(long testMemstoreSize) { + this.testMemstoreSize = testMemstoreSize; + } + } }