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

Gargi-jais11 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 07239e25756 HDDS-15300. Handle zero-capacity volumes in DiskBalancer 
policy (#10294).
07239e25756 is described below

commit 07239e25756dd8624a9c7adefcb2f06d1224097e
Author: slfan1989 <[email protected]>
AuthorDate: Tue May 19 12:14:18 2026 +0800

    HDDS-15300. Handle zero-capacity volumes in DiskBalancer policy (#10294).
---
 .../DiskBalancerVolumeCalculation.java             | 12 +++++++----
 .../policy/DefaultContainerChoosingPolicy.java     | 14 ++++++++++++
 .../TestDefaultContainerChoosingPolicy.java        | 16 ++++++++++++++
 .../TestDiskBalancerVolumeCalculation.java         | 25 ++++++++++++++++++++++
 4 files changed, 63 insertions(+), 4 deletions(-)

diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerVolumeCalculation.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerVolumeCalculation.java
index 89b00f073e7..6e6d662f14d 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerVolumeCalculation.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/DiskBalancerVolumeCalculation.java
@@ -118,17 +118,21 @@ public static double 
calculateVolumeDataDensity(List<VolumeFixedUsage> volumeSet
     }
     
     try {
-      // If there is only one volume, return 0.0 as there's no imbalance to 
measure
-      if (volumeSet.size() <= 1) {
+      final List<VolumeFixedUsage> usableVolumes = volumeSet.stream()
+          .filter(v -> v.getUsage().getCapacity() > 0)
+          .collect(Collectors.toList());
+
+      // If there is only one usable volume, return 0.0 as there's no 
imbalance to measure
+      if (usableVolumes.size() <= 1) {
         return 0.0;
       }
 
       // Calculate ideal usage using the same immutable volume snapshot
-      final double idealUsage = getIdealUsage(volumeSet);
+      final double idealUsage = getIdealUsage(usableVolumes);
       double volumeDensitySum = 0.0;
 
       // Calculate density for each volume using the same snapshot
-      for (VolumeFixedUsage volumeUsage : volumeSet) {
+      for (VolumeFixedUsage volumeUsage : usableVolumes) {
         final double currentUsage = volumeUsage.getUtilization();
 
         // Calculate density as absolute difference from ideal usage
diff --git 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java
 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java
index 97e553937b8..baee04bb976 100644
--- 
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java
+++ 
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java
@@ -83,9 +83,13 @@ public ContainerCandidate 
chooseVolumesAndContainer(OzoneContainer ozoneContaine
       // Use storage ID as secondary sort for deterministic ordering when 
utilizations are equal
       final List<VolumeFixedUsage> volumeUsages = allVolumes.stream()
           .map(v -> newVolumeFixedUsage(v, deltaMap))
+          .filter(DefaultContainerChoosingPolicy::hasPositiveCapacity)
           .sorted(Comparator.comparingDouble(VolumeFixedUsage::getUtilization)
               .thenComparing(v -> v.getVolume().getStorageID()))
           .collect(Collectors.toList());
+      if (volumeUsages.size() < 2) {
+        return null;
+      }
 
       // Calculate ideal usage and threshold range (once)
       final double idealUsage = getIdealUsage(volumeUsages);
@@ -145,6 +149,16 @@ public ContainerCandidate 
chooseVolumesAndContainer(OzoneContainer ozoneContaine
     }
   }
 
+  private static boolean hasPositiveCapacity(VolumeFixedUsage volumeUsage) {
+    long capacity = volumeUsage.getUsage().getCapacity();
+    if (capacity > 0) {
+      return true;
+    }
+    LOG.debug("Skipping volume {} for disk balancing because capacity is {}",
+        volumeUsage.getVolume(), capacity);
+    return false;
+  }
+
   /**
    * Finds a container on {@code src} that can move to {@code dst}.
    */
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDefaultContainerChoosingPolicy.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDefaultContainerChoosingPolicy.java
index a33807e9c50..2dbeab1c5bf 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDefaultContainerChoosingPolicy.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDefaultContainerChoosingPolicy.java
@@ -66,6 +66,7 @@
 import org.apache.hadoop.ozone.container.ozoneimpl.ContainerController;
 import org.apache.hadoop.ozone.container.ozoneimpl.OzoneContainer;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
@@ -436,6 +437,21 @@ private static Stream<Arguments> 
quasiClosedEligibilityParams() {
     );
   }
 
+  @Test
+  public void testChooseVolumesSkipsZeroCapacityVolume() throws IOException {
+    HddsVolume zeroCapacityVolume = createVolume("zero-capacity", 0, 0);
+    HddsVolume normalVolume = createVolume("normal", 0.80, VOLUME_CAPACITY);
+    volumeSet = createVolumeSetForUsages(Arrays.asList(
+        zeroCapacityVolume, normalVolume));
+    mockContainerSet(newContainerSet());
+
+    ContainerCandidate result = 
policy.chooseVolumesAndContainer(ozoneContainer,
+        volumeSet, deltaMap, inProgressContainerIDs, THRESHOLD,
+        DEFAULT_MOVABLE_STATES);
+
+    assertNull(result);
+  }
+
   /**
    * Generic test method that can be reused for different scenarios.
    *
diff --git 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerVolumeCalculation.java
 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerVolumeCalculation.java
index 9ea13503b05..a32da8a3de9 100644
--- 
a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerVolumeCalculation.java
+++ 
b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDiskBalancerVolumeCalculation.java
@@ -23,6 +23,7 @@
 import java.io.IOException;
 import java.nio.file.Path;
 import java.time.Duration;
+import java.util.Arrays;
 import java.util.Collections;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.fs.MockSpaceUsageCheckFactory;
@@ -58,6 +59,30 @@ void getIdealUsageReturnsZeroForZeroTotalCapacity() throws 
IOException {
                 zeroCapacityVolume, null))));
   }
 
+  @Test
+  void calculateVolumeDataDensityIgnoresZeroCapacityVolumes()
+      throws IOException {
+    HddsVolume zeroCapacityVolume = createVolume("zero-capacity", 0, 0);
+    HddsVolume lowUsageVolume = createVolume("low-usage", 100, 90);
+    HddsVolume highUsageVolume = createVolume("high-usage", 100, 50);
+
+    DiskBalancerVolumeCalculation.VolumeFixedUsage lowUsage =
+        DiskBalancerVolumeCalculation.newVolumeFixedUsage(lowUsageVolume, 
null);
+    DiskBalancerVolumeCalculation.VolumeFixedUsage highUsage =
+        DiskBalancerVolumeCalculation.newVolumeFixedUsage(highUsageVolume, 
null);
+    DiskBalancerVolumeCalculation.VolumeFixedUsage zeroCapacity =
+        DiskBalancerVolumeCalculation.newVolumeFixedUsage(
+            zeroCapacityVolume, null);
+
+    double densityWithoutZeroCapacityVolume =
+        DiskBalancerVolumeCalculation.calculateVolumeDataDensity(
+            Arrays.asList(lowUsage, highUsage));
+
+    assertEquals(densityWithoutZeroCapacityVolume,
+        DiskBalancerVolumeCalculation.calculateVolumeDataDensity(
+            Arrays.asList(zeroCapacity, lowUsage, highUsage)), 0.0);
+  }
+
   @Test
   void getIdealUsageRejectsNegativeCapacity() throws IOException {
     HddsVolume negativeCapacityVolume = createVolume(


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

Reply via email to