001/** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019package org.apache.hadoop.hbase.regionserver; 020 021import static org.apache.hadoop.hbase.HConstants.HFILE_BLOCK_CACHE_SIZE_KEY; 022 023import java.lang.management.MemoryUsage; 024import java.util.ArrayList; 025import java.util.List; 026import java.util.concurrent.atomic.AtomicLong; 027 028import org.apache.hadoop.conf.Configuration; 029import org.apache.hadoop.hbase.ChoreService; 030import org.apache.hadoop.hbase.HConstants; 031import org.apache.hadoop.hbase.ScheduledChore; 032import org.apache.hadoop.hbase.Server; 033import org.apache.yetus.audience.InterfaceAudience; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036import org.apache.hadoop.hbase.io.hfile.CacheConfig; 037import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache; 038import org.apache.hadoop.hbase.io.util.MemorySizeUtil; 039import org.apache.hadoop.util.ReflectionUtils; 040 041import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; 042 043/** 044 * Manages tuning of Heap memory using <code>HeapMemoryTuner</code>. Most part of the heap memory is 045 * split between Memstores and BlockCache. This manager helps in tuning sizes of both these 046 * dynamically, as per the R/W load on the servers. 047 */ 048@InterfaceAudience.Private 049public class HeapMemoryManager { 050 private static final Logger LOG = LoggerFactory.getLogger(HeapMemoryManager.class); 051 private static final int CONVERT_TO_PERCENTAGE = 100; 052 private static final int CLUSTER_MINIMUM_MEMORY_THRESHOLD = 053 (int) (CONVERT_TO_PERCENTAGE * HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD); 054 055 public static final String BLOCK_CACHE_SIZE_MAX_RANGE_KEY = "hfile.block.cache.size.max.range"; 056 public static final String BLOCK_CACHE_SIZE_MIN_RANGE_KEY = "hfile.block.cache.size.min.range"; 057 public static final String MEMSTORE_SIZE_MAX_RANGE_KEY = 058 "hbase.regionserver.global.memstore.size.max.range"; 059 public static final String MEMSTORE_SIZE_MIN_RANGE_KEY = 060 "hbase.regionserver.global.memstore.size.min.range"; 061 public static final String HBASE_RS_HEAP_MEMORY_TUNER_PERIOD = 062 "hbase.regionserver.heapmemory.tuner.period"; 063 public static final int HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD = 60 * 1000; 064 public static final String HBASE_RS_HEAP_MEMORY_TUNER_CLASS = 065 "hbase.regionserver.heapmemory.tuner.class"; 066 067 public static final float HEAP_OCCUPANCY_ERROR_VALUE = -0.0f; 068 069 private float globalMemStorePercent; 070 private float globalMemStorePercentMinRange; 071 private float globalMemStorePercentMaxRange; 072 073 private float blockCachePercent; 074 private float blockCachePercentMinRange; 075 private float blockCachePercentMaxRange; 076 077 private float heapOccupancyPercent; 078 079 private final ResizableBlockCache blockCache; 080 // TODO : remove this and mark regionServerAccounting as the observer directly 081 private final FlushRequester memStoreFlusher; 082 private final Server server; 083 private final RegionServerAccounting regionServerAccounting; 084 085 private HeapMemoryTunerChore heapMemTunerChore = null; 086 private final boolean tunerOn; 087 private final int defaultChorePeriod; 088 private final float heapOccupancyLowWatermark; 089 090 private final long maxHeapSize; 091 { 092 // note that this initialization still isn't threadsafe, because updating a long isn't atomic. 093 long tempMaxHeap = -1L; 094 try { 095 final MemoryUsage usage = MemorySizeUtil.safeGetHeapMemoryUsage(); 096 if (usage != null) { 097 tempMaxHeap = usage.getMax(); 098 } 099 } finally { 100 maxHeapSize = tempMaxHeap; 101 } 102 } 103 104 private MetricsHeapMemoryManager metricsHeapMemoryManager; 105 106 private List<HeapMemoryTuneObserver> tuneObservers = new ArrayList<>(); 107 108 public static HeapMemoryManager create(Configuration conf, FlushRequester memStoreFlusher, 109 Server server, RegionServerAccounting regionServerAccounting) { 110 ResizableBlockCache lruCache = CacheConfig.getOnHeapCache(conf); 111 if (lruCache != null) { 112 return new HeapMemoryManager(lruCache, memStoreFlusher, server, regionServerAccounting); 113 } 114 return null; 115 } 116 117 @VisibleForTesting 118 HeapMemoryManager(ResizableBlockCache blockCache, FlushRequester memStoreFlusher, 119 Server server, RegionServerAccounting regionServerAccounting) { 120 Configuration conf = server.getConfiguration(); 121 this.blockCache = blockCache; 122 this.memStoreFlusher = memStoreFlusher; 123 this.server = server; 124 this.regionServerAccounting = regionServerAccounting; 125 this.tunerOn = doInit(conf); 126 this.defaultChorePeriod = conf.getInt(HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 127 HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD); 128 this.heapOccupancyLowWatermark = conf.getFloat(HConstants.HEAP_OCCUPANCY_LOW_WATERMARK_KEY, 129 HConstants.DEFAULT_HEAP_OCCUPANCY_LOW_WATERMARK); 130 metricsHeapMemoryManager = new MetricsHeapMemoryManager(); 131 } 132 133 private boolean doInit(Configuration conf) { 134 boolean tuningEnabled = true; 135 globalMemStorePercent = MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, false); 136 blockCachePercent = conf.getFloat(HFILE_BLOCK_CACHE_SIZE_KEY, 137 HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT); 138 MemorySizeUtil.checkForClusterFreeHeapMemoryLimit(conf); 139 // Initialize max and min range for memstore heap space 140 globalMemStorePercentMinRange = conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, 141 globalMemStorePercent); 142 globalMemStorePercentMaxRange = conf.getFloat(MEMSTORE_SIZE_MAX_RANGE_KEY, 143 globalMemStorePercent); 144 if (globalMemStorePercent < globalMemStorePercentMinRange) { 145 LOG.warn("Setting " + MEMSTORE_SIZE_MIN_RANGE_KEY + " to " + globalMemStorePercent 146 + ", same value as " + MemorySizeUtil.MEMSTORE_SIZE_KEY 147 + " because supplied value greater than initial memstore size value."); 148 globalMemStorePercentMinRange = globalMemStorePercent; 149 conf.setFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercentMinRange); 150 } 151 if (globalMemStorePercent > globalMemStorePercentMaxRange) { 152 LOG.warn("Setting " + MEMSTORE_SIZE_MAX_RANGE_KEY + " to " + globalMemStorePercent 153 + ", same value as " + MemorySizeUtil.MEMSTORE_SIZE_KEY 154 + " because supplied value less than initial memstore size value."); 155 globalMemStorePercentMaxRange = globalMemStorePercent; 156 conf.setFloat(MEMSTORE_SIZE_MAX_RANGE_KEY, globalMemStorePercentMaxRange); 157 } 158 if (globalMemStorePercent == globalMemStorePercentMinRange 159 && globalMemStorePercent == globalMemStorePercentMaxRange) { 160 tuningEnabled = false; 161 } 162 // Initialize max and min range for block cache 163 blockCachePercentMinRange = conf.getFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercent); 164 blockCachePercentMaxRange = conf.getFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercent); 165 if (blockCachePercent < blockCachePercentMinRange) { 166 LOG.warn("Setting " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " to " + blockCachePercent 167 + ", same value as " + HFILE_BLOCK_CACHE_SIZE_KEY 168 + " because supplied value greater than initial block cache size."); 169 blockCachePercentMinRange = blockCachePercent; 170 conf.setFloat(BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercentMinRange); 171 } 172 if (blockCachePercent > blockCachePercentMaxRange) { 173 LOG.warn("Setting " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " to " + blockCachePercent 174 + ", same value as " + HFILE_BLOCK_CACHE_SIZE_KEY 175 + " because supplied value less than initial block cache size."); 176 blockCachePercentMaxRange = blockCachePercent; 177 conf.setFloat(BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercentMaxRange); 178 } 179 if (tuningEnabled && blockCachePercent == blockCachePercentMinRange 180 && blockCachePercent == blockCachePercentMaxRange) { 181 tuningEnabled = false; 182 } 183 184 int gml = (int) (globalMemStorePercentMaxRange * CONVERT_TO_PERCENTAGE); 185 int bcul = (int) ((blockCachePercentMinRange) * CONVERT_TO_PERCENTAGE); 186 if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { 187 throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds " 188 + "the threshold required for successful cluster operation. " 189 + "The combined value cannot exceed 0.8. Please check the settings for " 190 + MEMSTORE_SIZE_MAX_RANGE_KEY + " and " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY 191 + " in your configuration. " + MEMSTORE_SIZE_MAX_RANGE_KEY + " is " 192 + globalMemStorePercentMaxRange + " and " + BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " is " 193 + blockCachePercentMinRange); 194 } 195 gml = (int) (globalMemStorePercentMinRange * CONVERT_TO_PERCENTAGE); 196 bcul = (int) ((blockCachePercentMaxRange) * CONVERT_TO_PERCENTAGE); 197 if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { 198 throw new RuntimeException("Current heap configuration for MemStore and BlockCache exceeds " 199 + "the threshold required for successful cluster operation. " 200 + "The combined value cannot exceed 0.8. Please check the settings for " 201 + MEMSTORE_SIZE_MIN_RANGE_KEY + " and " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY 202 + " in your configuration. " + MEMSTORE_SIZE_MIN_RANGE_KEY + " is " 203 + globalMemStorePercentMinRange + " and " + BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " is " 204 + blockCachePercentMaxRange); 205 } 206 return tuningEnabled; 207 } 208 209 public void start(ChoreService service) { 210 LOG.info("Starting, tuneOn={}", this.tunerOn); 211 this.heapMemTunerChore = new HeapMemoryTunerChore(); 212 service.scheduleChore(heapMemTunerChore); 213 if (tunerOn) { 214 // Register HeapMemoryTuner as a memstore flush listener 215 memStoreFlusher.registerFlushRequestListener(heapMemTunerChore); 216 } 217 } 218 219 public void stop() { 220 // The thread is Daemon. Just interrupting the ongoing process. 221 LOG.info("Stopping"); 222 this.heapMemTunerChore.cancel(true); 223 } 224 225 public void registerTuneObserver(HeapMemoryTuneObserver observer) { 226 this.tuneObservers.add(observer); 227 } 228 229 // Used by the test cases. 230 boolean isTunerOn() { 231 return this.tunerOn; 232 } 233 234 /** 235 * @return heap occupancy percentage, 0 <= n <= 1. or -0.0 for error asking JVM 236 */ 237 public float getHeapOccupancyPercent() { 238 return this.heapOccupancyPercent == Float.MAX_VALUE ? HEAP_OCCUPANCY_ERROR_VALUE : this.heapOccupancyPercent; 239 } 240 241 private class HeapMemoryTunerChore extends ScheduledChore implements FlushRequestListener { 242 private HeapMemoryTuner heapMemTuner; 243 private AtomicLong blockedFlushCount = new AtomicLong(); 244 private AtomicLong unblockedFlushCount = new AtomicLong(); 245 private long evictCount = 0L; 246 private long cacheMissCount = 0L; 247 private TunerContext tunerContext = new TunerContext(); 248 private boolean alarming = false; 249 250 public HeapMemoryTunerChore() { 251 super(server.getServerName() + "-HeapMemoryTunerChore", server, defaultChorePeriod); 252 Class<? extends HeapMemoryTuner> tunerKlass = server.getConfiguration().getClass( 253 HBASE_RS_HEAP_MEMORY_TUNER_CLASS, DefaultHeapMemoryTuner.class, HeapMemoryTuner.class); 254 heapMemTuner = ReflectionUtils.newInstance(tunerKlass, server.getConfiguration()); 255 tunerContext 256 .setOffheapMemStore(regionServerAccounting.isOffheap()); 257 } 258 259 @Override 260 protected void chore() { 261 // Sample heap occupancy 262 final MemoryUsage usage = MemorySizeUtil.safeGetHeapMemoryUsage(); 263 if (usage != null) { 264 heapOccupancyPercent = (float)usage.getUsed() / (float)usage.getCommitted(); 265 } else { 266 // previously, an exception would have meant death for the tuning chore 267 // so switch to alarming so that we similarly stop tuning until we get 268 // heap usage information again. 269 heapOccupancyPercent = Float.MAX_VALUE; 270 } 271 // If we are above the heap occupancy alarm low watermark, switch to short 272 // sleeps for close monitoring. Stop autotuning, we are in a danger zone. 273 if (heapOccupancyPercent >= heapOccupancyLowWatermark) { 274 if (!alarming) { 275 LOG.warn("heapOccupancyPercent " + heapOccupancyPercent + 276 " is above heap occupancy alarm watermark (" + heapOccupancyLowWatermark + ")"); 277 alarming = true; 278 } 279 metricsHeapMemoryManager.increaseAboveHeapOccupancyLowWatermarkCounter(); 280 triggerNow(); 281 try { 282 // Need to sleep ourselves since we've told the chore's sleeper 283 // to skip the next sleep cycle. 284 Thread.sleep(1000); 285 } catch (InterruptedException e) { 286 // Interrupted, propagate 287 Thread.currentThread().interrupt(); 288 } 289 } else { 290 if (alarming) { 291 LOG.info("heapOccupancyPercent " + heapOccupancyPercent + 292 " is now below the heap occupancy alarm watermark (" + 293 heapOccupancyLowWatermark + ")"); 294 alarming = false; 295 } 296 } 297 // Autotune if tuning is enabled and allowed 298 if (tunerOn && !alarming) { 299 tune(); 300 } 301 } 302 303 private void tune() { 304 // TODO check if we can increase the memory boundaries 305 // while remaining in the limits 306 long curEvictCount; 307 long curCacheMisCount; 308 long blockedFlushCnt; 309 long unblockedFlushCnt; 310 curEvictCount = blockCache.getStats().getEvictedCount(); 311 tunerContext.setEvictCount(curEvictCount - evictCount); 312 evictCount = curEvictCount; 313 curCacheMisCount = blockCache.getStats().getMissCachingCount(); 314 tunerContext.setCacheMissCount(curCacheMisCount-cacheMissCount); 315 cacheMissCount = curCacheMisCount; 316 blockedFlushCnt = blockedFlushCount.getAndSet(0); 317 tunerContext.setBlockedFlushCount(blockedFlushCnt); 318 metricsHeapMemoryManager.updateBlockedFlushCount(blockedFlushCnt); 319 unblockedFlushCnt = unblockedFlushCount.getAndSet(0); 320 tunerContext.setUnblockedFlushCount(unblockedFlushCnt); 321 metricsHeapMemoryManager.updateUnblockedFlushCount(unblockedFlushCnt); 322 // TODO : add support for offheap metrics 323 tunerContext.setCurBlockCacheUsed((float) blockCache.getCurrentSize() / maxHeapSize); 324 metricsHeapMemoryManager.setCurBlockCacheSizeGauge(blockCache.getCurrentSize()); 325 long globalMemstoreHeapSize = regionServerAccounting.getGlobalMemStoreHeapSize(); 326 tunerContext.setCurMemStoreUsed((float) globalMemstoreHeapSize / maxHeapSize); 327 metricsHeapMemoryManager.setCurMemStoreSizeGauge(globalMemstoreHeapSize); 328 tunerContext.setCurBlockCacheSize(blockCachePercent); 329 tunerContext.setCurMemStoreSize(globalMemStorePercent); 330 TunerResult result = null; 331 try { 332 result = this.heapMemTuner.tune(tunerContext); 333 } catch (Throwable t) { 334 LOG.error("Exception thrown from the HeapMemoryTuner implementation", t); 335 } 336 if (result != null && result.needsTuning()) { 337 float memstoreSize = result.getMemStoreSize(); 338 float blockCacheSize = result.getBlockCacheSize(); 339 LOG.debug("From HeapMemoryTuner new memstoreSize: " + memstoreSize 340 + ". new blockCacheSize: " + blockCacheSize); 341 if (memstoreSize < globalMemStorePercentMinRange) { 342 LOG.info("New memstoreSize from HeapMemoryTuner " + memstoreSize + " is below min level " 343 + globalMemStorePercentMinRange + ". Resetting memstoreSize to min size"); 344 memstoreSize = globalMemStorePercentMinRange; 345 } else if (memstoreSize > globalMemStorePercentMaxRange) { 346 LOG.info("New memstoreSize from HeapMemoryTuner " + memstoreSize + " is above max level " 347 + globalMemStorePercentMaxRange + ". Resetting memstoreSize to max size"); 348 memstoreSize = globalMemStorePercentMaxRange; 349 } 350 if (blockCacheSize < blockCachePercentMinRange) { 351 LOG.info("New blockCacheSize from HeapMemoryTuner " + blockCacheSize 352 + " is below min level " + blockCachePercentMinRange 353 + ". Resetting blockCacheSize to min size"); 354 blockCacheSize = blockCachePercentMinRange; 355 } else if (blockCacheSize > blockCachePercentMaxRange) { 356 LOG.info("New blockCacheSize from HeapMemoryTuner " + blockCacheSize 357 + " is above max level " + blockCachePercentMaxRange 358 + ". Resetting blockCacheSize to min size"); 359 blockCacheSize = blockCachePercentMaxRange; 360 } 361 int gml = (int) (memstoreSize * CONVERT_TO_PERCENTAGE); 362 int bcul = (int) ((blockCacheSize) * CONVERT_TO_PERCENTAGE); 363 if (CONVERT_TO_PERCENTAGE - (gml + bcul) < CLUSTER_MINIMUM_MEMORY_THRESHOLD) { 364 LOG.info("Current heap configuration from HeapMemoryTuner exceeds " 365 + "the threshold required for successful cluster operation. " 366 + "The combined value cannot exceed 0.8. " + MemorySizeUtil.MEMSTORE_SIZE_KEY 367 + " is " + memstoreSize + " and " + HFILE_BLOCK_CACHE_SIZE_KEY + " is " 368 + blockCacheSize); 369 // TODO can adjust the value so as not exceed 80%. Is that correct? may be. 370 } else { 371 int memStoreDeltaSize = 372 (int) ((memstoreSize - globalMemStorePercent) * CONVERT_TO_PERCENTAGE); 373 int blockCacheDeltaSize = 374 (int) ((blockCacheSize - blockCachePercent) * CONVERT_TO_PERCENTAGE); 375 metricsHeapMemoryManager.updateMemStoreDeltaSizeHistogram(memStoreDeltaSize); 376 metricsHeapMemoryManager.updateBlockCacheDeltaSizeHistogram(blockCacheDeltaSize); 377 long newBlockCacheSize = (long) (maxHeapSize * blockCacheSize); 378 // we could have got an increase or decrease in size for the offheap memstore 379 // also if the flush had happened due to heap overhead. In that case it is ok 380 // to adjust the onheap memstore limit configs 381 long newMemstoreSize = (long) (maxHeapSize * memstoreSize); 382 LOG.info("Setting block cache heap size to " + newBlockCacheSize 383 + " and memstore heap size to " + newMemstoreSize); 384 blockCachePercent = blockCacheSize; 385 blockCache.setMaxSize(newBlockCacheSize); 386 globalMemStorePercent = memstoreSize; 387 // Internally sets it to RegionServerAccounting 388 // TODO : Set directly on RSAccounting?? 389 memStoreFlusher.setGlobalMemStoreLimit(newMemstoreSize); 390 for (HeapMemoryTuneObserver observer : tuneObservers) { 391 // Risky.. If this newMemstoreSize decreases we reduce the count in offheap chunk pool 392 observer.onHeapMemoryTune(newMemstoreSize, newBlockCacheSize); 393 } 394 } 395 } else { 396 metricsHeapMemoryManager.increaseTunerDoNothingCounter(); 397 if (LOG.isDebugEnabled()) { 398 LOG.debug("No changes made by HeapMemoryTuner."); 399 } 400 } 401 } 402 403 @Override 404 public void flushRequested(FlushType type, Region region) { 405 switch (type) { 406 case ABOVE_ONHEAP_HIGHER_MARK: 407 blockedFlushCount.incrementAndGet(); 408 break; 409 case ABOVE_ONHEAP_LOWER_MARK: 410 unblockedFlushCount.incrementAndGet(); 411 break; 412 // Removed the counting of the offheap related flushes (after reviews). Will add later if 413 // needed 414 default: 415 // In case of any other flush don't do any action. 416 break; 417 } 418 } 419 } 420 421 /** 422 * POJO to pass all the relevant information required to do the heap memory tuning. It holds the 423 * flush counts and block cache evictions happened within the interval. Also holds the current 424 * heap percentage allocated for memstore and block cache. 425 */ 426 public static final class TunerContext { 427 private long blockedFlushCount; 428 private long unblockedFlushCount; 429 private long evictCount; 430 private long cacheMissCount; 431 private float curBlockCacheUsed; 432 private float curMemStoreUsed; 433 private float curMemStoreSize; 434 private float curBlockCacheSize; 435 private boolean offheapMemstore; 436 437 public long getBlockedFlushCount() { 438 return blockedFlushCount; 439 } 440 441 public void setBlockedFlushCount(long blockedFlushCount) { 442 this.blockedFlushCount = blockedFlushCount; 443 } 444 445 public long getUnblockedFlushCount() { 446 return unblockedFlushCount; 447 } 448 449 public void setUnblockedFlushCount(long unblockedFlushCount) { 450 this.unblockedFlushCount = unblockedFlushCount; 451 } 452 453 public long getEvictCount() { 454 return evictCount; 455 } 456 457 public void setEvictCount(long evictCount) { 458 this.evictCount = evictCount; 459 } 460 461 public float getCurMemStoreSize() { 462 return curMemStoreSize; 463 } 464 465 public void setCurMemStoreSize(float curMemStoreSize) { 466 this.curMemStoreSize = curMemStoreSize; 467 } 468 469 public float getCurBlockCacheSize() { 470 return curBlockCacheSize; 471 } 472 473 public void setCurBlockCacheSize(float curBlockCacheSize) { 474 this.curBlockCacheSize = curBlockCacheSize; 475 } 476 477 public long getCacheMissCount() { 478 return cacheMissCount; 479 } 480 481 public void setCacheMissCount(long cacheMissCount) { 482 this.cacheMissCount = cacheMissCount; 483 } 484 485 public float getCurBlockCacheUsed() { 486 return curBlockCacheUsed; 487 } 488 489 public void setCurBlockCacheUsed(float curBlockCacheUsed) { 490 this.curBlockCacheUsed = curBlockCacheUsed; 491 } 492 493 public float getCurMemStoreUsed() { 494 return curMemStoreUsed; 495 } 496 497 public void setCurMemStoreUsed(float d) { 498 this.curMemStoreUsed = d; 499 } 500 501 public void setOffheapMemStore(boolean offheapMemstore) { 502 this.offheapMemstore = offheapMemstore; 503 } 504 505 public boolean isOffheapMemStore() { 506 return this.offheapMemstore; 507 } 508 } 509 510 /** 511 * POJO which holds the result of memory tuning done by HeapMemoryTuner implementation. 512 * It includes the new heap percentage for memstore and block cache. 513 */ 514 public static final class TunerResult { 515 private float memstoreSize; 516 private float blockCacheSize; 517 private final boolean needsTuning; 518 519 public TunerResult(boolean needsTuning) { 520 this.needsTuning = needsTuning; 521 } 522 523 public float getMemStoreSize() { 524 return memstoreSize; 525 } 526 527 public void setMemStoreSize(float memstoreSize) { 528 this.memstoreSize = memstoreSize; 529 } 530 531 public float getBlockCacheSize() { 532 return blockCacheSize; 533 } 534 535 public void setBlockCacheSize(float blockCacheSize) { 536 this.blockCacheSize = blockCacheSize; 537 } 538 539 public boolean needsTuning() { 540 return needsTuning; 541 } 542 } 543 544 /** 545 * Every class that wants to observe heap memory tune actions must implement this interface. 546 */ 547 public static interface HeapMemoryTuneObserver { 548 549 /** 550 * This method would be called by HeapMemoryManger when a heap memory tune action took place. 551 * @param newMemstoreSize The newly calculated global memstore size 552 * @param newBlockCacheSize The newly calculated global blockcache size 553 */ 554 void onHeapMemoryTune(long newMemstoreSize, long newBlockCacheSize); 555 } 556}