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

jojochuang 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 d7a2702212b HDDS-15828. Fix flaky TestDirectoryDeletingServiceWithFSO 
snapshot cleanup (#11212)
d7a2702212b is described below

commit d7a2702212bfeb8f7f1cdedbd939e4a46a73e77a
Author: Arun Sarin <[email protected]>
AuthorDate: Tue Sep 22 02:25:22 2026 +0530

    HDDS-15828. Fix flaky TestDirectoryDeletingServiceWithFSO snapshot cleanup 
(#11212)
    
    Generated-by: Cursor <[email protected]>
---
 .../TestDirectoryDeletingServiceWithFSO.java       | 97 +++++++++++++++++-----
 1 file changed, 74 insertions(+), 23 deletions(-)

diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/service/TestDirectoryDeletingServiceWithFSO.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/service/TestDirectoryDeletingServiceWithFSO.java
index d516a74a12b..58d816fbabd 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/service/TestDirectoryDeletingServiceWithFSO.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/om/service/TestDirectoryDeletingServiceWithFSO.java
@@ -107,6 +107,16 @@ public class TestDirectoryDeletingServiceWithFSO {
   private static OzoneClient client;
   private static DeletingServiceMetrics metrics;
 
+  // Per-test state for @AfterEach cleanup: tracked when a test suspends 
services or needs table cleanup.
+  private int snapshotCountAfterTest = -1;
+  private boolean pendingSdsResume = false;
+  private DirectoryDeletingService pendingResumeDds = null;
+  private boolean needsTableCleanup = false;
+  private String snapshotCleanupVolume = null;
+  private String snapshotCleanupBucket = null;
+  private String snapshotToDeleteInCleanup = null;
+  private String snapshotToDeleteInCleanup2 = null;
+
   @BeforeAll
   public static void init() throws Exception {
     OzoneConfiguration conf = new OzoneConfiguration();
@@ -149,7 +159,48 @@ public static void teardown() {
   }
 
   @AfterEach
-  public void cleanup() throws InterruptedException, TimeoutException {
+  public void cleanup() throws Exception {
+    try {
+      if (pendingSdsResume) {
+        
cluster.getOzoneManager().getKeyManager().getSnapshotDeletingService().resume();
+        pendingSdsResume = false;
+      }
+      if (snapshotToDeleteInCleanup != null) {
+        String cleanupVolume = snapshotCleanupVolume != null ? 
snapshotCleanupVolume : volumeName;
+        String cleanupBucket = snapshotCleanupBucket != null ? 
snapshotCleanupBucket : bucketName;
+        try {
+          client.getObjectStore().deleteSnapshot(cleanupVolume, cleanupBucket, 
snapshotToDeleteInCleanup);
+        } catch (IOException ignored) {
+          // snapshot may have already been deleted by the test body
+        }
+        snapshotToDeleteInCleanup = null;
+        if (snapshotToDeleteInCleanup2 != null) {
+          try {
+            client.getObjectStore().deleteSnapshot(cleanupVolume, 
cleanupBucket, snapshotToDeleteInCleanup2);
+          } catch (IOException ignored) {
+            // snapshot may have already been deleted by the test body
+          }
+          snapshotToDeleteInCleanup2 = null;
+        }
+        snapshotCleanupVolume = null;
+        snapshotCleanupBucket = null;
+      }
+      if (snapshotCountAfterTest >= 0) {
+        Table<String, SnapshotInfo> snapshotInfoTable =
+            
cluster.getOzoneManager().getMetadataManager().getSnapshotInfoTable();
+        waitForSnapshotsPurged(snapshotInfoTable, snapshotCountAfterTest);
+        snapshotCountAfterTest = -1;
+      }
+    } finally {
+      if (pendingResumeDds != null) {
+        pendingResumeDds.resume();
+        pendingResumeDds = null;
+      }
+      if (needsTableCleanup && snapshotCountAfterTest < 0) {
+        cleanupTables();
+        needsTableCleanup = false;
+      }
+    }
     assertDoesNotThrow(() -> {
       Path root = new Path("/");
       FileStatus[] fileStatuses = fs.listStatus(root);
@@ -571,10 +622,12 @@ public void 
testAOSKeyDeletingWithSnapshotCreateParallelExecution()
     Table<String, SnapshotInfo> snapshotInfoTable = 
omMetadataManager.getSnapshotInfoTable();
     Table<String, OmKeyInfo> deletedDirTable = 
omMetadataManager.getDeletedDirTable();
     Table<String, String> renameTable = 
omMetadataManager.getSnapshotRenamedTable();
-    
cluster.getOzoneManager().getKeyManager().getSnapshotDeletingService().shutdown();
+    
cluster.getOzoneManager().getKeyManager().getSnapshotDeletingService().suspend();
+    pendingSdsResume = true;
     DirectoryDeletingService dirDeletingService = 
cluster.getOzoneManager().getKeyManager().getDirDeletingService();
     // Suspend KeyDeletingService
     dirDeletingService.suspend();
+    pendingResumeDds = dirDeletingService;
     Random random = new Random();
     final String testVolumeName = "volume" + random.nextInt();
     final String testBucketName = "bucket" + random.nextInt();
@@ -594,10 +647,15 @@ public void 
testAOSKeyDeletingWithSnapshotCreateParallelExecution()
     service.shutdown();
     final int initialSnapshotCount =
         (int) 
cluster.getOzoneManager().getMetadataManager().countRowsInTable(snapshotInfoTable);
+    snapshotCountAfterTest = initialSnapshotCount;
     final int initialDeletedCount = (int) 
omMetadataManager.countRowsInTable(deletedDirTable);
     final int initialRenameCount = (int) 
omMetadataManager.countRowsInTable(renameTable);
     String snap1 = "snap1";
     String snap2 = "snap2";
+    snapshotCleanupVolume = testVolumeName;
+    snapshotCleanupBucket = testBucketName;
+    snapshotToDeleteInCleanup = snap1;
+    snapshotToDeleteInCleanup2 = snap2;
     createFileKey(bucket, "dir1/key1");
     store.createSnapshot(testVolumeName, testBucketName, "snap1");
     bucket.renameKey("dir1", "dir2");
@@ -659,24 +717,6 @@ public void 
testAOSKeyDeletingWithSnapshotCreateParallelExecution()
     service.runPeriodicalTaskNow();
     store.deleteSnapshot(testVolumeName, testBucketName, snap1);
     cluster.getOzoneManager().awaitDoubleBufferFlush();
-    cluster.restartOzoneManager();
-    cluster.waitForClusterToBeReady();
-    cluster.getOzoneManager().awaitDoubleBufferFlush();
-    SnapshotDeletingService snapshotDeletingService =
-        cluster.getOzoneManager().getKeyManager().getSnapshotDeletingService();
-    GenericTestUtils.waitFor(() -> {
-      try {
-        snapshotDeletingService.runPeriodicalTaskNow();
-        cluster.getOzoneManager().awaitDoubleBufferFlush();
-        long currentSnapshotCount = 
cluster.getOzoneManager().getMetadataManager()
-            
.countRowsInTable(cluster.getOzoneManager().getMetadataManager().getSnapshotInfoTable());
-        return currentSnapshotCount <= initialSnapshotCount;
-      } catch (Exception e) {
-        throw new RuntimeException(e);
-      }
-    }, 100, 10000);
-    
assertTableRowCount(cluster.getOzoneManager().getMetadataManager().getSnapshotInfoTable(),
 initialSnapshotCount);
-    dirDeletingService.resume();
   }
 
   @Test
@@ -730,8 +770,11 @@ public void testDirDeletedTableCleanUpForSnapshot() throws 
Exception {
     assertTableRowCount(keyTable, 8);
     assertTableRowCount(dirTable, 5);
 
-    // Create snapshot
+    // Create snapshot; register for cleanup in @AfterEach in case the test 
fails before deleting it.
     client.getObjectStore().createSnapshot(volumeName, bucketName, "snap1");
+    snapshotToDeleteInCleanup = "snap1";
+    snapshotCountAfterTest = 0;
+    needsTableCleanup = true;
     assertTableRowCount(snapshotInfoTable, 1);
 
     // Case-1) Delete 3 Files directly.
@@ -787,9 +830,8 @@ public void testDirDeletedTableCleanUpForSnapshot() throws 
Exception {
     assertSubPathsCount(dirDeletingService::getMovedDirsCount, 4);
     assertSubPathsCount(dirDeletingService::getDeletedDirsCount, 0);
 
-    // Manual cleanup deletedDirTable for next tests
+    // Snapshot deletion and table cleanup are handled in @AfterEach cleanup().
     client.getObjectStore().deleteSnapshot(volumeName, bucketName, "snap1");
-    cleanupTables();
   }
 
   private void cleanupTables() throws IOException {
@@ -823,6 +865,15 @@ static void assertSubPathsCount(LongSupplier pathCount, 
long expectedCount)
         1000, 120000);
   }
 
+  /**
+   * Wait until SnapshotDeletingService has purged snapshots and 
snapshotInfoTable
+   * reaches the expected row count. SDS must already be resumed before 
calling this.
+   */
+  private void waitForSnapshotsPurged(Table<String, SnapshotInfo> 
snapshotInfoTable,
+      int expectedCount) throws TimeoutException, InterruptedException {
+    assertTableRowCount(snapshotInfoTable, expectedCount);
+  }
+
   private void assertTableRowCount(Table<String, ?> table, int count)
       throws TimeoutException, InterruptedException {
     GenericTestUtils.waitFor(() -> assertTableRowCount(count, table), 1000,


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

Reply via email to