diff --git a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java index 8e1080dc48d1..e86620f172ed 100644 --- a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java +++ b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/KeyValueHandler.java @@ -1539,7 +1539,10 @@ private void deleteInternal(Container container, boolean force) } // Avoid holding write locks for disk operations sendICR(container); + long bytesUsed = container.getContainerData().getBytesUsed(); + HddsVolume volume = container.getContainerData().getVolume(); container.delete(); + volume.decrementUsedSpace(bytesUsed); } private void triggerVolumeScanAndThrowException(Container container, diff --git a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java index 76e696e91dd5..ee52de8b21f1 100644 --- a/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java +++ b/hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/keyvalue/TestKeyValueHandler.java @@ -25,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; @@ -432,6 +433,60 @@ public void testDeleteContainer() throws IOException { } } + /** + * Tests that deleting a container decrements the cached used space of its volume. + */ + @Test + public void testDeleteDecrementsVolumeUsedSpace() throws IOException { + final long containerID = 1; + final String clusterId = UUID.randomUUID().toString(); + final String datanodeId = UUID.randomUUID().toString(); + final ContainerSet containerSet = newContainerSet(); + final MutableVolumeSet volumeSet = mock(MutableVolumeSet.class); + final HddsVolume hddsVolume = mock(HddsVolume.class); + when(hddsVolume.getDeletedContainerDir()).thenReturn(new File("")); + + final ConfigurationSource conf = new OzoneConfiguration(); + final ContainerMetrics metrics = ContainerMetrics.create(conf); + final AtomicInteger icrReceived = new AtomicInteger(0); + final long containerBytesUsed = 1024 * 1024; + + // We're testing KeyValueHandler in this test, all the other objects are mocked + final KeyValueHandler kvHandler = new KeyValueHandler(conf, + datanodeId, containerSet, volumeSet, metrics, + c -> icrReceived.incrementAndGet()); + kvHandler.setClusterID(clusterId); + + // Setup ContainerData and Container mocks + KeyValueContainerData containerData = mock(KeyValueContainerData.class); + when(containerData.getContainerID()).thenReturn(containerID); + when(containerData.getVolume()).thenReturn(hddsVolume); + when(containerData.getBytesUsed()).thenReturn(containerBytesUsed); + when(containerData.getState()).thenReturn(ContainerProtos.ContainerDataProto.State.CLOSED); + when(containerData.isOpen()).thenReturn(false); + when(containerData.getLayoutVersion()).thenReturn(ContainerLayoutVersion.FILE_PER_BLOCK); + when(containerData.getDbFile()).thenReturn(new File(tempDir.toFile(), "dummy.db")); + when(containerData.getContainerPath()).thenReturn(tempDir.toString()); + when(containerData.getMetadataPath()).thenReturn(tempDir.toString()); + + KeyValueContainer container = mock(KeyValueContainer.class); + when(container.getContainerData()).thenReturn(containerData); + when(container.hasBlocks()).thenReturn(true); + + containerSet.addContainer(container); + assertNotNull(containerSet.getContainer(containerID)); + + // This is the method we're testing. It should decrement used space in the volume when deleting this container + kvHandler.deleteContainer(container, true); + assertNull(containerSet.getContainer(containerID)); + + // Verify ICR was sent (once for delete) + assertEquals(1, icrReceived.get(), "ICR should be sent for delete"); + verify(container, times(1)).delete(); + // Verify decrementUsedSpace was called with the correct amount + verify(hddsVolume, times(1)).decrementUsedSpace(eq(containerBytesUsed)); + } + @Test public void testDeleteContainerTimeout() throws IOException { final String testDir = tempDir.toString();