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

Siyao Meng updated HDDS-17042:
------------------------------
    Attachment: MC-6-wait-for-delta-hand-off-before-manual-rebuild.patch

> Recon manual task rebuild requested while a delta sync is being applied makes 
> the tasks apply that delta twice
> --------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-17042
>                 URL: https://issues.apache.org/jira/browse/HDDS-17042
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Major
>         Attachments: MC-6-wait-for-delta-hand-off-before-manual-rebuild.patch
>
>
> h3. Mechanism
> {{OzoneManagerServiceProviderImpl.syncDataFromOM}} commits each delta fetched 
> from OM to the Recon OM DB (in {{innerGetAndApplyDeltaUpdatesFromOM}}) and 
> only afterwards writes the task status rows and hands the events to the tasks 
> with {{ReconTaskController.consumeOMEvents}}. {{triggerTaskRebuild}}, behind 
> {{POST /api/v1/triggerdbsync/om/reinit}}, calls 
> {{queueReInitializationEvent}} without any coordination with that sequence. 
> If it runs during or after the commit and before the hand off, it drains the 
> event buffer (which does not hold the new batch yet), takes a checkpoint of 
> the Recon OM DB that already contains the batch, or part of it, since one 
> delta response is committed as several write batches, and queues the 
> reinitialization. The sync thread then buffers the batch behind the 
> reinitialization event, so the tasks first rebuild from a checkpoint that 
> includes all or part of the batch and then process the whole batch again. The 
> rebuild sets every task cursor to the checkpoint's sequence number and 
> nothing skips a batch at or below it, so the second application is never 
> noticed.
> h3. Trigger
> # OM writes a key; the scheduled delta sync of Recon fetches it and commits 
> it to the Recon OM DB.
> # Before that sync hands the events to the tasks, an admin calls {{POST 
> /api/v1/triggerdbsync/om/reinit}}. The call returns 202.
> # The rebuild runs, then the same events are applied on top of it.
> The window is the time from the start of the commit of one delta response to 
> its hand off, so it is short per sync, but under sustained OM writes the sync 
> applies deltas back to back. Only the REST rebuild can hit it: the NSSummary 
> rebuild of the upgrade actions runs before the OM sync is started.
> h3. Impact
> Every event of the batch is applied twice by every task. For NSSummary, file 
> counts and sizes of the affected directories and buckets are wrong (too high 
> for a replayed put, too low for a replayed delete), and the namespace summary 
> and du APIs report them. The file size, container key and table insight 
> counts are affected by the same mechanism (code reading, only NSSummary was 
> run). The task cursors match OM, so later syncs and a restart do not correct 
> it; only another rebuild outside the window does.
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugMC6RebuildDuringSyncDoubleCounts.java] ({{hadoop-ozone/recon}}) uses 
> a real OM RocksDB that serves its write ahead log through a mocked 
> {{getDBUpdates}}, and the real {{OzoneManagerServiceProviderImpl}}, 
> {{ReconTaskControllerImpl}} and {{NSSummaryTask}} with the staged rebuild and 
> swap. The sync thread is paused in {{updateOMMetadataManager}}, which the 
> sync calls between the commit and the hand off, and the rebuild is requested 
> from a second thread. Output: OM has 2 files under the bucket and NSSummary 
> reports 3; after one more ordinary sync OM has 3 and NSSummary 4. A passing 
> test means the defect is present.
> h3. Patch
> [^MC-6-wait-for-delta-hand-off-before-manual-rebuild.patch], against 
> 0665932dd35da4d05087e02748af0a64eb846ad5. It also applies to master at 
> 2264d4d48ac.
> A lock in {{OzoneManagerServiceProviderImpl}} is taken by the sync thread 
> after the OM RPC has returned and before it commits the delta, and released 
> at the end of that sync iteration, after the hand off. {{triggerTaskRebuild}} 
> takes it around {{queueReInitializationEvent}}. The rebuild therefore 
> checkpoints either before the delta is committed (the batch is then applied 
> after the rebuild, once) or after the batch is in the event buffer (it is 
> drained and contained in the checkpoint). The lock is never held during an OM 
> RPC, so a rebuild while OM is unreachable, the bootstrapping case the 
> endpoint exists for, is not delayed. Refusing the rebuild while a sync is 
> running would be simpler but would block that case, because a sync against an 
> unreachable OM spends a long time in RPC retries.
> Covered by {{testTriggerTaskRebuildWaitsForDeltaHandOff}} in the existing 
> {{TestOzoneManagerServiceProviderImpl}}; it fails without the change because 
> the rebuild is queued inside the window. With the change the Recon spi, tasks 
> and sync endpoint suites (200 tests) and {{TestReconWithOzoneManager}} on a 
> mini cluster, including the manual rebuild with OM stopped, pass, and 
> checkstyle is clean. With the patch the reproduction fails at its in window 
> assertion ({{rebuildQueuedInWindow}}), before the count assertions: the 
> rebuild waits for the hand off and NSSummary reports 2 and then 3, matching 
> OM. Totals that are already doubled are not repaired.
> 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-15863 (added the manual rebuild) and HDDS-5146 (a failure 
> between the Recon OM DB update and the task hand off loses the batch). 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