Siyao Meng created HDDS-17069:
---------------------------------

             Summary: Recon's per datanode open container count drifts from the 
containers that are actually open
                 Key: HDDS-17069
                 URL: https://issues.apache.org/jira/browse/HDDS-17069
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng
         Attachments: CR-2-count-open-containers-per-pipeline-from-state.patch, 
TestBugCR2OpenContainerCountDrift.java

h3. Mechanism
{{NodeEndpoint.getDatanodes}} fills {{openContainers}} of each datanode in 
{{/api/v1/datanodes}} by adding up 
{{ReconContainerManager.getPipelineToOpenContainer()}} over the datanode's 
pipelines. That map is a counter: {{addNewContainer}} increments it and 
{{transitionOpenToClosing}} decrements it, and nothing rebuilds or checks it. 
Three paths make it wrong:
* An UNHEALTHY (or INVALID, DELETED) replica report of an OPEN container. 
Recon's own step, {{checkContainerStateAndUpdate}}, skips 
{{transitionOpenToClosing}} for unhealthy replicas (a check that dates from 
HDDS-4029 and was moved there by HDDS-5126), and SCM's shared 
{{AbstractContainerReportHandler}} then moves the container to CLOSING through 
{{updateContainerState}}, which does not touch the counter. The count stays one 
too high.
* Two datanodes reporting the same new container. 
{{ContainerStateManagerImpl.addContainer}} silently skips a container that 
already exists, but {{addNewContainer}} increments anyway. Reports from 
different datanodes are handled in parallel, and the window includes an SCM 
call.
* Restart. The map starts empty and is not rebuilt from the OPEN containers 
Recon loads, so they count as zero, and the first two paths keep adding to 
whatever is left.

h3. Trigger
A datanode reporting an unhealthy replica of an open container, reports of a 
new container from two of the pipeline's datanodes that race (both pass the 
existence check before either adds the container), or a Recon restart.

h3. Impact
Wrong per datanode open container count in Recon's datanode API and UI, growing 
over the life of a pipeline and reset to zero by each restart. In the attached 
run: two reports of one new container gave a count of 2 with one OPEN 
container; after an UNHEALTHY then a CLOSED report the container was CLOSED and 
the count stayed 1; after a restart the OPEN container was loaded and the 
pipeline had no count. Display only: nothing else reads the counter.

h3. Reproduction
[^TestBugCR2OpenContainerCountDrift.java] goes in {{hadoop-ozone/recon}} 
(target path and Maven command in the class comment) and passes on unmodified 
source when the bug is present. It uses a real {{ReconContainerManager}} and 
{{ReconPipelineManager}} on RocksDB and delivers reports through the real 
{{ReconIncrementalContainerReportHandler}}. Only the SCM RPC peer is mocked. 
The concurrent case handles the second datanode's report inside the first one's 
SCM call, so it is deterministic. The restart case builds a new container 
manager over the same Recon SCM DB.

h3. Patch
[^CR-2-count-open-containers-per-pipeline-from-state.patch], against 
916aa1d9949cbb10f2750a40c8704340893131a2. It also applies to master at 
d77edaa6c15.

The counter is removed. {{getPipelineToOpenContainer()}} now counts Recon's 
OPEN containers per pipeline from {{getContainers(OPEN)}}, which uses the 
container state index, and {{NodeEndpoint.getDatanodes}} calls it once per 
request instead of once per pipeline per datanode. The count can no longer 
drift, and nothing needs rebuilding at startup.

Covered by the new 
{{TestReconContainerManager.testOpenContainerCountWhenContainerAddedAgain}}, 
{{TestReconContainerManager.testOpenContainerCountAfterRestart}} and 
{{TestReconIncrementalContainerReportHandler.testOpenContainerCountAfterUnhealthyReplicaReport}};
 all fail without the change (count 2 instead of 1, no count after the restart, 
and 1 left for a CLOSED container). 
{{testTransitionOpenToClosingDoesNotDecrementCountOnFailure}} set the removed 
counter directly; its check that {{transitionOpenToClosing}} of an unknown 
container throws {{ContainerNotFoundException}} is kept as 
{{testTransitionOpenToClosingOfUnknownContainer}}. With the change the Recon 
{{scm}}, {{fsck}} and {{api}} unit tests pass, checkstyle is clean, and the 
attached tests no longer show the bug.

Found by code review of the datanode container report and Recon container 
tracking paths, as part of the TLA+ verification effort under HDDS-15926, on 
commit 916aa1d9949cbb10f2750a40c8704340893131a2. Checked against HDDS issues 
and apache/ozone pull requests for duplicates before filing. Related but not 
duplicates: HDDS-5314 (resolved, introduced the counter), HDDS-5126 (resolved, 
moved the unhealthy replica check into its current method), HDDS-15308 
(resolved, reworked Recon's report driven transitions), HDDS-14560 (resolved, 
per disk open containers, does not use this counter). 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