[ 
https://issues.apache.org/jira/browse/HDDS-16791?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Siyao Meng updated HDDS-16791:
------------------------------
    Attachment: TestBugMC5UpdateOnlyPurgeRejected.java

> PurgeKeys requests that only carry keysToUpdate are rejected, so a partly 
> reclaimable deleted key is not rewritten and its blocks are resent to SCM
> ---------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16791
>                 URL: https://issues.apache.org/jira/browse/HDDS-16791
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Major
>         Attachments: 
> MC-5-accept-purge-keys-request-with-only-keys-to-update.patch, 
> TestBugMC5UpdateOnlyPurgeRejected.java
>
>
> h3. Mechanism
> When a {{deletedTable}} entry holds one version that can be reclaimed and one 
> that a snapshot still needs, {{KeyDeletingService}} sends the reclaimable 
> blocks to SCM and then puts the entry into {{keysToUpdate}} of a PurgeKeys 
> request, so that OM rewrites the entry with only the retained version. If 
> nothing else in that store can be purged, the request has no deleted keys and 
> no renamed keys. {{OMKeyPurgeRequest.validateAndUpdateCache}} rejects such a 
> request with {{KEY_DELETION_ERROR}} ("No keys found to be purged or renamed 
> in the request.") without looking at {{keysToUpdate}}. The entry is not 
> rewritten and the next run finds the same blocks again.
> The check was added by HDDS-11411 for deleted keys and extended to renamed 
> keys by HDDS-13026. No comment, commit message or test says that a request 
> with only {{keysToUpdate}} should be refused, and {{OMKeyPurgeResponse}} 
> applies {{keysToUpdate}} whenever another key shares the request. HDDS-11411 
> is first contained in release 2.0.0 (by history, not run on older code).
> h3. Trigger
> # Create a key and take a snapshot of the bucket.
> # Overwrite the key with a commit that leaves an allocated block uncommitted. 
> The {{deletedTable}} entry now holds the old version, which the snapshot 
> still references, and the uncommitted blocks, which are reclaimable.
> # {{KeyDeletingService}} runs while that entry is the only reclaimable work 
> of the active object store.
> Default settings, no fault. For the active object store the condition ends 
> when another purgeable key shares the request. Snapshot variant: a second 
> snapshot is taken after step 2 while the entry still holds both versions. The 
> entry then sits in the deleted table of the second snapshot and, if that 
> deleted table holds no fully reclaimable key and no reclaimable rename entry, 
> the request for that snapshot is rejected in every run for as long as both 
> snapshots exist.
> h3. Impact
> * The same block is sent to SCM for deletion in every run of the service 
> (default interval 1m). Run: 3 of 3 runs in both variants, on the OM side with 
> a recording SCM block client. By code reading SCM creates a new delete 
> transaction per call and duplicates are detected by transaction ID, not by 
> block, so every resend is a new SCM transaction and datanode command for a 
> block that is already deleted. That part was not run against a real SCM or 
> datanode.
> * The updates that follow a successful purge are skipped. In the active store 
> variant the exclusive size of the snapshot stayed 0 during the rejected runs 
> and became 268435456 in the first accepted run. In the snapshot variant the 
> second snapshot is never marked as deep cleaned, so it is scanned again in 
> every run.
> * {{keysReclaimedInInterval}} counts the same block again in every run (1, 2, 
> 3 over three runs).
> * No data is lost and no client call fails.
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugMC5UpdateOnlyPurgeRejected.java] ({{hadoop-ozone/ozone-manager}}) 
> drives one real OM per test through {{OzoneManagerProtocol}}, with a 
> recording SCM block client and no datanodes, and calls the service task 
> directly three times. The first test covers the active object store, 
> including the run in which an unrelated deleted key makes the request 
> acceptable. The second covers the snapshot variant. Both print the requests, 
> their responses, the blocks sent to SCM and the content of the entry for 
> every run. A passing test means the defect is present.
> h3. Patch
> [^MC-5-accept-purge-keys-request-with-only-keys-to-update.patch], against 
> a6332fb59879b80615b9233e953d6813d03ae7a8. It also applies to master at 
> 3a22acfaa21.
> {{OMKeyPurgeRequest.validateAndUpdateCache}} rejects a request only when the 
> deleted keys, the renamed keys and {{keysToUpdate}} are all empty. 
> {{OMKeyPurgeResponse}} already applies {{keysToUpdate}}, so no other code 
> change is needed. An accepted request also records the purge transaction, 
> like any other PurgeKeys request. The change is not gated by a layout 
> feature, like HDDS-13026 on the same condition. Not tested with OMs of 
> different versions applying the same log. By code reading, an OM without the 
> change still rejects such a request, so the entry (and for a snapshot the 
> recorded purge transaction) can differ between OMs until the entry is purged 
> or its snapshot is deleted. What remains on the older OM is a reference to 
> blocks that are already deleted.
> Covered by {{testRequestWithOnlyKeysToUpdate}} in the existing 
> {{TestOMKeyPurgeRequestAndResponse}}, which also checks that a request with 
> nothing to purge, update or rename is still rejected. Without the change it 
> fails with "expected: <OK> but was: <KEY_DELETION_ERROR>". With it 
> {{TestOMKeyPurgeRequestAndResponse}}, 
> {{TestOMDirectoriesPurgeRequestAndResponse}}, 
> {{TestOMSnapshotPurgeRequestAndResponse}}, {{TestKeyDeletingService}} and 
> {{TestKeyManagerImpl}} pass (98 tests) and checkstyle is clean. 
> {{TestKeyPurging}} and {{TestSnapshotDeletingServiceIntegrationTest}} on a 
> mini cluster (9 tests) pass in a run that had this patch and a second, 
> unrelated change to {{KeyDeletingService}} applied together. With the patch 
> both tests of the reproduction fail at their first assertion on the response 
> status, and the output of the first run shows the request accepted, the entry 
> rewritten, the exclusive size set and the second snapshot deep cleaned. In a 
> variant of the reproduction without assertions, the second and third run send 
> no block and no PurgeKeys request.
> Not part of the patch: the reclaim metrics are updated whether or not a purge 
> request was applied. This change removes the case that inflated them in every 
> run. Other failed purges are still counted and then counted again by the run 
> that retries them. That is the same kind of issue as HDDS-16437.
> Found by TLA+ model checking and code review of the OM key deletion service 
> and key purge paths under HDDS-15926, on commit 
> a6332fb59879b80615b9233e953d6813d03ae7a8. Checked against HDDS issues and 
> apache/ozone pull requests for duplicates before filing. Related but not 
> duplicates: HDDS-16464 (deep clean flag of a snapshot set too early), 
> HDDS-16755 (a different defect on the same kind of entry), HDDS-16437. The 
> attached patch is a proposal for review. Generated with Specula (Claude Opus 
> 5.5).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to