From 9912b84743cbb75a9acac085fa0d7f2a5a8ce973 Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:56:59 -0700 Subject: [PATCH 1/4] HDDS-15860. Always rewrite live SSTs before snapshot defrag ingestion --- .../defrag/SnapshotDefragService.java | 28 ++- .../defrag/TestSnapshotDefragService.java | 187 +++++++++++++++--- 2 files changed, 172 insertions(+), 43 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java index 4f018ed4641e..85b6ea2bfcb9 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java @@ -411,22 +411,18 @@ void performIncrementalDefragmentation(SnapshotInfo previousSnapshotInfo, Snapsh for (Map.Entry> entry : tableGroupedDeltaFiles.entrySet()) { String table = entry.getKey(); List deltaFiles = entry.getValue(); - Path fileToBeIngested; - if (deltaFiles.size() == 1 && snapshotVersion > 0) { - // If there is only one delta file for the table and the snapshot version is also not 0 then the same delta - // file can reingested into the checkpointStore. - fileToBeIngested = deltaFiles.get(0); - } else { - Table snapshotTable = snapshot.get().getMetadataManager().getStore() - .getTable(table, StringCodec.get(), CodecBufferCodec.get(true)); - Table previousSnapshotTable = previousSnapshot.get().getMetadataManager().getStore() - .getTable(table, StringCodec.get(), CodecBufferCodec.get(true)); - String tableBucketPrefix = bucketPrefixInfo.getTablePrefix(table); - Pair spillResult = spillTableDiffIntoSstFile(deltaFiles, snapshotTable, - previousSnapshotTable, tableBucketPrefix); - fileToBeIngested = spillResult.getValue() ? spillResult.getLeft() : null; - filesToBeDeleted.add(spillResult.getLeft()); - } + // Delta candidates are live RocksDB SSTs selected at file granularity, + // not valid external SSTs containing an exact bucket-level delta. Always + // rebuild the logical delta, even when there is only one candidate file. + Table snapshotTable = snapshot.get().getMetadataManager().getStore() + .getTable(table, StringCodec.get(), CodecBufferCodec.get(true)); + Table previousSnapshotTable = previousSnapshot.get().getMetadataManager().getStore() + .getTable(table, StringCodec.get(), CodecBufferCodec.get(true)); + String tableBucketPrefix = bucketPrefixInfo.getTablePrefix(table); + Pair spillResult = spillTableDiffIntoSstFile(deltaFiles, snapshotTable, + previousSnapshotTable, tableBucketPrefix); + Path fileToBeIngested = spillResult.getValue() ? spillResult.getLeft() : null; + filesToBeDeleted.add(spillResult.getLeft()); if (fileToBeIngested != null) { if (!fileToBeIngested.toFile().exists()) { throw new IOException("Delta file does not exist: " + fileToBeIngested); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java index f93d95d6ac9e..dda0f7e2805b 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java @@ -52,10 +52,13 @@ import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -82,9 +85,11 @@ import org.apache.hadoop.hdds.utils.db.CodecException; import org.apache.hadoop.hdds.utils.db.DBCheckpoint; import org.apache.hadoop.hdds.utils.db.DBStore; +import org.apache.hadoop.hdds.utils.db.DBStoreBuilder; import org.apache.hadoop.hdds.utils.db.InMemoryTestTable; import org.apache.hadoop.hdds.utils.db.ManagedRawSSTFileReader; import org.apache.hadoop.hdds.utils.db.RDBSstFileWriter; +import org.apache.hadoop.hdds.utils.db.RDBStore; import org.apache.hadoop.hdds.utils.db.RocksDBCheckpoint; import org.apache.hadoop.hdds.utils.db.RocksDatabaseException; import org.apache.hadoop.hdds.utils.db.SstFileSetReader; @@ -122,6 +127,7 @@ import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InOrder; @@ -130,12 +136,18 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.rocksdb.LiveFileMetaData; /** * Unit tests for SnapshotDefragService. */ public class TestSnapshotDefragService { + private enum LiveSstType { + DB_GENERATED, + PREVIOUSLY_INGESTED + } + @Mock private OzoneManager ozoneManager; @@ -224,6 +236,71 @@ private String getFromCodecBuffer(CodecBuffer buffer) { return StringCodec.get().fromCodecBuffer(buffer); } + private void putString(Table table, String key, + String value) throws RocksDatabaseException, CodecException { + table.put(key, StringCodec.get().toDirectCodecBuffer(value)); + } + + private DBStore createDBStore(String name, String tableName) + throws RocksDatabaseException { + return DBStoreBuilder.newBuilder(configuration) + .setName(name) + .setPath(tempDir) + .addTable(tableName) + .build(); + } + + private Path createLiveSstDelta(DBStore sourceStore, String tableName, + String key, LiveSstType liveSstType) throws Exception { + Table sourceTable = sourceStore.getTable( + tableName, StringCodec.get(), CodecBufferCodec.get(true)); + putString(sourceTable, key, "source-value"); + sourceStore.flushDB(); + + if (liveSstType == LiveSstType.PREVIOUSLY_INGESTED) { + File externalFile = tempDir.resolve("external-" + UUID.randomUUID() + + ".sst").toFile(); + try (RDBSstFileWriter writer = new RDBSstFileWriter(externalFile); + CodecBuffer keyBuffer = StringCodec.get().toDirectCodecBuffer(key); + CodecBuffer valueBuffer = StringCodec.get() + .toDirectCodecBuffer("ingested-value")) { + writer.put(keyBuffer, valueBuffer); + } + sourceTable.loadFromFile(externalFile); + } + + LiveFileMetaData liveFile = ((RDBStore) sourceStore).getDb() + .getLiveFilesMetaData().stream() + .max(Comparator.comparingLong(LiveFileMetaData::largestSeqno)) + .orElseThrow(() -> new IllegalStateException("No live SST file")); + Path sourceFile = Paths.get(liveFile.path(), liveFile.fileName()); + Path deltaFile = tempDir.resolve("delta-" + UUID.randomUUID() + ".sst"); + Files.createLink(deltaFile, sourceFile); + return deltaFile; + } + + private void createMockSnapshot(SnapshotInfo snapshotInfo, + DBStore snapshotStore) throws IOException { + OmSnapshot snapshot = mock(OmSnapshot.class); + UncheckedAutoCloseableSupplier snapshotSupplier = + new UncheckedAutoCloseableSupplier() { + @Override + public void close() { + } + + @Override + public OmSnapshot get() { + return snapshot; + } + }; + OMMetadataManager snapshotMetadataManager = mock(OMMetadataManager.class); + when(snapshot.getMetadataManager()).thenReturn(snapshotMetadataManager); + when(snapshotMetadataManager.getStore()).thenReturn(snapshotStore); + when(omSnapshotManager.getActiveSnapshot( + eq(snapshotInfo.getVolumeName()), eq(snapshotInfo.getBucketName()), + eq(snapshotInfo.getName()))).thenReturn(snapshotSupplier); + } + @AfterEach public void tearDown() throws Exception { if (defragService != null) { @@ -639,12 +716,86 @@ public OmSnapshot get() { eq(snapshotInfo.getName()))).thenReturn(snapshotSupplier); } + @ParameterizedTest + @EnumSource(LiveSstType.class) + public void testRewritesSingleLiveSstBeforeIngestion( + LiveSstType liveSstType) throws Exception { + String tableName = "cf1"; + String key = "ab001"; + String previousValue = "previous-value"; + String currentValue = "current-value"; + SnapshotInfo previousSnapshotInfo = createMockSnapshotInfo( + UUID.randomUUID(), "vol1", "bucket1", "snap1"); + SnapshotInfo snapshotInfo = createMockSnapshotInfo( + UUID.randomUUID(), "vol1", "bucket1", "snap2"); + TablePrefixInfo prefixInfo = new TablePrefixInfo( + ImmutableMap.of(tableName, "ab")); + + try (DBStore sourceStore = createDBStore( + "source-" + liveSstType + "-" + UUID.randomUUID(), tableName); + DBStore previousStore = createDBStore( + "previous-" + liveSstType + "-" + UUID.randomUUID(), tableName); + DBStore snapshotStore = createDBStore( + "snapshot-" + liveSstType + "-" + UUID.randomUUID(), tableName); + DBStore checkpointStore = createDBStore( + "checkpoint-" + liveSstType + "-" + UUID.randomUUID(), + tableName)) { + putString(previousStore.getTable( + tableName, StringCodec.get(), CodecBufferCodec.get(true)), + key, previousValue); + previousStore.flushDB(); + putString(snapshotStore.getTable( + tableName, StringCodec.get(), CodecBufferCodec.get(true)), + key, currentValue); + snapshotStore.flushDB(); + createMockSnapshot(previousSnapshotInfo, previousStore); + createMockSnapshot(snapshotInfo, snapshotStore); + Path deltaFile = createLiveSstDelta( + sourceStore, tableName, key, liveSstType); + when(deltaFileComputer.getDeltaFiles(eq(previousSnapshotInfo), + eq(snapshotInfo), eq(ImmutableSet.of(tableName)))) + .thenReturn(ImmutableList.of(Pair.of(deltaFile, + new SstFileInfo(deltaFile.getFileName().toString(), key, key, + tableName)))); + + try (MockedConstruction ignored = mockConstruction( + SstFileSetReader.class, (mock, context) -> when(mock + .getKeyStreamWithTombstone(anyString(), anyString())) + .thenReturn(new ClosableIterator() { + private boolean hasNext = true; + + @Override + public void close() { + } + + @Override + public boolean hasNext() { + return hasNext; + } + + @Override + public String next() { + hasNext = false; + return key; + } + }))) { + defragService.performIncrementalDefragmentation(previousSnapshotInfo, + snapshotInfo, 1, checkpointStore, prefixInfo, + ImmutableSet.of(tableName)); + } + + assertEquals(currentValue, checkpointStore.getTable( + tableName, StringCodec.get(), StringCodec.get()).get(key)); + } + } + /** * Tests the incremental defragmentation process between two snapshots. * *

This parameterized test validates the {@code performIncrementalDefragmentation} method - * across different version scenarios (0, 1, 2, 10) to ensure proper handling of snapshot - * delta files and version-specific optimizations.

+ * across different version scenarios (0, 1, 2, 10) to ensure all snapshot + * delta files are rewritten into fresh external SST files before + * ingestion.

* *

Test Data Generation:

* Creates 67,600 synthetic key-value pairs (26×26×100) distributed across two snapshots @@ -667,26 +818,16 @@ public OmSnapshot get() { *
  • SstFileSetReader mock returns keys with indices 0-4 (i % 6 < 5)
  • * * - *

    Version-Specific Behavior:

    + *

    Expected Behavior:

    *
      - *
    • currentVersion == 0 (initial version): - *
        - *
      • All incremental tables are dumped to new SST files
      • - *
      • All dumped files are ingested into the checkpoint database
      • - *
      - *
    • - *
    • currentVersion > 0 (subsequent versions): - *
        - *
      • Single delta file tables (cf1) are ingested directly without merging
      • - *
      • Multiple delta file tables (cf2) are merged and dumped before ingestion
      • - *
      • Optimization: avoids unnecessary file I/O for single delta files
      • - *
      - *
    • + *
    • Every incremental table is dumped to a fresh external SST file
    • + *
    • All dumped files are ingested into the checkpoint database
    • + *
    • Behavior is independent of snapshot version and delta-file count
    • *
    * *

    Assertions:

    *
      - *
    • Verifies correct tables are dumped and ingested based on version
    • + *
    • Verifies all incremental tables are dumped and ingested
    • *
    • Validates that only modified keys (i % 6 < 3) appear in delta files
    • *
    • Confirms written values match snap2's values or null for deletions
    • *
    • Ensures all incremental tables are ultimately ingested
    • @@ -841,16 +982,8 @@ public String next() { }).when(checkpointDBStore).getTable(anyString()); defragService.performIncrementalDefragmentation(snap1Info, snap2Info, currentVersion, checkpointDBStore, prefixInfo, incrementalTables); - if (currentVersion == 0) { - assertEquals(incrementalTables, new HashSet<>(dumpedFileName.values())); - assertEquals(ingestedFiles, dumpedFileName); - } else { - assertEquals(ImmutableSet.of("cf2"), new HashSet<>(dumpedFileName.values())); - assertEquals("cf1", ingestedFiles.get(deltaFiles.get(0).getLeft().toAbsolutePath().toString())); - assertEquals(ingestedFiles.entrySet().stream().filter(e -> e.getValue().equals( - "cf2")).collect(Collectors.toSet()), dumpedFileName.entrySet().stream().filter(e -> e.getValue().equals( - "cf2")).collect(Collectors.toSet())); - } + assertEquals(incrementalTables, new HashSet<>(dumpedFileName.values())); + assertEquals(ingestedFiles, dumpedFileName); assertEquals(incrementalTables, new HashSet<>(ingestedFiles.values())); for (Map.Entry>> deltaFileContent : deltaFileContents.entrySet()) { int idx = 0; From ca72a52dc86ee9fb68f4e0ce1b71164e2cdd0837 Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:55:13 -0700 Subject: [PATCH 2/4] HDDS-15860. Select ingested SST deterministically in test --- .../defrag/TestSnapshotDefragService.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java index dda0f7e2805b..a23928730b84 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java @@ -58,7 +58,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -256,6 +255,10 @@ private Path createLiveSstDelta(DBStore sourceStore, String tableName, tableName, StringCodec.get(), CodecBufferCodec.get(true)); putString(sourceTable, key, "source-value"); sourceStore.flushDB(); + Set liveFilesBeforeIngestion = ((RDBStore) sourceStore).getDb() + .getLiveFilesMetaData().stream() + .map(LiveFileMetaData::fileName) + .collect(Collectors.toSet()); if (liveSstType == LiveSstType.PREVIOUSLY_INGESTED) { File externalFile = tempDir.resolve("external-" + UUID.randomUUID() @@ -269,10 +272,18 @@ private Path createLiveSstDelta(DBStore sourceStore, String tableName, sourceTable.loadFromFile(externalFile); } - LiveFileMetaData liveFile = ((RDBStore) sourceStore).getDb() + List candidateFiles = ((RDBStore) sourceStore).getDb() .getLiveFilesMetaData().stream() - .max(Comparator.comparingLong(LiveFileMetaData::largestSeqno)) - .orElseThrow(() -> new IllegalStateException("No live SST file")); + .filter(file -> tableName.equals( + StringUtils.bytes2String(file.columnFamilyName()))) + .filter(file -> liveSstType != LiveSstType.PREVIOUSLY_INGESTED || + !liveFilesBeforeIngestion.contains(file.fileName())) + .collect(Collectors.toList()); + if (candidateFiles.size() != 1) { + throw new IllegalStateException("Expected one live SST file, found " + + candidateFiles.size()); + } + LiveFileMetaData liveFile = candidateFiles.get(0); Path sourceFile = Paths.get(liveFile.path(), liveFile.fileName()); Path deltaFile = tempDir.resolve("delta-" + UUID.randomUUID() + ".sst"); Files.createLink(deltaFile, sourceFile); From c45ea869774eec94503997c87039370af04e496d Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Tue, 14 Jul 2026 21:09:07 -0700 Subject: [PATCH 3/4] HDDS-15860. Fix static analysis issues in defrag test --- .../defrag/TestSnapshotDefragService.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java index a23928730b84..c5b0eb08f563 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java @@ -63,6 +63,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -142,11 +143,6 @@ */ public class TestSnapshotDefragService { - private enum LiveSstType { - DB_GENERATED, - PREVIOUSLY_INGESTED - } - @Mock private OzoneManager ozoneManager; @@ -181,6 +177,11 @@ private enum LiveSstType { private Map dummyTableValues; private Set closeSet = new HashSet<>(); + private enum LiveSstType { + DB_GENERATED, + PREVIOUSLY_INGESTED + } + @BeforeEach public void setup() throws IOException { mocks = MockitoAnnotations.openMocks(this); @@ -766,7 +767,7 @@ public void testRewritesSingleLiveSstBeforeIngestion( when(deltaFileComputer.getDeltaFiles(eq(previousSnapshotInfo), eq(snapshotInfo), eq(ImmutableSet.of(tableName)))) .thenReturn(ImmutableList.of(Pair.of(deltaFile, - new SstFileInfo(deltaFile.getFileName().toString(), key, key, + new SstFileInfo(deltaFile.toFile().getName(), key, key, tableName)))); try (MockedConstruction ignored = mockConstruction( @@ -786,6 +787,9 @@ public boolean hasNext() { @Override public String next() { + if (!hasNext) { + throw new NoSuchElementException(); + } hasNext = false; return key; } From 2e6bdbbc692b97e3685bc6ab71072de351fe1aa2 Mon Sep 17 00:00:00 2001 From: Siyao Meng <50227127+smengcl@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:25:37 -0700 Subject: [PATCH 4/4] HDDS-15860. Remove unused snapshot version parameter --- .../defrag/SnapshotDefragService.java | 7 +++--- .../defrag/TestSnapshotDefragService.java | 22 ++++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java index 85b6ea2bfcb9..d96e4869b9d6 100644 --- a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/snapshot/defrag/SnapshotDefragService.java @@ -377,7 +377,6 @@ private Pair spillTableDiffIntoSstFile(List deltaFilePaths, * @param previousSnapshotInfo information about the previous snapshot. * @param snapshotInfo information about the current snapshot for which * incremental defragmentation is performed. - * @param snapshotVersion the version of the snapshot to be processed. * @param checkpointStore the dbStore instance where data * updates are ingested after being processed. * @param bucketPrefixInfo table prefix information associated with buckets, @@ -387,7 +386,7 @@ private Pair spillTableDiffIntoSstFile(List deltaFilePaths, */ @VisibleForTesting void performIncrementalDefragmentation(SnapshotInfo previousSnapshotInfo, SnapshotInfo snapshotInfo, - int snapshotVersion, DBStore checkpointStore, TablePrefixInfo bucketPrefixInfo, Set incrementalTables) + DBStore checkpointStore, TablePrefixInfo bucketPrefixInfo, Set incrementalTables) throws IOException { // Map of delta files grouped on the basis of the tableName. Collection> allTableDeltaFiles = this.deltaDiffComputer.getDeltaFiles( @@ -683,8 +682,8 @@ boolean checkAndDefragSnapshot(SnapshotChainManager chainManager, UUID snapshotI LOG.info("Performing incremental defragmentation for snapshot: {} (ID: {})", snapshotInfo.getTableKey(), snapshotInfo.getSnapshotId()); try { - performIncrementalDefragmentation(checkpointSnapshotInfo, snapshotInfo, needsDefragVersionPair.getValue(), - checkpointDBStore, prefixInfo, COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT); + performIncrementalDefragmentation(checkpointSnapshotInfo, snapshotInfo, checkpointDBStore, prefixInfo, + COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT); perfMetrics.setSnapshotDefragServiceIncLatencyMs(Time.monotonicNow() - defragStart); } catch (IOException e) { snapshotMetrics.incNumSnapshotIncDefragFails(); diff --git a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java index c5b0eb08f563..99beb715c50c 100644 --- a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java +++ b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/snapshot/defrag/TestSnapshotDefragService.java @@ -795,7 +795,7 @@ public String next() { } }))) { defragService.performIncrementalDefragmentation(previousSnapshotInfo, - snapshotInfo, 1, checkpointStore, prefixInfo, + snapshotInfo, checkpointStore, prefixInfo, ImmutableSet.of(tableName)); } @@ -807,10 +807,8 @@ public String next() { /** * Tests the incremental defragmentation process between two snapshots. * - *

      This parameterized test validates the {@code performIncrementalDefragmentation} method - * across different version scenarios (0, 1, 2, 10) to ensure all snapshot - * delta files are rewritten into fresh external SST files before - * ingestion.

      + *

      This test validates that all snapshot delta files are rewritten into + * fresh external SST files before ingestion.

      * *

      Test Data Generation:

      * Creates 67,600 synthetic key-value pairs (26×26×100) distributed across two snapshots @@ -848,13 +846,11 @@ public String next() { *
    • Ensures all incremental tables are ultimately ingested
    • *
    * - * @param currentVersion the snapshot version being defragmented (0 for initial, >0 for subsequent) * @throws Exception if any error occurs during the test execution */ @SuppressWarnings("checkstyle:MethodLength") - @ParameterizedTest - @ValueSource(ints = {0, 1, 2, 10}) - public void testPerformIncrementalDefragmentation(int currentVersion) throws Exception { + @Test + public void testPerformIncrementalDefragmentation() throws Exception { DBStore checkpointDBStore = mock(DBStore.class); String samePrefix = "samePrefix"; String snap1Prefix = "snap1Prefix"; @@ -995,7 +991,7 @@ public String next() { String tableName = i.getArgument(0, String.class); return checkpointTables.get(tableName); }).when(checkpointDBStore).getTable(anyString()); - defragService.performIncrementalDefragmentation(snap1Info, snap2Info, currentVersion, checkpointDBStore, + defragService.performIncrementalDefragmentation(snap1Info, snap2Info, checkpointDBStore, prefixInfo, incrementalTables); assertEquals(incrementalTables, new HashSet<>(dumpedFileName.values())); assertEquals(ingestedFiles, dumpedFileName); @@ -1086,7 +1082,7 @@ public void testCheckAndDefragSnapshotFailure(boolean previousSnapshotExists) th IOException defragException = new IOException("Defrag failed"); if (previousSnapshotExists) { Mockito.doThrow(defragException).when(spyDefragService).performIncrementalDefragmentation( - eq(previousSnapshotInfo), eq(snapshotInfo), eq(10), eq(checkpointDBStore), eq(prefixInfo), + eq(previousSnapshotInfo), eq(snapshotInfo), eq(checkpointDBStore), eq(prefixInfo), eq(COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT)); } else { Mockito.doThrow(defragException).when(spyDefragService).performFullDefragmentation( @@ -1193,7 +1189,7 @@ public void testCheckAndDefragActiveSnapshot(boolean previousSnapshotExists) thr doNothing().when(spyDefragService).performFullDefragmentation(eq(checkpointDBStore), eq(prefixInfo), eq(COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT)); doNothing().when(spyDefragService).performIncrementalDefragmentation(eq(previousSnapshotInfo), - eq(snapshotInfo), eq(10), eq(checkpointDBStore), eq(prefixInfo), + eq(snapshotInfo), eq(checkpointDBStore), eq(prefixInfo), eq(COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT)); AtomicInteger lockAcquired = new AtomicInteger(0); AtomicInteger lockReleased = new AtomicInteger(0); @@ -1242,7 +1238,7 @@ public void testCheckAndDefragActiveSnapshot(boolean previousSnapshotExists) thr eq(COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT)); if (previousSnapshotExists) { verifier.verify(spyDefragService).performIncrementalDefragmentation(eq(previousSnapshotInfo), - eq(snapshotInfo), eq(10), eq(checkpointDBStore), eq(prefixInfo), + eq(snapshotInfo), eq(checkpointDBStore), eq(prefixInfo), eq(COLUMN_FAMILIES_TO_TRACK_IN_SNAPSHOT)); } else { verifier.verify(spyDefragService).performFullDefragmentation(eq(checkpointDBStore), eq(prefixInfo),