This is an automated email from the ASF dual-hosted git repository.

junegunn pushed a commit to branch branch-3
in repository https://gitbox.apache.org/repos/asf/hbase.git


The following commit(s) were added to refs/heads/branch-3 by this push:
     new 5a80d4ebaf6 HBASE-15625 Make minimum free heap memory percentage 
configurable (#7076)
5a80d4ebaf6 is described below

commit 5a80d4ebaf6d82480901b3511e87e8ba7cdf2600
Author: JinHyuk Kim <[email protected]>
AuthorDate: Wed Jul 30 10:05:07 2025 +0900

    HBASE-15625 Make minimum free heap memory percentage configurable (#7076)
    
    Signed-off-by: Junegunn Choi <[email protected]>
---
 .../java/org/apache/hadoop/hbase/HConstants.java   |  3 +-
 hbase-common/src/main/resources/hbase-default.xml  |  9 +++
 .../hadoop/hbase/io/util/MemorySizeUtil.java       | 91 ++++++++++++++++------
 .../hadoop/hbase/regionserver/HRegionServer.java   |  2 +-
 .../hbase/regionserver/HeapMemoryManager.java      | 73 +++++++++--------
 .../hadoop/hbase/io/util/TestMemorySizeUtil.java   | 89 +++++++++++++++++++++
 6 files changed, 208 insertions(+), 59 deletions(-)

diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java 
b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
index eba3eb657ea..29def997818 100644
--- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
+++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java
@@ -1041,7 +1041,8 @@ public final class HConstants {
   public static final boolean HFILE_PREAD_ALL_BYTES_ENABLED_DEFAULT = false;
 
   /*
-   * Minimum percentage of free heap necessary for a successful cluster 
startup.
+   * Default minimum fraction (20%) of free heap required for RegionServer 
startup, used only when
+   * 'hbase.regionserver.free.heap.min.memory.size' is not explicitly set.
    */
   public static final float HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD = 0.2f;
 
diff --git a/hbase-common/src/main/resources/hbase-default.xml 
b/hbase-common/src/main/resources/hbase-default.xml
index ccb1b28f870..ab700587ffa 100644
--- a/hbase-common/src/main/resources/hbase-default.xml
+++ b/hbase-common/src/main/resources/hbase-default.xml
@@ -278,6 +278,15 @@ possible configurations would overwhelm and obscure the 
important.
     log rolling.  Even a small value (2 or 3) will allow a region server
     to ride over transient HDFS errors.</description>
   </property>
+  <property>
+    <name>hbase.regionserver.free.heap.min.memory.size</name>
+    <value></value>
+    <description>Defines the minimum amount of heap memory that must remain 
free for the RegionServer to start,
+      specified in bytes or human-readable formats like '512m' for megabytes 
or '4g' for gigabytes.
+      If not set, the default is 20% of the total heap size. To disable the 
check entirely,
+      set this value to 0. If the combined memory usage of memstore and block 
cache
+      exceeds (total heap - this value), the RegionServer will fail to 
start.</description>
+  </property>
   <property>
     <name>hbase.regionserver.global.memstore.size</name>
     <value></value>
diff --git 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/util/MemorySizeUtil.java
 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/util/MemorySizeUtil.java
index fdeef4e5839..7ada303d293 100644
--- 
a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/util/MemorySizeUtil.java
+++ 
b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/util/MemorySizeUtil.java
@@ -51,9 +51,14 @@ public class MemorySizeUtil {
   // Default lower water mark limit is 95% size of memstore size.
   public static final float DEFAULT_MEMSTORE_SIZE_LOWER_LIMIT = 0.95f;
 
+  /**
+   * Configuration key for the absolute amount of heap memory that must remain 
free for a
+   * RegionServer to start
+   */
+  public static final String HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY 
=
+    "hbase.regionserver.free.heap.min.memory.size";
+
   private static final Logger LOG = 
LoggerFactory.getLogger(MemorySizeUtil.class);
-  // a constant to convert a fraction to a percentage
-  private static final int CONVERT_TO_PERCENTAGE = 100;
 
   private static final String JVM_HEAP_EXCEPTION = "Got an exception while 
attempting to read "
     + "information about the JVM heap. Please submit this log information in a 
bug report and "
@@ -77,34 +82,70 @@ public class MemorySizeUtil {
   }
 
   /**
-   * Checks whether we have enough heap memory left out after portion for 
Memstore and Block cache.
-   * We need atleast 20% of heap left out for other RS functions.
+   * Validates that heap allocations for MemStore and block cache do not 
exceed the allowed limit,
+   * ensuring enough free heap remains for other RegionServer tasks.
+   * @param conf the configuration to validate
+   * @throws RuntimeException if the combined allocation exceeds the threshold
    */
-  public static void checkForClusterFreeHeapMemoryLimit(Configuration conf) {
+  public static void validateRegionServerHeapMemoryAllocation(Configuration 
conf) {
     if (conf.get(MEMSTORE_SIZE_OLD_KEY) != null) {
       LOG.warn(MEMSTORE_SIZE_OLD_KEY + " is deprecated by " + 
MEMSTORE_SIZE_KEY);
     }
-    float globalMemstoreSize = getGlobalMemStoreHeapPercent(conf, false);
-    int gml = (int) (globalMemstoreSize * CONVERT_TO_PERCENTAGE);
-    float blockCacheUpperLimit = getBlockCacheHeapPercent(conf);
-    int bcul = (int) (blockCacheUpperLimit * CONVERT_TO_PERCENTAGE);
-    if (
-      CONVERT_TO_PERCENTAGE - (gml + bcul)
-          < (int) (CONVERT_TO_PERCENTAGE * 
HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD)
-    ) {
-      throw new RuntimeException("Current heap configuration for MemStore and 
BlockCache exceeds "
-        + "the threshold required for successful cluster operation. "
-        + "The combined value cannot exceed 0.8. Please check " + "the 
settings for "
-        + MEMSTORE_SIZE_KEY + " and either " + 
HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + " or "
-        + HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + " in your configuration. " + 
MEMSTORE_SIZE_KEY
-        + "=" + globalMemstoreSize + ", " + 
HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + "="
-        + conf.get(HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY) + ", "
-        + HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + "="
-        + conf.get(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY) + ". (Note: If both "
-        + HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + " and "
-        + HConstants.HFILE_BLOCK_CACHE_SIZE_KEY + " are set, " + "the system 
will use "
-        + HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY + ")");
+    float memStoreFraction = getGlobalMemStoreHeapPercent(conf, false);
+    float blockCacheFraction = getBlockCacheHeapPercent(conf);
+    float minFreeHeapFraction = getRegionServerMinFreeHeapFraction(conf);
+
+    int memStorePercent = (int) (memStoreFraction * 100);
+    int blockCachePercent = (int) (blockCacheFraction * 100);
+    int minFreeHeapPercent = (int) (minFreeHeapFraction * 100);
+    int usedPercent = memStorePercent + blockCachePercent;
+    int maxAllowedUsed = 100 - minFreeHeapPercent;
+
+    if (usedPercent > maxAllowedUsed) {
+      throw new RuntimeException(String.format(
+        "RegionServer heap memory allocation is invalid: total memory usage 
exceeds 100%% "
+          + "(memStore + blockCache + requiredFreeHeap). "
+          + "Check the following configuration values:%n" + "  - %s = %.2f%n" 
+ "  - %s = %s%n"
+          + "  - %s = %s%n" + "  - %s = %s",
+        MEMSTORE_SIZE_KEY, memStoreFraction, 
HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY,
+        conf.get(HConstants.HFILE_BLOCK_CACHE_MEMORY_SIZE_KEY),
+        HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 
conf.get(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY),
+        HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY,
+        conf.get(HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY)));
+    }
+  }
+
+  /**
+   * Retrieve an explicit minimum required free heap size in bytes in the 
configuration.
+   * @param conf used to read configs
+   * @return the minimum required free heap size in bytes, or a negative value 
if not configured.
+   * @throws IllegalArgumentException if 
HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY format is
+   *                                  invalid
+   */
+  private static long getRegionServerMinFreeHeapInBytes(Configuration conf) {
+    final String key = HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY;
+    try {
+      return Long.parseLong(conf.get(key));
+    } catch (NumberFormatException e) {
+      return (long) conf.getStorageSize(key, -1, StorageUnit.BYTES);
+    }
+  }
+
+  /**
+   * Returns the minimum required free heap as a fraction of total heap.
+   */
+  public static float getRegionServerMinFreeHeapFraction(final Configuration 
conf) {
+    final MemoryUsage usage = safeGetHeapMemoryUsage();
+    if (usage == null) {
+      return 0;
+    }
+
+    long minFreeHeapInBytes = getRegionServerMinFreeHeapInBytes(conf);
+    if (minFreeHeapInBytes >= 0) {
+      return (float) minFreeHeapInBytes / usage.getMax();
     }
+
+    return HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD;
   }
 
   /**
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 ae170ccad2a..2bddf7f9d27 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
@@ -510,7 +510,7 @@ public class HRegionServer extends 
HBaseServerBase<RSRpcServices>
     try (Scope ignored = span.makeCurrent()) {
       this.dataFsOk = true;
       this.masterless = !clusterMode();
-      MemorySizeUtil.checkForClusterFreeHeapMemoryLimit(this.conf);
+      MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
       HFile.checkHFileVersion(this.conf);
       checkCodecs(this.conf);
       FSUtils.setupShortCircuitRead(this.conf);
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 1b28846efad..9c4cd5b3ca4 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
@@ -47,8 +47,6 @@ import org.slf4j.LoggerFactory;
 public class HeapMemoryManager {
   private static final Logger LOG = 
LoggerFactory.getLogger(HeapMemoryManager.class);
   private static final int CONVERT_TO_PERCENTAGE = 100;
-  private static final int CLUSTER_MINIMUM_MEMORY_THRESHOLD =
-    (int) (CONVERT_TO_PERCENTAGE * 
HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD);
 
   public static final String BLOCK_CACHE_SIZE_MAX_RANGE_KEY = 
"hfile.block.cache.size.max.range";
   public static final String BLOCK_CACHE_SIZE_MIN_RANGE_KEY = 
"hfile.block.cache.size.min.range";
@@ -84,6 +82,7 @@ public class HeapMemoryManager {
   private final boolean tunerOn;
   private final int defaultChorePeriod;
   private final float heapOccupancyLowWatermark;
+  private final float minFreeHeapFraction;
 
   private final long maxHeapSize;
   {
@@ -110,6 +109,7 @@ public class HeapMemoryManager {
     this.memStoreFlusher = memStoreFlusher;
     this.server = server;
     this.regionServerAccounting = regionServerAccounting;
+    this.minFreeHeapFraction = 
MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf);
     this.tunerOn = doInit(conf);
     this.defaultChorePeriod =
       conf.getInt(HBASE_RS_HEAP_MEMORY_TUNER_PERIOD, 
HBASE_RS_HEAP_MEMORY_TUNER_DEFAULT_PERIOD);
@@ -130,7 +130,7 @@ public class HeapMemoryManager {
     boolean tuningEnabled = true;
     globalMemStorePercent = MemorySizeUtil.getGlobalMemStoreHeapPercent(conf, 
false);
     blockCachePercent = MemorySizeUtil.getBlockCacheHeapPercent(conf);
-    MemorySizeUtil.checkForClusterFreeHeapMemoryLimit(conf);
+    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
     // Initialize max and min range for memstore heap space
     globalMemStorePercentMinRange =
       conf.getFloat(MEMSTORE_SIZE_MIN_RANGE_KEY, globalMemStorePercent);
@@ -184,28 +184,11 @@ public class HeapMemoryManager {
       tuningEnabled = false;
     }
 
-    int gml = (int) (globalMemStorePercentMaxRange * CONVERT_TO_PERCENTAGE);
-    int bcul = (int) ((blockCachePercentMinRange) * CONVERT_TO_PERCENTAGE);
-    if (CONVERT_TO_PERCENTAGE - (gml + bcul) < 
CLUSTER_MINIMUM_MEMORY_THRESHOLD) {
-      throw new RuntimeException("Current heap configuration for MemStore and 
BlockCache exceeds "
-        + "the threshold required for successful cluster operation. "
-        + "The combined value cannot exceed 0.8. Please check the settings for 
"
-        + MEMSTORE_SIZE_MAX_RANGE_KEY + " and " + 
BLOCK_CACHE_SIZE_MIN_RANGE_KEY
-        + " in your configuration. " + MEMSTORE_SIZE_MAX_RANGE_KEY + " is "
-        + globalMemStorePercentMaxRange + " and " + 
BLOCK_CACHE_SIZE_MIN_RANGE_KEY + " is "
-        + blockCachePercentMinRange);
-    }
-    gml = (int) (globalMemStorePercentMinRange * CONVERT_TO_PERCENTAGE);
-    bcul = (int) ((blockCachePercentMaxRange) * CONVERT_TO_PERCENTAGE);
-    if (CONVERT_TO_PERCENTAGE - (gml + bcul) < 
CLUSTER_MINIMUM_MEMORY_THRESHOLD) {
-      throw new RuntimeException("Current heap configuration for MemStore and 
BlockCache exceeds "
-        + "the threshold required for successful cluster operation. "
-        + "The combined value cannot exceed 0.8. Please check the settings for 
"
-        + MEMSTORE_SIZE_MIN_RANGE_KEY + " and " + 
BLOCK_CACHE_SIZE_MAX_RANGE_KEY
-        + " in your configuration. " + MEMSTORE_SIZE_MIN_RANGE_KEY + " is "
-        + globalMemStorePercentMinRange + " and " + 
BLOCK_CACHE_SIZE_MAX_RANGE_KEY + " is "
-        + blockCachePercentMaxRange);
-    }
+    checkHeapMemoryLimits(MEMSTORE_SIZE_MAX_RANGE_KEY, 
globalMemStorePercentMaxRange,
+      BLOCK_CACHE_SIZE_MIN_RANGE_KEY, blockCachePercentMinRange);
+    checkHeapMemoryLimits(MEMSTORE_SIZE_MIN_RANGE_KEY, 
globalMemStorePercentMinRange,
+      BLOCK_CACHE_SIZE_MAX_RANGE_KEY, blockCachePercentMaxRange);
+
     return tuningEnabled;
   }
 
@@ -241,6 +224,31 @@ public class HeapMemoryManager {
       : this.heapOccupancyPercent;
   }
 
+  private boolean isHeapMemoryUsageExceedingLimit(float memStoreFraction,
+    float blockCacheFraction) {
+    // Use integer percentage to avoid subtle float precision issues and 
ensure consistent
+    // comparison. This also maintains backward compatibility with previous 
logic relying on int
+    // truncation.
+    int memStorePercent = (int) (memStoreFraction * CONVERT_TO_PERCENTAGE);
+    int blockCachePercent = (int) (blockCacheFraction * CONVERT_TO_PERCENTAGE);
+    int minFreeHeapPercent = (int) (this.minFreeHeapFraction * 
CONVERT_TO_PERCENTAGE);
+
+    return memStorePercent + blockCachePercent + minFreeHeapPercent > 
CONVERT_TO_PERCENTAGE;
+  }
+
+  private void checkHeapMemoryLimits(String memStoreConfKey, float 
memStoreFraction,
+    String blockCacheConfKey, float blockCacheFraction) {
+    if (isHeapMemoryUsageExceedingLimit(memStoreFraction, blockCacheFraction)) 
{
+      throw new RuntimeException(String.format(
+        "Current heap configuration for MemStore and BlockCache exceeds the 
allowed heap usage. "
+          + "At least %.2f of the heap must remain free to ensure stable 
RegionServer operation. "
+          + "Please check the settings for %s and %s in your configuration. "
+          + "%s is %.2f and %s is %.2f",
+        minFreeHeapFraction, memStoreConfKey, blockCacheConfKey, 
memStoreConfKey, memStoreFraction,
+        blockCacheConfKey, blockCacheFraction));
+    }
+  }
+
   private class HeapMemoryTunerChore extends ScheduledChore implements 
FlushRequestListener {
     private HeapMemoryTuner heapMemTuner;
     private AtomicLong blockedFlushCount = new AtomicLong();
@@ -363,14 +371,15 @@ public class HeapMemoryManager {
               + blockCachePercentMaxRange + ". Resetting blockCacheSize to min 
size");
           blockCacheSize = blockCachePercentMaxRange;
         }
-        int gml = (int) (memstoreSize * CONVERT_TO_PERCENTAGE);
-        int bcul = (int) ((blockCacheSize) * CONVERT_TO_PERCENTAGE);
-        if (CONVERT_TO_PERCENTAGE - (gml + bcul) < 
CLUSTER_MINIMUM_MEMORY_THRESHOLD) {
+
+        if (isHeapMemoryUsageExceedingLimit(memstoreSize, blockCacheSize)) {
           LOG.info("Current heap configuration from HeapMemoryTuner exceeds "
-            + "the threshold required for successful cluster operation. "
-            + "The combined value cannot exceed 0.8. " + 
MemorySizeUtil.MEMSTORE_SIZE_KEY + " is "
-            + memstoreSize + " and " + HFILE_BLOCK_CACHE_SIZE_KEY + " is " + 
blockCacheSize);
-          // TODO can adjust the value so as not exceed 80%. Is that correct? 
may be.
+            + "the allowed heap usage. At least " + minFreeHeapFraction
+            + " of the heap must remain free to ensure stable RegionServer 
operation. "
+            + MemorySizeUtil.MEMSTORE_SIZE_KEY + " is " + memstoreSize + " and 
"
+            + HFILE_BLOCK_CACHE_SIZE_KEY + " is " + blockCacheSize);
+          // NOTE: In the future, we might adjust values to not exceed limits,
+          // but for now tuning is skipped if over threshold.
         } else {
           int memStoreDeltaSize =
             (int) ((memstoreSize - globalMemStorePercent) * 
CONVERT_TO_PERCENTAGE);
diff --git 
a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/util/TestMemorySizeUtil.java
 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/util/TestMemorySizeUtil.java
new file mode 100644
index 00000000000..5f00c34dbcb
--- /dev/null
+++ 
b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/util/TestMemorySizeUtil.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase.io.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HBaseClassTestRule;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({ MiscTests.class, SmallTests.class })
+public class TestMemorySizeUtil {
+
+  @ClassRule
+  public static final HBaseClassTestRule CLASS_RULE =
+    HBaseClassTestRule.forClass(TestMemorySizeUtil.class);
+
+  private Configuration conf;
+
+  @Before
+  public void setup() {
+    conf = new Configuration();
+  }
+
+  @Test
+  public void testValidateRegionServerHeapMemoryAllocation() {
+    // when memstore size + block cache size + default free heap min size == 
1.0
+    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4f);
+    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.4f);
+    assertEquals(HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD, 0.2f, 
0.0f);
+    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
+
+    // when memstore size + block cache size + default free heap min size > 1.0
+    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.5f);
+    assertThrows(RuntimeException.class,
+      () -> MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf));
+
+    // when free heap min size is set to 0, it should not throw an exception
+    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.5f);
+    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.5f);
+    
conf.setLong(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, 
0L);
+    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
+
+    // when free heap min size is set to a negative value, it should be 
regarded as default value
+    
conf.setLong(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, 
-1024L);
+    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.4f);
+    conf.setFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, 0.4f);
+    MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf);
+
+    conf.setFloat(MemorySizeUtil.MEMSTORE_SIZE_KEY, 0.41f);
+    assertThrows(RuntimeException.class,
+      () -> MemorySizeUtil.validateRegionServerHeapMemoryAllocation(conf));
+  }
+
+  @Test
+  public void testGetRegionServerMinFreeHeapFraction() {
+    // when setting is not set, it should return the default value
+    conf.set(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, 
"");
+    float minFreeHeapFraction = 
MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf);
+    assertEquals(HConstants.HBASE_CLUSTER_MINIMUM_MEMORY_THRESHOLD, 
minFreeHeapFraction, 0.0f);
+
+    // when setting to 0, it should return 0.0f
+    conf.set(MemorySizeUtil.HBASE_REGION_SERVER_FREE_HEAP_MIN_MEMORY_SIZE_KEY, 
"0");
+    minFreeHeapFraction = 
MemorySizeUtil.getRegionServerMinFreeHeapFraction(conf);
+    assertEquals(0.0f, minFreeHeapFraction, 0.0f);
+  }
+}

Reply via email to