Siyao Meng created HDDS-17043:
---------------------------------

             Summary: Recon emits a second DELETE event with a stale value when 
a key is deleted twice within one delta sync, and subtracts the key twice
                 Key: HDDS-17043
                 URL: https://issues.apache.org/jira/browse/HDDS-17043
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: MC-4-drop-repeated-delete-event-in-one-recon-delta.patch, 
TestBugMC4DoubleDeleteInOneDelta.java

h3. Mechanism
{{OMDBUpdatesHandler.processEvent}} takes the old value of a key from the 
latest event for that key in the current Recon delta when there is one, and 
from the Recon OM DB otherwise. After a DELETE event that latest value is the 
row that was deleted. The DELETE branch drops an event when the old value is 
null, so a second DELETE of the same key in the same delta is emitted again 
with the stale row, and {{NSSummaryTaskDbEventHandler.handleDeleteKeyEvent}} 
subtracts that key a second time. Without the earlier event the old value would 
be read from the Recon OM DB, where the key is already gone, and the event 
would be dropped.

OM produces this WAL shape in normal operation: {{OzoneManagerDoubleBuffer}} 
writes one flush as one batch, and {{RDBBatchOperation}} keeps only the last 
write per key, so a key that is committed and deleted again within one flush 
reaches the WAL as a bare DELETE.

h3. Trigger
# Key {{k}} exists when Recon last synced.
# OM flush 1: {{k}} is deleted.
# OM flush 2: {{k}} is created again (commit) and deleted again, both applied 
before the same double buffer flush.
# One Recon delta sync covers both flushes.

No fault is needed. Whether both deletes fall into one Recon delta and the 
re-create and delete into one OM flush depends on timing and load; I did not 
run this on a cluster.

h3. Impact
* The bucket (or the FSO parent and its ancestors) loses the key's file count 
and size twice. In the reproduction the bucket ended at 0 files and {{-50}} 
bytes instead of 1 file and 50 bytes.
* The wrong totals are served by the namespace summary and disk usage endpoints 
and are kept by every later incremental sync until a full NSSummary rebuild. OM 
data is not affected.
* Every Recon OM task receives the duplicate DELETE and subtracts it again: 
{{FileSizeCountTask}} decrements the file size bin of the stale value again, 
with no floor; {{OmTableInsightTask}} decrements the table's object count again 
(and, for the open key and deleted tables, the sizes); 
{{ContainerKeyMapperTask}} still finds the key's container rows, which are 
removed only when the batch is written, and decrements each container's key 
count again (argued from the code, not run).
* Since when: OM writes a re-create and delete of a key in one batch as a bare 
DELETE since HDDS-8128, so 1.4.0 and later are affected.

h3. Reproduction
Deterministic, unmodified source. [^TestBugMC4DoubleDeleteInOneDelta.java] 
({{hadoop-ozone/recon}}) applies real {{OMKeyCommitResponse}} and 
{{OMKeyDeleteResponse}} objects to a real OM DB, one batch per flush, reads the 
delta with {{RDBStore.getUpdatesSince}}, iterates each WAL batch into 
{{OMDBUpdatesHandler}} and applies it to the Recon OM DB as 
{{OzoneManagerServiceProviderImpl}} does, and runs {{NSSummaryTaskWithOBS}}. 
The expected totals come from a full rebuild of the same Recon OM DB. With the 
re-create and second delete in one flush, the handler emits two {{DELETE 
/vol1/ob1/k}} events with the same stale value (objectID 2002, 100 bytes) and 
the test fails with {{numOfFiles incremental vs rebuild ==> expected: <1> but 
was: <0>}}. The second test, with the re-create and second delete in separate 
flushes, passes. With the patch both pass.

h3. Patch
[^MC-4-drop-repeated-delete-event-in-one-recon-delta.patch], against 
0665932dd35da4d05087e02748af0a64eb846ad5. It also applies to master at 
2264d4d48ac.

In the DELETE branch of {{OMDBUpdatesHandler.processEvent}}, a DELETE whose 
latest event in this delta is already a DELETE produces no event, as for any 
DELETE of a key Recon does not have. Later events for the key are unchanged. 
{{TestOMDBUpdatesHandler.testOperateOnSameEntry}} asserted the duplicate DELETE 
(7 events); it now expects 6 and keeps its other assertions. Without the change 
it fails with {{expected: <6> but was: <7>}}. With it the existing Recon task 
and handler suites pass and checkstyle is clean.

Found by TLA+ model checking and code review of the Recon namespace summary and 
task sync paths under HDDS-15926, on commit 
0665932dd35da4d05087e02748af0a64eb846ad5. Checked against HDDS issues and 
apache/ozone pull requests for duplicates before filing. 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