Siyao Meng created HDDS-17741:
---------------------------------

             Summary: OM crash during an ordered snapshot diff resubmit can 
leave a DONE job whose report the cleanup then deletes
                 Key: HDDS-17741
                 URL: https://issues.apache.org/jira/browse/HDDS-17741
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: MC-7-replace-job-and-queue-old-report-in-one-write.patch, 
TestBugMC7CrashDuringResubmitLosesDoneReport.java

h3. Mechanism
With {{ozone.om.snapshot.diff.optimized.enabled}} = true (default false), on an 
FSO bucket, an ordered request for a pair whose job is DONE (or QUEUED) with an 
unordered report replaces that job. {{SnapshotDiffManager.createSnapDiffJob}} 
does this with two separate RocksDB writes: 
{{enqueueSnapshotDiffReportCleanup}} puts the old job ID into the purged job 
table, then the new job is put into the job table. If the OM process dies 
between the two writes, or the second write fails without a crash (the case the 
regression test simulates), the old job is still the DONE job of its key while 
its report is queued for deletion. The next {{SnapshotDiffCleanupService}} run 
deletes the report rows of every queued job ID without looking at the job 
table, and {{loadJobsOnStartUp}} only handles IN_PROGRESS jobs.

h3. Trigger
# An unordered snapshot diff of a pair finishes DONE.
# The same pair is submitted with an ordered report.
# The OM process dies after the first write of the resubmit and before the 
second.
# After the restart, a cleanup run happens before the job expires.

h3. Impact
The job stays DONE but its report is gone. Every read of it fails, at the 
moment with the NullPointerException of HDDS-16442 in 
{{checkReportsIntegrity}}, until the job expires (default 7 days) or someone 
submits an ordered request again. With HDDS-16442 fixed, the first read would 
mark the job FAILED and return an error, and the next submit of the pair would 
recompute it (argued from the code, not run). Only the snapshot diff report is 
affected.

h3. Reproduction
PASS, deterministic, unmodified source. 
[^TestBugMC7CrashDuringResubmitLosesDoneReport.java] 
({{hadoop-ozone/ozone-manager}}) runs the real {{SnapshotDiffManager}} and 
{{SnapshotDiffCleanupService}} on a real RocksDB with the rest of the OM 
mocked. A stand in for the report generation task writes three report rows and 
publishes DONE through the real {{updateJobStatusToDone}}. The crash is 
modelled by failing the serialization of the new job, which happens after the 
first write and before the second; the restart is a new {{SnapshotDiffManager}} 
on the same DB. A real process kill was not run. Output on 
d3b75c75bf9ad475551202477c3a21a3f4b968b7: the old job is queued for purge after 
the crash, and after the restart and one cleanup run the job is still DONE with 
0 of 3 report rows, and reading it throws. A passing test means the defect is 
present.

h3. Patch
[^MC-7-replace-job-and-queue-old-report-in-one-write.patch], against 
d3b75c75bf9ad475551202477c3a21a3f4b968b7. It also applies to master at 
bbc8505e00d.

When a previous job exists, {{createSnapDiffJob}} now writes the purged table 
entry of the old job and the new job in one {{ManagedWriteBatch}} 
({{replaceSnapDiffJob}}), so either both are durable or neither is. A first 
submission still uses a plain put. A failed write now fails the resubmit and 
leaves the old job as it was, where it used to be logged while the resubmit 
went on.

Covered by {{testResubmitQueuesReplacedJobForCleanupOnlyWithItsReplacement}} in 
the existing {{TestSnapshotDiffManager}}: with the write of the new job 
failing, the ordered resubmit must leave the DONE job and no purged entry; 
without the failure it must replace the job and queue the old one. Without the 
change the first part fails because the old job is queued. With it 
{{TestSnapshotDiffManager}}, {{TestSnapshotDiffCleanupService}} and 
{{TestSnapshotDiffManagerMXBean}} (88 tests) pass, checkstyle is clean, and the 
reproduction fails because all three rows remain and the read succeeds.

Found by TLA+ model checking and code review of the OM optimized snapshot diff 
paths under HDDS-15926, on commit d3b75c75bf9ad475551202477c3a21a3f4b968b7. 
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
(v10.3.26#10030026)

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

Reply via email to