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

ArafatKhan2198 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 a152e6e34ba HDDS-16091. Recon fills disk with leaked checkpoints and 
crashes on startup when local OM DB is missing. (#10950)
a152e6e34ba is described below

commit a152e6e34bad7cfba60feefa14d2ee81cb743525
Author: Arafat2198 <[email protected]>
AuthorDate: Wed Aug 5 19:16:03 2026 +0530

    HDDS-16091. Recon fills disk with leaked checkpoints and crashes on startup 
when local OM DB is missing. (#10950)
    
    Co-authored-by: Claude Opus <[email protected]>
---
 .../spi/impl/OzoneManagerServiceProviderImpl.java  |  11 +-
 .../ozone/recon/tasks/ReconTaskControllerImpl.java | 141 ++++++++++++---------
 .../recon/tasks/TestReconTaskControllerImpl.java   | 138 +++++++++++++++++---
 3 files changed, 213 insertions(+), 77 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/OzoneManagerServiceProviderImpl.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/OzoneManagerServiceProviderImpl.java
index d221168aa00..7453e7bcc63 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/OzoneManagerServiceProviderImpl.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/spi/impl/OzoneManagerServiceProviderImpl.java
@@ -294,7 +294,16 @@ public void start() {
                   deltaTaskStatusUpdater.getLastUpdatedSeqNumber()) < 0; // 
Condition 3
         })
         .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));  
