[
https://issues.apache.org/jira/browse/HDDS-16929?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Anurag Parvatikar reassigned HDDS-16929:
----------------------------------------
Assignee: Anurag Parvatikar
> SCM follower stops applying the Raft log, while reporting RUNNING, if the
> transaction buffer init fails after a checkpoint install
> ----------------------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-16929
> URL: https://issues.apache.org/jira/browse/HDDS-16929
> Project: Apache Ozone
> Issue Type: Bug
> Reporter: Siyao Meng
> Assignee: Anurag Parvatikar
> Priority: Minor
> Attachments:
> MC-5-fail-reinitialize-when-transaction-buffer-init-fails.patch,
> TestBugMC5BufferInitFailureStaleApplied.java
>
>
> h3. Mechanism
> {{SCMStateMachine.reinitialize}} installs the downloaded checkpoint and then
> calls {{transactionBuffer.init()}} and {{setLastAppliedTermIndex}} inside a
> try block whose catch only logs "Failed to unpause". If {{init()}} throws,
> the state machine still resumes with the transaction info and latest snapshot
> from before the install. Ratis {{StateMachineUpdater.reload}} then takes that
> old snapshot index (-1 for a new SCM) as the applied index. Ratis purged the
> follower's log up to the checkpoint index when it acknowledged the install,
> so the entry after the applied index no longer exists and the updater never
> applies anything again. The leader does not send another install
> notification, because the follower's log is consistent with its own.
> h3. Trigger
> # A follower SCM installs the leader's checkpoint through the normal Ratis
> install notification (for example a new SCM bootstrapping, or a lagging
> follower with {{ozone.scm.ha.ratis.log.purge.enabled}}).
> # {{SCMHADBTransactionBufferImpl.init}} fails during {{reinitialize}}, for
> example a read error on the transaction info key of the newly installed DB.
> The second step is unlikely: {{installCheckpoint}} reads and decodes the same
> key from the checkpoint moments earlier, so it needs a transient read error
> at that instant. In the reproduction it is injected.
> h3. Impact
> * The follower reports RUNNING but never applies another entry and never
> starts its datanode server. It is missing every container created after the
> install.
> * A graceful stop of that SCM never completes, because
> {{StateMachineUpdater}} waits to reach the commit index; the updater thread
> also spins on one core. It has to be killed. Argued, not run: after a restart
> it opens the installed DB and catches up, unless it was elected leader in the
> meantime, because the flush on becoming leader
> ({{SCMStateMachine.notifyLeaderChanged}}) writes the stale transaction info
> into that DB.
> * Argued, not run for this trigger: its log is complete, so it can be elected
> leader, and then no SCM is a ready leader. I ran that outcome for the same
> applied index below log start state reached through a failed checkpoint copy.
> h3. Reproduction
> PASS on unmodified source. [^TestBugMC5BufferInitFailureStaleApplied.java]
> ({{hadoop-ozone/integration-test}}) uses the cluster shape of
> {{TestSCMInstallSnapshotWithHA}} (three SCMs, one started late, so it
> installs the leader's checkpoint through Ratis; log purge enabled, purge gap
> 5, snapshot threshold 5) and injects one {{RocksDatabaseException}} into the
> transaction info read that {{SCMHADBTransactionBufferImpl.init}} does inside
> {{reinitialize}}, with a Mockito spy on the follower's {{SCMMetadataStore}}.
> Result: lifecycle RUNNING, DB transaction index 202, Ratis applied index -1,
> log start 203, commit 238, 16 of 16 later containers missing, datanode server
> not started, about 4.9 s of updater CPU in 5 s, graceful stop still running
> after 20 s. A passing test means the defect is present.
> h3. Patch
> [^MC-5-fail-reinitialize-when-transaction-buffer-init-fails.patch], against
> b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. It also applies to master at
> 52812559dad. It conflicts textually with the patch attached to HDDS-16923 in
> {{SCMStateMachine}} and {{TestSCMStateMachine}}; whichever lands second needs
> a rebase.
> The patch removes the catch, so the failure propagates from {{reinitialize}}
> like a failure of {{installCheckpoint}} already does. Ratis then closes the
> server and SCM shuts down; on restart it opens the installed DB, whose
> transaction info is the checkpoint index, and catches up. With the patch the
> reproduction fails at its first assertion because the follower SCM stops, and
> a restart of that follower applied up to the leader's index and started its
> datanode server (local variant of the reproduction, not attached).
> Covered by {{testReinitializeFailsWhenTransactionBufferInitFails}} and
> {{testReinitializeResumesAtInstalledCheckpoint}} in the existing
> {{TestSCMStateMachine}}. Without the change the first fails with "Expected
> java.io.IOException to be thrown, but nothing was thrown." With it
> {{TestSCMStateMachine}}, {{TestSCMHAManagerImpl}} and
> {{TestSCMHADBTransactionBufferImpl}} (31 tests) and the mini cluster suites
> {{TestSCMInstallSnapshotWithHA}} and {{TestSCMInstallSnapshot}} (5 tests)
> pass, checkstyle is clean.
> Found by TLA+ model checking and code review of the SCM Ratis snapshot and
> checkpoint install paths under HDDS-15926, on commit
> b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. Checked against HDDS and RATIS
> 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]