HDDS-13217. Test that snapshot checkpoint content is preserved after defrag - #10951
HDDS-13217. Test that snapshot checkpoint content is preserved after defrag#10951arunsarin85 wants to merge 12 commits into
Conversation
…adata to live OM for a bucket
…rag. Address review feedback on PR apache#10235: compare each snapshot checkpoint against its version-0 baseline before and after defrag iterations, including after deleting a middle snapshot. Rebased onto upstream master.
Use Java 8 compatible Collections.singletonMap, correct OmSnapshot and UncheckedAutoCloseableSupplier imports.
…oss-test interference on the snapshot defrag chain.
There was a problem hiding this comment.
Pull request overview
This PR adds a new OM integration test to ensure snapshot defragmentation preserves the checkpoint RocksDB metadata for a bucket prefix across defrag iterations, including a follow-up defrag after deleting/purging a middle snapshot in the snapshot chain (HDDS-13217).
Changes:
- Introduces
TestOmSnapshotCheckpointDbContentintegration test that snapshots a bucket (S1/S2/S3), captures version-0 checkpoint baselines, triggers defrag, and verifies post-defrag metadata matches baselines. - Adds a second scenario that deletes/purges S2 after an initial defrag and verifies S3 remains consistent after a subsequent defrag pass.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| conf = new OzoneConfiguration(); | ||
| conf.setBoolean(OZONE_FILESYSTEM_SNAPSHOT_ENABLED_KEY, true); | ||
| conf.setInt(OZONE_SNAPSHOT_DEFRAG_SERVICE_INTERVAL, 7200); | ||
| conf.setInt(SNAPSHOT_DEFRAG_LIMIT_PER_TASK, 10); | ||
| conf.setTimeDuration(OZONE_SNAPSHOT_DELETING_SERVICE_INTERVAL, 1, TimeUnit.SECONDS); |
| private void triggerDefragUntilDone(List<SnapshotInfo> snapshots) | ||
| throws TimeoutException, InterruptedException { | ||
| OzoneManager om = cluster.getOzoneManager(); | ||
| for (SnapshotInfo snapshotInfo : snapshots) { | ||
| GenericTestUtils.waitFor(() -> { | ||
| if (isSnapshotDefragComplete(snapshotInfo)) { | ||
| return true; | ||
| } | ||
| try { | ||
| om.triggerSnapshotDefrag(false); | ||
| } catch (IOException e) { | ||
| return false; | ||
| } | ||
| return isSnapshotDefragComplete(snapshotInfo); | ||
| }, 2000, DEFRAG_WAIT_MS); | ||
| } | ||
| } |
| assertEquals(expected, readPrefix(current, prefix), tableName); | ||
| } | ||
|
|
||
| private static <V> SortedMap<String, V> readPrefix( |
There was a problem hiding this comment.
The helper method name doesn't convery its intent.
Filter tables whose key starts with prefix prefix, and add them to a sorted map.
There was a problem hiding this comment.
Sure ! Renamed the method .
jojochuang
left a comment
There was a problem hiding this comment.
just a few cosmetic comments
| return OmMetadataManagerImpl.createCheckpointMetadataManager(conf, checkpoint); | ||
| } | ||
|
|
||
| private static Map<String, SortedMap<String, ?>> readAllBucketPrefixTables( |
There was a problem hiding this comment.
collects the snapshot’s OM metadata for just the tables that matter to a bucket an
There was a problem hiding this comment.
added Javadoc explaining it collects snapshot OM metadata for bucket-relevant tables and returns sorted maps keyed by table name.
…llBucketPrefixTables.
adoroszlai
left a comment
There was a problem hiding this comment.
Thanks @arunsarin85 for the patch.
There is a checkstyle failure. Please wait for clean CI run in fork before opening PR.
| * <p>Each test method starts a fresh MiniOzone cluster to avoid cross-test interference on the | ||
| * global snapshot defrag chain. | ||
| */ | ||
| @Timeout(value = 15, unit = TimeUnit.MINUTES) |
There was a problem hiding this comment.
Please don't add timeout, see HDDS-12575.
| @Timeout(value = 15, unit = TimeUnit.MINUTES) |
| IOUtils.closeQuietly(client); | ||
| IOUtils.closeQuietly(cluster); |
There was a problem hiding this comment.
nit: merge the calls, closeQuietly accepts multiple objects
| /** | ||
| * Test#1 from HDDS-13217: create S1, S2, S3 on one bucket, run defrag, and verify each | ||
| * defragged checkpoint still matches its version-0 baseline. | ||
| */ | ||
| @Test | ||
| public void testDefragPreservesSnapshotCheckpointContent() | ||
| throws Exception { | ||
| ThreeSnapshotSetup setup = createThreeSnapshotsOnNewBucket(); | ||
| triggerDefragUntilDone(setup.snapshots); | ||
| assertCheckpointMatchesBaseline(setup.baselines, setup.snapshots); | ||
| } | ||
|
|
||
| /** | ||
| * Test#2 from HDDS-13217: after an initial defrag pass, delete the middle snapshot, run defrag | ||
| * again, and verify the remaining youngest snapshot checkpoint still matches its baseline. | ||
| */ | ||
| @Test | ||
| public void testDefragAfterSnapshotDeletePreservesRemainingSnapshot() | ||
| throws Exception { | ||
| ThreeSnapshotSetup setup = createThreeSnapshotsOnNewBucket(); | ||
| triggerDefragUntilDone(setup.snapshots); |
There was a problem hiding this comment.
It looks like test2's initial steps match test1's steps. Please merge them to reduce time.
Thanks for running flaky-test-check. There was one timeout, please check: |
|
Thanks @arunsarin85 for the test additions. |
| private ThreeSnapshotSetup createThreeSnapshotsOnNewBucket() | ||
| throws IOException, InterruptedException, TimeoutException { | ||
| OzoneBucket bucket = | ||
| DataTestUtil.createVolumeAndBucket(client, BucketLayout.OBJECT_STORE); |
There was a problem hiding this comment.
Please cover the FSO defrag path too. This setup hard-codes OBJECT_STORE, so the test validates keyTable only. Snapshot defrag reconstructs keyTable, directoryTable, and fileTable; the current integration test never checks two of those three tables. Add an FSO bucket to the merged scenario and compare its directory and file tables with their version-0 baselines.
There was a problem hiding this comment.
Thanks for the review .
The test now runs the flow for both OBS and FSO buckets.
https://github.com/arunsarin85/ozone/actions/runs/31029322914
| DataTestUtil.createKey(bucket, "key-s1", TEST_KEY_CONTENT); | ||
| store.createSnapshot(volumeName, bucketName, "snap-s1"); | ||
|
|
||
| DataTestUtil.createKey(bucket, "key-s2", TEST_KEY_CONTENT); |
There was a problem hiding this comment.
Please include an overwrite and a delete between the snapshots. The current sequence only adds keys, so this end-to-end test exercises insert deltas but cannot detect a regression in update or tombstone reconstruction. For example, overwrite one S1 key before S2 and delete another key before S3, then compare each defragged checkpoint with its baseline.
There was a problem hiding this comment.
Thanks for the review .
The snapshot sequence now includes insert, update, and tombstone cases: S1 creates key-a and key-b, we overwrite key-a before S2 and add key-s2, then delete key-b before S3 and add key-s3. After each defrag pass, we still verify the checkpoint matches its version-0 baseline.
https://github.com/arunsarin85/ozone/actions/runs/31029322914
…ls, and combine both defrag scenarios into a single test
|
Thanks @arunsarin85 for updating the patch. |
What changes were proposed in this pull request?
This PR adds an integration test, TestOmSnapshotCheckpointDbContent, to verify that snapshot checkpoint DB metadata for a bucket prefix is preserved across snapshot defrag iterations (HDDS-13217).
Please describe your PR in detail:
This PR adds a new integration test, TestOmSnapshotCheckpointDbContent, to verify that snapshot checkpoint DB metadata for a bucket prefix is preserved across snapshot defrag iterations (HDDS-13217).
The test uses a dedicated MiniOzone cluster with snapshot defrag enabled and covers two scenarios:
Because version-0 checkpoint directories are removed after defrag, the test captures baselines before the first defrag and compares against the active snapshot view after defrag completes.
Each test method starts a fresh cluster to avoid cross-test interference on the snapshot defrag chain.
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-13217
How was this patch tested?
https://github.com/arunsarin85/ozone/actions/runs/30941614952