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]