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

weichiu pushed a commit to branch HDDS-7593
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/HDDS-7593 by this push:
     new 6c6dc4352e HDDS-11135. [hsync] Replace expensive 
VolumeUsage.getMinVolumeFreeSpace() (#6930)
6c6dc4352e is described below

commit 6c6dc4352e475c56a5972f8fe355c0aca2a6554c
Author: Wei-Chiu Chuang <[email protected]>
AuthorDate: Tue Jul 16 10:23:54 2024 -0700

    HDDS-11135. [hsync] Replace expensive VolumeUsage.getMinVolumeFreeSpace() 
(#6930)
    
    Co-authored-by: Duong Nguyen <[email protected]>
---
 .../container/common/impl/HddsDispatcher.java      |  4 +-
 .../common/impl/StorageLocationReport.java         |  2 +-
 .../common/volume/AvailableSpaceFilter.java        |  2 +-
 .../ozone/container/common/volume/VolumeUsage.java | 72 ++++++++++++++--------
 .../common/volume/TestReservedVolumeSpace.java     | 26 ++++++++
 5 files changed, 76 insertions(+), 30 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
index 8d7dc087c6..3f7b752b1c 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/HddsDispatcher.java
@@ -113,6 +113,7 @@ public class HddsDispatcher implements ContainerDispatcher, 
Auditor {
   private ContainerMetrics metrics;
   private final TokenVerifier tokenVerifier;
   private long slowOpThresholdMs;
+  private VolumeUsage.MinFreeSpaceCalculator freeSpaceCalculator;
 
   /**
    * Constructs an OzoneContainer that receives calls from
@@ -147,6 +148,7 @@ public class HddsDispatcher implements ContainerDispatcher, 
Auditor {
             LOG,
             HddsUtils::processForDebug,
             HddsUtils::processForDebug);
+    this.freeSpaceCalculator = new VolumeUsage.MinFreeSpaceCalculator(conf);
   }
 
   @Override
@@ -612,7 +614,7 @@ public class HddsDispatcher implements ContainerDispatcher, 
Auditor {
           volume.getCurrentUsage();
       long volumeCapacity = precomputedVolumeSpace.getCapacity();
       long volumeFreeSpaceToSpare =
-          VolumeUsage.getMinVolumeFreeSpace(conf, volumeCapacity);
+          freeSpaceCalculator.get(volumeCapacity);
       long volumeFree = precomputedVolumeSpace.getAvailable();
       long volumeCommitted = volume.getCommittedBytes();
       long volumeAvailable = volumeFree - volumeCommitted;
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java
index f31d45a778..dfcedbe75e 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/impl/StorageLocationReport.java
@@ -189,7 +189,7 @@ public final class StorageLocationReport implements
         .setStorageLocation(getStorageLocation())
         .setFailed(isFailed())
         .setFreeSpaceToSpare(conf != null ?
-            VolumeUsage.getMinVolumeFreeSpace(conf, getCapacity()) : 0)
+            new VolumeUsage.MinFreeSpaceCalculator(conf).get(getCapacity()) : 
0)
         .build();
   }
 
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/AvailableSpaceFilter.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/AvailableSpaceFilter.java
index 622c85a52f..0d82a38d1c 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/AvailableSpaceFilter.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/AvailableSpaceFilter.java
@@ -43,7 +43,7 @@ public class AvailableSpaceFilter implements 
Predicate<HddsVolume> {
     long committed = vol.getCommittedBytes();
     long available = free - committed;
     long volumeFreeSpaceToSpare =
-        VolumeUsage.getMinVolumeFreeSpace(vol.getConf(), volumeCapacity);
+        new 
VolumeUsage.MinFreeSpaceCalculator(vol.getConf()).get(volumeCapacity);
     boolean hasEnoughSpace = VolumeUsage.hasVolumeEnoughSpace(free, committed,
         requiredSpace, volumeFreeSpaceToSpare);
 
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java
index d18998821b..7e138b0571 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java
@@ -140,37 +140,55 @@ public class VolumeUsage {
   }
 
   /**
-   * If 'hdds.datanode.volume.min.free.space' is defined,
-   * it will be honored first. If it is not defined and
-   * 'hdds.datanode.volume.min.free.space.' is defined,it will honor this
-   * else it will fall back to 'hdds.datanode.volume.min.free.space.default'
+   * Convenience class to calculate minimum free space.
    */
-  public static long getMinVolumeFreeSpace(ConfigurationSource conf,
-      long capacity) {
-    if (conf.isConfigured(
-        HDDS_DATANODE_VOLUME_MIN_FREE_SPACE) && conf.isConfigured(
-        HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT)) {
-      LOG.error(
-          "Both {} and {} are set. Set either one, not both. If both are set,"
-              + "it will use default value which is {} as min free space",
-          HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
-          HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT,
-          HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT);
-    }
-
-    if (conf.isConfigured(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE)) {
-      return (long) conf.getStorageSize(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
+  public static class MinFreeSpaceCalculator {
+    private final boolean minFreeSpaceConfigured;
+    private final boolean minFreeSpacePercentConfigured;
+    private final long freeSpace;
+    private float freeSpacePercent;
+    private final long defaultFreeSpace;
+    public MinFreeSpaceCalculator(ConfigurationSource conf) {
+      // cache these values to avoid repeated lookups
+      minFreeSpaceConfigured = 
conf.isConfigured(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE);
+      minFreeSpacePercentConfigured = 
conf.isConfigured(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT);
+      freeSpace = 
(long)conf.getStorageSize(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
           HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT, StorageUnit.BYTES);
-    } else if (conf.isConfigured(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT)) 
{
-      float volumeMinFreeSpacePercent = Float.parseFloat(
-          conf.get(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT));
-      return (long) (capacity * volumeMinFreeSpacePercent);
+      if (minFreeSpacePercentConfigured) {
+        freeSpacePercent = Float.parseFloat(
+            conf.get(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT));
+      }
+      StorageSize measure = 
StorageSize.parse(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT);
+      double byteValue = measure.getUnit().toBytes(measure.getValue());
+      defaultFreeSpace = (long)StorageUnit.BYTES.fromBytes(byteValue);
     }
-    // either properties are not configured,then return
-    // HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT,
-    return (long) conf.getStorageSize(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
-        HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT, StorageUnit.BYTES);
 
+    /**
+     * If 'hdds.datanode.volume.min.free.space' is defined,
+     * it will be honored first. If it is not defined and
+     * 'hdds.datanode.volume.min.free.space' is defined, it will honor this
+     * else it will fall back to 'hdds.datanode.volume.min.free.space.default'
+     */
+    public long get(long capacity) {
+      if (minFreeSpaceConfigured && minFreeSpacePercentConfigured) {
+        LOG.error(
+            "Both {} and {} are set. Set either one, not both. If both are 
set,"
+                + "it will use default value which is {} as min free space",
+            HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
+            HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT,
+            HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT);
+        return defaultFreeSpace;
+      }
+
+      if (minFreeSpaceConfigured) {
+        return freeSpace;
+      } else if (minFreeSpacePercentConfigured) {
+        return (long) (capacity * freeSpacePercent);
+      }
+      // either properties are not configured,then return
+      // HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_DEFAULT
+      return defaultFreeSpace;
+    }
   }
 
   public static boolean hasVolumeEnoughSpace(long volumeAvailableSpace,
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestReservedVolumeSpace.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestReservedVolumeSpace.java
index cd9beab4b7..5e2dd0c75c 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestReservedVolumeSpace.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestReservedVolumeSpace.java
@@ -18,6 +18,8 @@
 
 package org.apache.hadoop.ozone.container.common.volume;
 
+import org.apache.hadoop.conf.StorageUnit;
+import org.apache.hadoop.hdds.HddsConfigKeys;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.fs.MockSpaceUsageCheckFactory;
 import org.apache.hadoop.hdds.scm.ScmConfigKeys;
@@ -30,6 +32,8 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.UUID;
 
+import static 
org.apache.hadoop.hdds.HddsConfigKeys.HDDS_DATANODE_VOLUME_MIN_FREE_SPACE;
+import static 
org.apache.hadoop.hdds.HddsConfigKeys.HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT;
 import static 
org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_DU_RESERVED_PERCENT;
 import static 
org.apache.hadoop.hdds.scm.ScmConfigKeys.HDDS_DATANODE_DIR_DU_RESERVED_PERCENT_DEFAULT;
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -178,6 +182,28 @@ public class TestReservedVolumeSpace {
     assertEquals(500, reservedFromVolume);
   }
 
+  @Test
+  public void testMinFreeSpaceCalculator() throws Exception {
+    OzoneConfiguration conf = new OzoneConfiguration();
+    double minSpace = 100.0;
+    conf.setStorageSize(HddsConfigKeys.HDDS_DATANODE_VOLUME_MIN_FREE_SPACE,
+        minSpace, StorageUnit.BYTES);
+    VolumeUsage.MinFreeSpaceCalculator calc = new 
VolumeUsage.MinFreeSpaceCalculator(conf);
+    long capacity = 1000;
+    assertEquals(minSpace, calc.get(capacity));
+
+    conf.setFloat(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE_PERCENT, 0.01f);
+    calc = new VolumeUsage.MinFreeSpaceCalculator(conf);
+    // default is 5GB
+    assertEquals(5L * 1024 * 1024 * 1024, calc.get(capacity));
+
+    // capacity * 1% = 10
+    conf.unset(HDDS_DATANODE_VOLUME_MIN_FREE_SPACE);
+    calc = new VolumeUsage.MinFreeSpaceCalculator(conf);
+    assertEquals(10, calc.get(capacity));
+  }
+
+
   private long getExpectedDefaultReserved(HddsVolume volume) {
     long totalCapacity = 
volume.getVolumeInfo().get().getUsageForTesting().realUsage().getCapacity();
     return (long) Math.ceil(totalCapacity * 
HDDS_DATANODE_DIR_DU_RESERVED_PERCENT_DEFAULT);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to