[
https://issues.apache.org/jira/browse/HDDS-17050?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Siyao Meng updated HDDS-17050:
------------------------------
Attachment: TestBugMC7FailedBatchLostAcrossRestart.java
> Recon task cursor advances past a batch that failed both attempts, so a
> restart soon after the failure can lose that batch
> --------------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-17050
> URL: https://issues.apache.org/jira/browse/HDDS-17050
> Project: Apache Ozone
> Issue Type: Bug
> Reporter: Siyao Meng
> Priority: Minor
> Attachments:
> MC-7-skip-batches-behind-failed-batch-until-reinit.patch,
> TestBugMC7FailedBatchLostAcrossRestart.java
>
>
> h3. Mechanism
> When a delta batch fails both attempts in
> {{ReconTaskControllerImpl.processOMUpdateBatch}}, the controller only sets
> the in memory {{tasksFailed}} flag; the next sync iteration turns it into a
> reinitialization. Batches that are already in the event buffer behind the
> failed one are still processed, and for each task that succeeds
> {{processTasks}} saves {{lastUpdatedSeqNumber}} to the task status table. The
> cursor of the failed task therefore reaches the cursor of {{OmDeltaRequest}}.
> If Recon restarts before the reinitialization has finished and before the
> sync has fetched any new OM update, the flag and the queued reinitialization
> are gone, and the startup check in {{OzoneManagerServiceProviderImpl.start}},
> which rebuilds only tasks whose cursor is below that of {{OmDeltaRequest}},
> finds nothing to do. The failed batch is never applied.
> The same happens when a manual rebuild drains a buffered batch and the
> rebuild's reprocess step then fails, because that failure also only sets
> {{tasksFailed}} (code reading, not run). A rebuild that fails in its DB swap
> sets no flag at all, because {{reInitializeTasks}} still reports success;
> HDDS-17047 makes it report the failure.
> h3. Trigger
> # The sync buffers two batches before the event thread gets to the first, as
> when it fetches several deltas in one run.
> # A task fails the first batch on both attempts and succeeds on the second
> batch. The failure has to be tied to the first batch; a Recon RocksDB I/O
> error closes the DB, so the second batch would fail too. One such failure is
> HDDS-17048: {{NSSummaryTask}} fails with a NullPointerException, on both
> attempts, on a key event whose bucket was deleted later in the same delta,
> while a later batch about other buckets succeeds (code reading).
> # Recon restarts after the event thread has processed the buffered batches
> and before the sync fetches any new OM update. A non empty fetch after the
> failure moves the {{OmDeltaRequest}} cursor past the task cursors, because
> the batch is refused or drained, and the startup check then rebuilds. On a
> cluster with ongoing writes this leaves about one sync interval (5s by
> default). Without new writes, it lasts until the queued reinitialization has
> completed.
> h3. Impact
> The changes of the failed batch are missing from that task's derived data for
> good: for NSSummary the namespace summary and du APIs report too few files
> and bytes. Later syncs and restarts do not notice it; a manual rebuild
> repairs it. Without a restart the reinitialization repairs it as designed.
> h3. Reproduction
> PASS, deterministic, unmodified source.
> [^TestBugMC7FailedBatchLostAcrossRestart.java] ({{hadoop-ozone/recon}}) uses
> a real OM RocksDB that serves its write ahead log through a mocked
> {{getDBUpdates}}, and the real {{OzoneManagerServiceProviderImpl}},
> {{ReconTaskControllerImpl}}, {{NSSummaryTask}} and task status table.
> {{NSSummaryTask.process}} returns a failed result for one batch on both
> attempts, and its first attempt is held until the next batch is buffered. The
> restart stops the provider and controller and starts new ones on the same
> databases. Output before the restart: {{tasksFailed}} true, NSSummaryTask
> cursor 5, OmDeltaRequest cursor 5, OM has 3 files under the bucket and
> NSSummary 2. After the restart and a sync NSSummary still reports 2; a
> rebuild gives 3. A passing test means the defect is present.
> h3. Patch
> [^MC-7-skip-batches-behind-failed-batch-until-reinit.patch], against
> 0665932dd35da4d05087e02748af0a64eb846ad5. It also applies to master at
> 2264d4d48ac.
> {{processOMUpdateBatch}} does not run the tasks while {{tasksFailed}} is set.
> In that state {{consumeOMEvents}} already refuses new batches, and queueing
> the reinitialization drains the buffer, clears the flag and takes the
> checkpoint the rebuild uses, which contains every batch applied to the Recon
> OM DB, so the skipped batches would be discarded by it anyway. Not processing
> them keeps the failed task's cursor behind, and the existing startup check
> rebuilds after a restart. Without a restart nothing changes, except that
> until the reinitialization is queued (normally the next sync iteration) the
> tasks that did not fail also stop applying buffered batches, which the
> reinitialization rebuilds.
> Covered by {{testBatchesBehindFailedBatchDoNotAdvanceTaskCursor}} in the
> existing {{TestReconTaskControllerImpl}}, which fails without the change
> ({{expected: 0L but was: 200L}}). With the change the Recon tasks suites and
> {{TestOzoneManagerServiceProviderImpl}} (155 tests) pass and checkstyle is
> clean. With the patch the reproduction fails at its undercount assertion: the
> NSSummaryTask cursor stays at 3, the restart rebuilds the tasks and NSSummary
> reports 3.
> A related case, a task whose {{process}} throws instead of returning a failed
> result and so never sets {{tasksFailed}}, is HDDS-17040.
> 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. Related but not
> duplicates: HDDS-5146 (a failure between the Recon OM DB update and the task
> hand off loses the batch) and HDDS-16463 (sync the Recon DB before the cursor
> advances). 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]