HDDS-14989. Delay follower SCM DN server start until Ratis log catch-up.#10617
HDDS-14989. Delay follower SCM DN server start until Ratis log catch-up.#10617ArafatKhan2198 wants to merge 7 commits into
Conversation
…ring cluster Reduce test execution time by ~60% (2m28s → ~1m) via three targeted optimizations: 1. Share one cluster across all three test methods (@BeforeAll/@afterall instead of @BeforeEach/@AfterEach). This eliminates 2 of 3 cluster bring-up cycles, which account for ~80-90% of the test duration. Each test uses its own volume/bucket name to avoid collisions on the shared cluster. 2. Lower the datanode heartbeat interval to 1 second in the config. This speeds safe-mode exit at startup and replica re-reporting after the deferred DN-server start, both happening in ~1s instead of default timers. 3. Tighten the waitFor poll interval from 1000ms to 250ms. This allows the test to notice when async conditions (safe-mode exit, leadership transfer) are met sooner, without changing the timeout ceilings. The test essence is fully preserved: 3 SCMs, 3 DNs, 5-minute report interval, down→mutate→restart→catch-up→promote sequence all unchanged. Only the test harness (cluster setup and polling) was optimized. The regression still catches empty replicas on the unfixed code and confirms full replicas on the fix. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
sumitagrawl
left a comment
There was a problem hiding this comment.
@ArafatKhan2198 Thanks for working over this, given few comments
isStateMachineReady is the condition of the StateMachineReadyRule safe-mode rule, so it must be set once the SCM is caught up independent of the deferred datanode-server start. Reusing it as the server-start guard coupled a safe-mode-critical flag to the start path and risked hanging safe mode if the catch-up check misfired. Restore isStateMachineReady to its original semantics (set on leader change and on term catch-up in notifyTermIndexUpdated, each followed by refreshAndValidate) and introduce a separate dnServerStarted flag that guards the one-time datanode protocol server start when isLeader() || isFollowerCaughtUp(). The leaderCommitIndexOnStart capture is now gated on !dnServerStarted since isStateMachineReady flips early again. The fix is preserved: the datanode server is still deferred until catch-up, and the datanode-report safe-mode rules still hold safe mode shut until the server starts and reports arrive, so a promoted follower never serves empty replicas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pled approach) Per review: the deferred datanode server start should simply set isStateMachineReady=true at the same point it starts the server, with no separate flag or extra restructuring. Revert the decoupling change and keep the simpler approach where tryStartDNServerAndRefreshSafeMode() sets isStateMachineReady, starts the datanode protocol server, and refreshes safe mode once the SCM is caught up (isLeader() || isFollowerCaughtUp()). This reverts commit 9e2c2b9. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sumitagrawl
left a comment
There was a problem hiding this comment.
@ArafatKhan2198 overall looks good with Minor comment
Per review: drop the leaderCommit >= 0 guard when capturing the catch-up target in notifyLeaderChanged. A leader change may bring a different leader whose commit index differs, so the target should always be refreshed. getLeaderCommitIndex() returns -1 only when the leader is not known yet, which isFollowerCaughtUp() already treats as uncaptured and re-reads later, so setting it unconditionally is safe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses SCM-HA correctness during follower restart by deferring the SCM datanode protocol server start until the follower has caught up to the leader’s committed Ratis log, preventing early container report processing against stale container state. It also ensures followers do not attempt replicated container state transitions while handling container reports, and adds integration coverage for the restart/catch-up scenarios.
Changes:
- Defer
ScmDatanodeProtocolserver startup in HA mode and start it fromSCMStateMachineonce the SCM is leader or a caught-up follower. - Add follower catch-up detection based on a fixed leader committed index captured at (re)join time, and trigger DN server start/safemode refresh from state machine callbacks.
- Add an integration test suite covering close-while-down, create-while-down, and idle-cluster follower catch-up scenarios.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestSCMFollowerCatchupWithContainerReport.java | New HA integration tests validating replica rebuild correctness after follower restart/catch-up and leadership transfer. |
| hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/StorageContainerManager.java | Defers datanode protocol server start when SCM HA is enabled. |
| hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/ha/SCMStateMachine.java | Starts DN server/safemode refresh after leader promotion or follower catch-up to a captured leader commit index. |
| hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/AbstractContainerReportHandler.java | Avoids replicated lifecycle state transitions on followers during container report handling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What changes were proposed in this pull request?
When an SCM follower restarts in an HA cluster, it used to start talking to datanodes right away, even while it was still catching up on the Ratis log.
That caused problems:
CONTAINER_NOT_FOUNDNotLeaderExceptionThe fix:
SCMStateMachine.Why: Replica locations are rebuilt from datanode reports. Those reports must only be processed after the SCM has replayed all committed Ratis entries.
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-14989
How was this patch tested?
Integration tests
TestSCMFollowerCatchupWithContainerReport -
testFollowerCatchupAfterContainerClose— close-while-down (HDDS-14989 scenario)testFollowerCatchupAfterContainerCreate— create-while-down (CONTAINER_NOT_FOUNDscenario)testFollowerCatchupOnIdleCluster— idle cluster edge caseManual test (docker-compose
ozone-ha)Environment:
hadoop-ozone/dist/target/ozone-2.3.0-SNAPSHOT/compose/ozone-haConfig: RF=3, 3 datanodes,
hdds.container.report.interval=1h,ozone.scm.container.size=1GBProcedure (same for with/without fix):
OZONE_REPLICATION_FACTOR=3 docker compose up -d --scale datanode=3vol1/buck1(containers 1–3)vol1/buck2(creates containers 4, 5, 6 while scm3 is down)ozone admin container infofor containers 4–6Without the fix:
After leadership transfer, containers 4–6 had 1 replica each (expected 3).
With the fix:
CONTAINER_NOT_FOUNDon scm3: 0