Skip to content

Commit 1cc4a87

Browse files
authored
HDDS-14186. [DiskBalancer] Don't pick size 0 container when choosing container to move (#9514)
1 parent 2abd751 commit 1cc4a87

3 files changed

Lines changed: 61 additions & 10 deletions

File tree

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/diskbalancer/policy/DefaultContainerChoosingPolicy.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ public ContainerData chooseContainer(OzoneContainer ozoneContainer,
7878
final long dstCommittedBytes = dst.getCommittedBytes();
7979
while (itr.hasNext()) {
8080
ContainerData containerData = itr.next().getContainerData();
81-
if (!inProgressContainerIDs.contains(
82-
ContainerID.valueOf(containerData.getContainerID())) &&
81+
if (containerData.getBytesUsed() > 0 &&
82+
!inProgressContainerIDs.contains(ContainerID.valueOf(containerData.getContainerID())) &&
8383
(containerData.isClosed() || (test && containerData.isQuasiClosed()))) {
8484

8585
// Check if dst can accept the candidate container.

hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/diskbalancer/TestDefaultContainerChoosingPolicy.java

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@
3535
import java.util.Set;
3636
import java.util.UUID;
3737
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
38+
import org.apache.hadoop.hdds.conf.StorageUnit;
3839
import org.apache.hadoop.hdds.fs.MockSpaceUsageCheckFactory;
3940
import org.apache.hadoop.hdds.fs.MockSpaceUsageSource;
4041
import org.apache.hadoop.hdds.fs.SpaceUsageCheckFactory;
4142
import org.apache.hadoop.hdds.fs.SpaceUsagePersistence;
4243
import org.apache.hadoop.hdds.fs.SpaceUsageSource;
4344
import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto;
45+
import org.apache.hadoop.hdds.scm.ScmConfigKeys;
4446
import org.apache.hadoop.hdds.scm.container.ContainerID;
4547
import org.apache.hadoop.ozone.container.common.impl.ContainerData;
4648
import org.apache.hadoop.ozone.container.common.impl.ContainerLayoutVersion;
@@ -154,14 +156,7 @@ private HddsVolume createVolume(String dir, double utilization)
154156
*/
155157
private void createContainer(long id, long size, HddsVolume vol)
156158
throws IOException {
157-
KeyValueContainerData containerData = new KeyValueContainerData(id,
158-
ContainerLayoutVersion.FILE_PER_BLOCK, size,
159-
UUID.randomUUID().toString(), UUID.randomUUID().toString());
160-
containerData.setState(ContainerDataProto.State.CLOSED);
161-
containerData.setVolume(vol);
162-
containerData.getStatistics().setBlockBytesForTesting(size);
163-
KeyValueContainer container = new KeyValueContainer(containerData, CONF);
164-
containerSet.addContainer(container);
159+
createContainer(id, size, vol, containerSet);
165160
}
166161

167162
@Test
@@ -200,4 +195,56 @@ public void testContainerNotChosen() {
200195
// No containers should not be chosen
201196
assertNull(chosenContainer);
202197
}
198+
199+
@Test
200+
public void testSizeZeroContainersSkipped() throws IOException {
201+
// Create a new container set with containers that have size 0
202+
ContainerSet testContainerSet = newContainerSet();
203+
204+
// Create containers with size 0 (should be skipped)
205+
createContainer(10L, 0L, sourceVolume, testContainerSet);
206+
createContainer(11L, 0L, sourceVolume, testContainerSet);
207+
208+
// Create a container with non-zero size (should be chosen)
209+
createContainer(12L, 200L * MB, sourceVolume, testContainerSet);
210+
211+
// Mock OzoneContainer to return our test container set
212+
OzoneContainer testOzoneContainer = mock(OzoneContainer.class);
213+
ContainerController testController = new ContainerController(testContainerSet, null);
214+
when(testOzoneContainer.getController()).thenReturn(testController);
215+
216+
// The policy should skip containers 10 and 11 (size 0) and choose container 12
217+
ContainerData chosenContainer = policy.chooseContainer(testOzoneContainer,
218+
sourceVolume, destVolume1, inProgressContainerIDs, THRESHOLD, volumeSet, deltaMap);
219+
220+
// Container 12 (non-zero size) should be chosen, skipping containers 10 and 11 (size 0)
221+
assertNotNull(chosenContainer);
222+
assertEquals(12L, chosenContainer.getContainerID());
223+
assertEquals(200L * MB, chosenContainer.getBytesUsed());
224+
}
225+
226+
/**
227+
* Create KeyValueContainers and add it to the specified containerSet.
228+
* @param id container ID
229+
* @param usedBytes bytes used by the container (can be 0)
230+
* @param vol volume where container is located
231+
* @param targetContainerSet container set to add the container to
232+
*/
233+
private void createContainer(long id, long usedBytes, HddsVolume vol,
234+
ContainerSet targetContainerSet) throws IOException {
235+
// Use maxSize as the container capacity (must be > 0)
236+
// If usedBytes is 0, we still need a valid maxSize for container creation
237+
long maxSize = usedBytes > 0 ? usedBytes : (long) CONF.getStorageSize(
238+
ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE,
239+
ScmConfigKeys.OZONE_SCM_CONTAINER_SIZE_DEFAULT, StorageUnit.BYTES);
240+
KeyValueContainerData containerData = new KeyValueContainerData(id,
241+
ContainerLayoutVersion.FILE_PER_BLOCK, maxSize,
242+
UUID.randomUUID().toString(), UUID.randomUUID().toString());
243+
containerData.setState(ContainerDataProto.State.CLOSED);
244+
containerData.setVolume(vol);
245+
// Set the actual used bytes (can be 0)
246+
containerData.getStatistics().setBlockBytesForTesting(usedBytes);
247+
KeyValueContainer container = new KeyValueContainer(containerData, CONF);
248+
targetContainerSet.addContainer(container);
249+
}
203250
}

hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/scm/node/TestContainerChoosingPolicy.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ public void createContainers() {
273273

274274
containerData.setState(isOpen ? ContainerDataProto.State.OPEN : ContainerDataProto.State.CLOSED);
275275
containerData.setVolume(volume);
276+
// Set some bytes used for containers so they can be chosen for disk balancing
277+
// Use a small non-zero value to ensure containers are not skipped
278+
long bytesUsed = isOpen ? 0 : (i % 1000 + 1) * 1024L; // 1KB to 1MB for closed containers
279+
containerData.getStatistics().setBlockBytesForTesting(bytesUsed);
276280
KeyValueContainer container = new KeyValueContainer(containerData, CONF);
277281

278282
try {

0 commit comments

Comments
 (0)