// Collect into desired Map
-    if (!reconOmTaskMap.isEmpty()) {
+    if (!reconOmTaskMap.isEmpty() && omMetadataManager.getStore() == null) {
+      // Fresh start (or the local OM snapshot DB is missing) while stale task
+      // status rows still exist in the Recon SQL DB. There is no local OM DB 
to
+      // checkpoint/reprocess yet, so attempting reinitialization here would 
fail
+      // (checkpoint creation dereferences a null DB store). Skip it; the full
+      // snapshot sync scheduled below will download the OM DB and initialize 
tasks.
+      LOG.info("Skipping startup task reinitialization because the local OM DB 
store " +
+          "is not initialized yet (no OM snapshot present). The scheduled full 
snapshot " +
+          "sync will download the OM DB and initialize tasks.");
+    } else if (!reconOmTaskMap.isEmpty()) {
       LOG.info("Task name and last updated sequence number of tasks, that are 
not matching with " +
           "the last updated sequence number of OmDeltaRequest task:\n");
       LOG.info("{} -> {}", deltaTaskStatusUpdater.getTaskName(), 
deltaTaskStatusUpdater.getLastUpdatedSeqNumber());
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java
index 5b142c0189d..6f142b57a69 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/tasks/ReconTaskControllerImpl.java
@@ -106,6 +106,9 @@ public class ReconTaskControllerImpl implements 
ReconTaskController {
   // Clock for the retry-delay gate; overridable in tests via the
   // @VisibleForTesting constructor to drive the gate with a MockClock.
   private Clock clock = Clock.systemUTC();
+  // Log the 1st cleanup and every Nth after that at INFO; the rest at DEBUG.
+  private static final int CHECKPOINT_CLEANUP_LOG_SAMPLE_RATE = 20;
+  private final AtomicLong checkpointCleanupCount = new AtomicLong(0);
 
   @Inject
   @SuppressWarnings("checkstyle:ParameterNumber")
@@ -633,30 +636,45 @@ public synchronized 
ReconTaskController.ReInitializationResult queueReInitializa
 
     // Try checkpoint creation (single attempt per iteration)
     ReconOMMetadataManager checkpointedOMMetadataManager = null;
-    
+    // Whether the checkpoint has been handed off to the event buffer. If not,
+    // this method owns its cleanup (the finally block below).
+    boolean handedOff = false;
+
     try {
       LOG.info("Attempting checkpoint creation (retry attempt: {})", 
eventProcessRetryCount.get() + 1);
-      checkpointedOMMetadataManager = 
createOMCheckpoint(currentOMMetadataManager);
-      LOG.info("Checkpoint creation succeeded");
-    } catch (IOException e) {
-      LOG.error("Checkpoint creation failed: {}", e.getMessage());
+      try {
+        checkpointedOMMetadataManager = 
createOMCheckpoint(currentOMMetadataManager);
+        LOG.info("Checkpoint creation succeeded");
+      } catch (IOException e) {
+        LOG.error("Checkpoint creation failed: {}", e.getMessage());
+        handleEventFailure();
+        return ReInitializationResult.RETRY_LATER;
+      }
+
+      // Create and queue the reinitialization event with checkpointed 
metadata manager
+      ReconTaskReInitializationEvent reinitEvent =
+          new ReconTaskReInitializationEvent(reason, 
checkpointedOMMetadataManager);
+      // If reinitialization event queued successfully, reset event buffer 
overflow flag and task failure flag,
+      // so that we can resume queuing the delta events.
+      if (eventBuffer.offer(reinitEvent)) {
+        // The downstream consumer now owns the checkpoint and its cleanup.
+        handedOff = true;
+        resetEventFlags();
+        LOG.info("Successfully queued reinitialization event after {} 
retries", eventProcessRetryCount.get() + 1);
+        return ReconTaskController.ReInitializationResult.SUCCESS;
+      }
+
+      // Buffer full - drop the event and clean up the fresh checkpoint (in 
finally) to avoid leaking it.
+      LOG.warn("Failed to queue reinitialization event (buffer full); 
discarding fresh checkpoint at {}",
+          checkpointedOMMetadataManager.getStore() != null
+              ? checkpointedOMMetadataManager.getStore().getDbLocation() : 
"<unknown>");
       handleEventFailure();
       return ReInitializationResult.RETRY_LATER;
+    } finally {
+      if (!handedOff && checkpointedOMMetadataManager != null) {
+        cleanupCheckpoint(checkpointedOMMetadataManager);
+      }
     }
-
-    // Create and queue the reinitialization event with checkpointed metadata 
manager
-    ReconTaskReInitializationEvent reinitEvent =
-        new ReconTaskReInitializationEvent(reason, 
checkpointedOMMetadataManager);
-    boolean queued = eventBuffer.offer(reinitEvent);
-    // If reinitialization event queued successfully, reset event buffer 
overflow flag and task failure flag,
-    // so that we can resume queuing the delta events.
-    if (queued) {
-      resetEventFlags();
-      // Success - reset retry counters and flags
-      LOG.info("Successfully queued reinitialization event after {} retries", 
eventProcessRetryCount.get() + 1);
-      return ReconTaskController.ReInitializationResult.SUCCESS;
-    }
-    return null;
   }
 
   private ReconTaskController.ReInitializationResult 
validateRetryCountAndDelay() {
@@ -715,15 +733,7 @@ public void drainEventBufferAndCleanExistingCheckpoints() {
           ReconOMMetadataManager checkpointedManager = 
reinitEvent.getCheckpointedOMMetadataManager();
           if (checkpointedManager != null) {
             LOG.info("Cleaning up unprocessed checkpoint from drained 
ReconTaskReInitializationEvent");
-            // Close the database connections first
-            try {
-              checkpointedManager.close();
-              LOG.debug("Closed checkpointed OM metadata manager database 
connections");
-            } catch (Exception e) {
-              LOG.warn("Failed to close checkpointed OM metadata manager", e);
-            }
-            // Then clean up the files
-            cleanupCheckpointFiles(checkpointedManager);
+            cleanupCheckpoint(checkpointedManager);
           }
         }
       }
@@ -770,6 +780,10 @@ public ReconOMMetadataManager 
createOMCheckpoint(ReconOMMetadataManager omMetaMa
    * @throws IOException if directory operations fail
    */
   private String cleanTempCheckPointPath(ReconOMMetadataManager omMetaManager) 
throws IOException {
+    if (omMetaManager == null || omMetaManager.getStore() == null) {
+      throw new IOException("OM DB store is not initialized yet; cannot create 
"
+          + "reinitialization checkpoint. A full OM snapshot must be fetched 
first.");
+    }
     File dbLocation = omMetaManager.getStore().getDbLocation();
     if (dbLocation == null) {
       throw new IOException("OM DB location is null");
@@ -793,9 +807,9 @@ private void 
processReInitializationEvent(ReconTaskReInitializationEvent event)
         event.getReason(), event.getTimestamp());
     resetTasksFailureFlag();
     // Use the checkpointed OM metadata manager for reinitialization to 
prevent data inconsistency
-    ReconOMMetadataManager checkpointedOMMetadataManager = null;
-    try (ReconOMMetadataManager manager = 
event.getCheckpointedOMMetadataManager()) {
-      checkpointedOMMetadataManager = manager;
+    ReconOMMetadataManager checkpointedOMMetadataManager =
+        event.getCheckpointedOMMetadataManager();
+    try {
       if (checkpointedOMMetadataManager != null) {
         LOG.info("Starting async task reinitialization with checkpointed OM 
metadata manager due to: {}",
                  event.getReason());
@@ -817,9 +831,8 @@ private void 
processReInitializationEvent(ReconTaskReInitializationEvent event)
     } catch (Exception e) {
       LOG.error("Error processing reinitialization event", e);
     } finally {
-      if (checkpointedOMMetadataManager != null) {
-        cleanupCheckpointFiles(checkpointedOMMetadataManager);
-      }
+      // Clean up the checkpointed metadata manager and its files after use
+      cleanupCheckpoint(checkpointedOMMetadataManager);
     }
   }
 
@@ -877,11 +890,14 @@ AtomicBoolean getTasksFailedFlag() {
    */
   private void cleanupPreExistingCheckpoints() {
     try {
+      // The DB store is only initialized after Recon downloads its first DB
+      // snapshot from the OM. On a fresh startup it may still be null.
       if (currentOMMetadataManager == null || 
currentOMMetadataManager.getStore() == null) {
-        LOG.debug("No current OM metadata manager or store, skipping 
pre-existing checkpoint cleanup");
+        LOG.debug("No current OM metadata manager or DB store not yet 
initialized, "
+            + "skipping pre-existing checkpoint cleanup");
         return;
       }
-      
+
       // Get the base directory where checkpoints are created
       File dbLocation = currentOMMetadataManager.getStore().getDbLocation();
       if (dbLocation == null || dbLocation.getParent() == null) {
@@ -924,41 +940,50 @@ private void cleanupPreExistingCheckpoints() {
   }
   
   /**
-   * Cleanup checkpoint files for a checkpointed OM metadata manager.
-   * This method only removes the temporary checkpoint files without closing 
database connections.
-   * Used when the manager is closed via try-with-resources.
-   * 
-   * @param checkpointedManager the checkpointed OM metadata manager
+   * Cleanup checkpointed OM metadata manager and associated checkpoint files.
+   * This method closes the database connections and removes the temporary 
checkpoint files.
+   *
+   * @param checkpointedManager the checkpointed OM metadata manager to clean 
up
    */
-  private void cleanupCheckpointFiles(ReconOMMetadataManager 
checkpointedManager) {
+  private void cleanupCheckpoint(ReconOMMetadataManager checkpointedManager) {
     if (checkpointedManager == null) {
       return;
     }
+    // Get the checkpoint location before closing.
+    File checkpointLocation = null;
     try {
-      // Get the checkpoint location
-      File checkpointLocation = null;
-      try {
-        if (checkpointedManager.getStore() != null && 
-            checkpointedManager.getStore().getDbLocation() != null) {
-          // The checkpoint location is typically the parent directory of the 
DB location
-          checkpointLocation = 
checkpointedManager.getStore().getDbLocation().getParentFile();
-        }
-      } catch (Exception e) {
-        LOG.warn("Failed to get checkpoint location for cleanup", e);
+      if (checkpointedManager.getStore() != null &&
+          checkpointedManager.getStore().getDbLocation() != null) {
+        // The checkpoint location is typically the parent directory of the DB 
location
+        checkpointLocation = 
checkpointedManager.getStore().getDbLocation().getParentFile();
       }
-      
-      // Clean up the checkpoint files if we have the location
+    } catch (Exception e) {
+      LOG.warn("Failed to get checkpoint location for cleanup", e);
+    }
+
+    // Close the database connections first, but always attempt to delete the
+    // checkpoint files afterwards - even if stop() throws - so the directory
+    // (a full copy of the OM DB) is never leaked.
+    try {
+      checkpointedManager.stop();
+      LOG.debug("Closed checkpointed OM metadata manager database 
connections");
+    } catch (Exception e) {
+      LOG.warn("Failed to stop checkpointed OM metadata manager", e);
+    } finally {
       if (checkpointLocation != null && checkpointLocation.exists()) {
         try {
           FileUtils.deleteDirectory(checkpointLocation);
-          LOG.debug("Cleaned up checkpoint directory: {}", checkpointLocation);
+          long cleaned = checkpointCleanupCount.incrementAndGet();
+          if (cleaned % CHECKPOINT_CLEANUP_LOG_SAMPLE_RATE == 1) {
+            LOG.info("Cleaned up checkpoint directory: {} (total cleaned so 
far: {})",
+                checkpointLocation, cleaned);
+          } else {
+            LOG.debug("Cleaned up checkpoint directory: {}", 
checkpointLocation);
+          }
         } catch (IOException e) {
           LOG.warn("Failed to cleanup checkpoint directory: {}", 
checkpointLocation, e);
         }
       }
-      
-    } catch (Exception e) {
-      LOG.warn("Failed to cleanup checkpoint files", e);
     }
   }
 
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestReconTaskControllerImpl.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestReconTaskControllerImpl.java
index e9da0f76a0e..b5f742116d9 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestReconTaskControllerImpl.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/tasks/TestReconTaskControllerImpl.java
@@ -17,6 +17,8 @@
 
 package org.apache.hadoop.ozone.recon.tasks;
 
+import static 
org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.getTestReconOmMetadataManager;
+import static 
org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.initializeNewOmMetadataManager;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -26,6 +28,8 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -63,6 +67,7 @@
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 
 /**
  * Class used to test ReconTaskControllerImpl.
@@ -506,27 +511,124 @@ public void testUpdateOMMetadataManager() throws 
Exception {
   
   @Test
   public void testCheckpointManagerCleanupOnQueueFailure() throws Exception {
-    // Set up properly mocked ReconOMMetadataManager with required dependencies
-    ReconOMMetadataManager mockOMMetadataManager = 
mock(ReconOMMetadataManager.class);
+    // Verify the buffer-full branch of queueReInitializationEvent: when the 
freshly
+    // created checkpoint cannot be handed off to the event buffer, it must be 
cleaned
+    // up (not leaked) and the call must return RETRY_LATER.
+
+    // Stop the async processor from setUp so it can't consume buffered events.
+    reconTaskController.stop();
+
+    // Build a controller with a capacity-1 event buffer so a single 
pre-filled event
+    // makes the internal eventBuffer.offer(...) return false (buffer full).
+    OzoneConfiguration ozoneConfiguration = new OzoneConfiguration();
+    ozoneConfiguration.setInt("ozone.recon.om.event.buffer.capacity", 1);
+    ReconTaskStatusUpdaterManager reconTaskStatusUpdaterManagerMock = 
mock(ReconTaskStatusUpdaterManager.class);
+    when(reconTaskStatusUpdaterManagerMock.getTaskStatusUpdater(anyString()))
+        .thenAnswer(i -> {
+          String taskName = i.getArgument(0);
+          return new ReconTaskStatusUpdater(reconTaskStatusDao, taskName);
+        });
+    ReconDBProvider reconDbProvider = mock(ReconDBProvider.class);
+    when(reconDbProvider.getDbStore()).thenReturn(mock(DBStore.class));
+    
when(reconDbProvider.getStagedReconDBProvider()).thenReturn(reconDbProvider);
+    ReconTaskControllerImpl controller = new 
ReconTaskControllerImpl(ozoneConfiguration, new HashSet<>(),
+        reconTaskStatusUpdaterManagerMock, reconDbProvider, 
mock(ReconContainerMetadataManager.class),
+        mock(ReconNamespaceSummaryManager.class), 
mock(ReconGlobalStatsManager.class),
+        mock(ReconFileMetadataManager.class));
+    // Do not start async processing.
+
+    // Checkpointed manager whose cleanup (stop()) we verify.
+    ReconOMMetadataManager mockCheckpointedManager = 
mock(ReconOMMetadataManager.class);
     DBStore mockDBStore = mock(DBStore.class);
     File mockDbLocation = mock(File.class);
-    DBCheckpoint mockCheckpoint = mock(DBCheckpoint.class);
-    Path mockCheckpointPath = Paths.get("/tmp/test/checkpoint");
-    
-    when(mockOMMetadataManager.getStore()).thenReturn(mockDBStore);
+    when(mockCheckpointedManager.getStore()).thenReturn(mockDBStore);
     when(mockDBStore.getDbLocation()).thenReturn(mockDbLocation);
-    when(mockDbLocation.getParent()).thenReturn("/tmp/test");
-    when(mockDBStore.getCheckpoint(any(String.class), 
any(Boolean.class))).thenReturn(mockCheckpoint);
-    
when(mockCheckpoint.getCheckpointLocation()).thenReturn(mockCheckpointPath);
-    
-    reconTaskController.updateOMMetadataManager(mockOMMetadataManager);
-    reconTaskController.stop();
-    
-    // This test verifies the successful path - in practice, queue failure 
after clear is very rare
-    // since we clear the buffer before queueing the reinitialization event
-    ReconTaskController.ReInitializationResult result = 
reconTaskController.queueReInitializationEvent(
+    when(mockDbLocation.getParentFile()).thenReturn(mockDbLocation);
+
+    ReconTaskControllerImpl controllerSpy = spy(controller);
+    // Keep the buffer full through the drain step, and return our checkpoint 
without
+    // touching RocksDB.
+    
doNothing().when(controllerSpy).drainEventBufferAndCleanExistingCheckpoints();
+    
doReturn(mockCheckpointedManager).when(controllerSpy).createOMCheckpoint(any());
+    controllerSpy.updateOMMetadataManager(mock(ReconOMMetadataManager.class));
+
+    // Fill the capacity-1 buffer so the real offer(...) inside the method 
fails.
+    OMUpdateEventBatch fillerBatch = mock(OMUpdateEventBatch.class);
+    
when(fillerBatch.getEventType()).thenReturn(ReconEvent.EventType.OM_UPDATE_BATCH);
+    when(fillerBatch.getEventCount()).thenReturn(1);
+    assertTrue(controllerSpy.getEventBuffer().offer(fillerBatch), 
"precondition: filler event queued");
+
+    ReconTaskController.ReInitializationResult result = 
controllerSpy.queueReInitializationEvent(
         ReconTaskReInitializationEvent.ReInitializationReason.BUFFER_OVERFLOW);
-    assertEquals(ReconTaskController.ReInitializationResult.SUCCESS, result, 
"Should succeed under normal conditions");
+
+    assertEquals(ReconTaskController.ReInitializationResult.RETRY_LATER, 
result,
+        "Buffer-full offer should result in RETRY_LATER");
+    // The fresh checkpoint was never handed off, so it must be cleaned up.
+    verify(mockCheckpointedManager, times(1)).stop();
+  }
+
+  @Test
+  public void testCleanupCheckpointDeletesDirEvenWhenStopThrows(@TempDir File 
tempDir) throws Exception {
+    // Verify the cleanupCheckpoint try/finally: even if stop() throws, the 
checkpoint
+    // directory (a full copy of the OM DB) is still deleted and not leaked.
+
+    // Halt the async processor so the buffered event isn't consumed before we 
drain.
+    reconTaskController.stop();
+    ReconTaskControllerImpl controllerImpl = (ReconTaskControllerImpl) 
reconTaskController;
+
+    // Real on-disk checkpoint directory (with content) that cleanup must 
delete.
+    File checkpointDir = new File(tempDir, 
"temp-recon-reinit-checkpoint_test");
+    assertTrue(checkpointDir.mkdirs(), "precondition: checkpoint dir created");
+    assertTrue(new File(checkpointDir, "CURRENT").createNewFile(), 
"precondition: dir has content");
+
+    ReconOMMetadataManager mockCheckpointedManager = 
mock(ReconOMMetadataManager.class);
+    DBStore mockDBStore = mock(DBStore.class);
+    when(mockCheckpointedManager.getStore()).thenReturn(mockDBStore);
+    // getDbLocation().getParentFile() resolves to the real checkpointDir.
+    when(mockDBStore.getDbLocation()).thenReturn(new File(checkpointDir, 
"om.db"));
+    // stop() throws - cleanup must still delete the directory.
+    doThrow(new IOException("stop 
failed")).when(mockCheckpointedManager).stop();
+
+    controllerImpl.getEventBuffer().offer(new ReconTaskReInitializationEvent(
+        ReconTaskReInitializationEvent.ReInitializationReason.BUFFER_OVERFLOW, 
mockCheckpointedManager));
+
+    controllerImpl.drainEventBufferAndCleanExistingCheckpoints();
+
+    verify(mockCheckpointedManager, times(1)).stop();
+    assertFalse(checkpointDir.exists(),
+        "checkpoint directory must be deleted even when stop() throws");
+  }
+
+  @Test
+  public void testRealCheckpointCreatedThenCleanedUp(
+      @TempDir File dirOmMetadata, @TempDir File dirReconMetadata) throws 
Exception {
+    // End-to-end with real RocksDB (no mocked manager): create a real reinit
+    // checkpoint, then verify the real cleanup path deletes it from disk.
+
+    // Halt the async processor so our explicit drain owns the enqueued event.
+    reconTaskController.stop();
+    ReconTaskControllerImpl controllerImpl = (ReconTaskControllerImpl) 
reconTaskController;
+
+    // Real source OM DB + real RocksDB-backed Recon OM metadata manager.
+    OMMetadataManager omMetadataManager = 
initializeNewOmMetadataManager(dirOmMetadata);
+    ReconOMMetadataManager reconOMMetadataManager =
+        getTestReconOmMetadataManager(omMetadataManager, dirReconMetadata);
+    controllerImpl.updateOMMetadataManager(reconOMMetadataManager);
+
+    // Real checkpoint creation -> temp-recon-reinit-checkpoint_<UUID>/ on 
disk.
+    ReconOMMetadataManager checkpointed = 
controllerImpl.createOMCheckpoint(reconOMMetadataManager);
+    File checkpointDir = 
checkpointed.getStore().getDbLocation().getParentFile();
+    assertTrue(checkpointDir.exists(), "checkpoint dir should exist after 
creation");
+    
assertTrue(checkpointDir.getName().startsWith("temp-recon-reinit-checkpoint"),
+        "checkpoint dir should be the reinit temp dir");
+
+    // Real cleanup path: closes the real RocksDB and deletes the directory.
+    controllerImpl.getEventBuffer().offer(new ReconTaskReInitializationEvent(
+        ReconTaskReInitializationEvent.ReInitializationReason.BUFFER_OVERFLOW, 
checkpointed));
+    controllerImpl.drainEventBufferAndCleanExistingCheckpoints();
+
+    assertFalse(checkpointDir.exists(),
+        "real checkpoint directory must be deleted by the cleanup path");
   }
   
   @Test
@@ -811,7 +913,7 @@ public void 
testProcessReInitializationEventWithCheckpointedManager() throws Exc
     assertFalse(controllerSpy.hasTasksFailed(), "tasksFailed should remain 
false after successful reinitialization");
     
     // Verify cleanup was called on the checkpointed manager
-    verify(mockCheckpointedManager, times(1)).close();
+    verify(mockCheckpointedManager, times(1)).stop();
   }
 
   @Test


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

Reply via email to