Siyao Meng created HDDS-16924:
---------------------------------

             Summary: SCM that installed a Ratis snapshot in process keeps 
serving checkpoints from the closed DB, so downloads from it fail once it is 
leader
                 Key: HDDS-16924
                 URL: https://issues.apache.org/jira/browse/HDDS-16924
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: MC-4-serve-scm-checkpoints-from-current-db-store.patch, 
TestBugMC4CheckpointServiceClosedStore.java

h3. Mechanism
{{InterSCMGrpcService}} takes the transaction info table and an 
{{SCMDBCheckpointProvider}} from {{scm.getScmMetadataStore().getStore()}} once, 
in its constructor, and the service is created once per process in the 
{{SCMHAManagerImpl}} constructor. {{SCMHAManagerImpl.installCheckpoint}} closes 
that store ({{stopServices}}, which runs {{SCMMetadataStoreImpl.stop}}) and 
{{startServices}} opens a new one and points the managers at it, but the gRPC 
service is not updated. From then on every {{InterSCMGrpcService.download}} 
reads the closed RocksDB and fails with {{RocksDatabaseException: Rocks 
Database is closed}}. Only a restart of that SCM clears it.

The javadoc of {{SCMHAManagerImpl.reloadSCMState}} says that all classes which 
use or store the metadata manager should be updated with the new instance; this 
one is missed.

h3. Trigger
# An SCM installs a checkpoint in process. With default settings this happens 
on every SCM added with {{--bootstrap}}: Ratis (3.3.1) sends a snapshot 
notification to a bootstrapping follower once, independent of log purging, and 
the new SCM downloads and installs the leader's checkpoint.
# That SCM becomes leader before its next restart (failover or 
{{transferLeadership}}).
# Something downloads a checkpoint from it.

h3. Impact
* Every checkpoint download from that leader fails with gRPC {{UNKNOWN}}, and 
the leader logs "Error streaming SCM DB checkpoint" with "Rocks Database is 
closed" (run).
* Consumers of that download: an SCM being bootstrapped while this SCM is 
leader (see HDDS-16899 for how a bootstrap behaves when the download fails), 
Recon's SCM DB snapshot sync 
({{StorageContainerServiceProviderImpl.getSCMDBSnapshot}} downloads through 
{{InterSCMGrpcClient}} from the leader), and, with 
{{ozone.scm.ha.ratis.log.purge.enabled}}, any follower that lags behind the 
purged log. These are code reading; the run shows the failing download by the 
call a follower makes in {{SCMStateMachine.notifyInstallSnapshotFromLeader}}.
* It lasts until that SCM restarts. Losing leadership does not clear it: 
downloads then go to another SCM, and they fail again whenever this SCM is 
leader before a restart.
* The SCM's own data is not affected. An SCM bootstrapped while this one is 
leader is subject to HDDS-16899 and can end up without DB state that is not in 
the Raft log.

{{SCMDBCheckpointServlet}} ({{/dbCheckpoint}}) stores the store the same way, 
but Jetty initializes it on its first request, so it is affected only if it 
served a request before the install, and no Ozone component uses SCM's 
{{/dbCheckpoint}}. It is not changed by the patch (code reading only). The same 
pattern in the OM checkpoint servlets is HDDS-16878. 
{{SCMDBCheckpointServlet.init}} passes the store to the same 
{{DBCheckpointServlet.initialize}}, so the SCM servlet can follow the fix made 
there.

h3. Reproduction
PASS on the unmodified source, default configuration. 
[^TestBugMC4CheckpointServiceClosedStore.java] 
({{hadoop-ozone/integration-test}}) starts three SCMs with one held back, 
starts the held back SCM C (it bootstraps and installs the leader's checkpoint 
in process, and its original store is closed), checks that a download from 
leader A works, transfers leadership to C and downloads from C through the 
follower's {{SCMSnapshotProvider}}. The download from C fails and C logs "Rocks 
Database is closed". A passing test means the defect is present. With the patch 
the download from C succeeds and the test fails at its {{assertThatThrownBy}}.

h3. Patch
[^MC-4-serve-scm-checkpoints-from-current-db-store.patch], against 
b0aa6475b7856d2c7f467dd3db12b9a1dd116f63. It also applies to master at 
52812559dad.

{{InterSCMGrpcService.download}} looks up the current store on each request and 
builds the transaction info table and the {{SCMDBCheckpointProvider}} from it, 
so the service holds no reference to a store that an install can close. Nothing 
changes for an SCM that never installed a checkpoint.

Covered by an assertion added to 
{{TestSCMInstallSnapshot.testInstallCheckPoint}}: after the in process install 
the SCM serves a checkpoint, and that checkpoint carries the installed 
transaction index. Without the change the download fails with the error above. 
With it {{TestSCMInstallSnapshot}}, {{TestSCMInstallSnapshotWithHA}}, 
{{TestSCMSnapshot}}, {{TestScmHAFinalization}}, {{TestSecretKeySnapshot}} and 
the server-scm {{TestInterSCMGrpcProtocolService}}, {{TestInterSCMGrpcClient}} 
and {{TestSCMSnapshotProvider}} pass, and 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 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]

Reply via email to