Siyao Meng created HDDS-16119:
---------------------------------

             Summary: DatanodeStorageMetrics leaks a metrics source and its 
MutableVolumeSet per datanode in mini-cluster JVMs
                 Key: HDDS-16119
                 URL: https://issues.apache.org/jira/browse/HDDS-16119
             Project: Apache Ozone
          Issue Type: Bug
            Reporter: Siyao Meng


{{DatanodeStorageMetrics}} (added in HDDS-13128) registers with the metrics 
system under a constant source name and keeps a {{final MutableVolumeSet}} 
reference. {{OzoneContainer}} creates one instance per datanode.

Integration tests run many datanodes in a single JVM and enable 
{{DefaultMetricsSystem.setMiniClusterMode(true)}} (see {{MiniOzoneClusterImpl}} 
and {{MiniOzoneHAClusterImpl}}). In mini-cluster mode the metrics system 
uniquifies duplicate source names, so the second and later datanodes register 
as {{DatanodeStorageMetrics-1}}, {{DatanodeStorageMetrics-2}}, and so on. 
However {{DatanodeStorageMetrics.unregister()}} calls 
{{unregisterSource("DatanodeStorageMetrics")}} using the constant base name, so 
only the first datanode's source is ever removed. Every datanode beyond the 
first leaks its metrics source, and because each leaked source holds a 
{{MutableVolumeSet}}, the entire volume set graph of the shut-down datanode 
stays reachable and cannot be collected.

Within any single test class that stands up multiple datanodes (or builds 
clusters back to back), the leaked sources and their pinned volume sets 
accumulate in that class's JVM until the class finishes. This is a correctness 
and heap-hygiene bug: shut-down datanode state that should be collectable stays 
reachable, and stale {{DatanodeStorageMetrics-N}} sources pile up in the 
metrics registry.

The older {{ContainerMetrics}} uses a similar constant-name register and 
unregister and also leaks its source in mini-cluster mode, but it retains only 
lightweight counters, so it was tolerated. {{DatanodeStorageMetrics}} is 
qualitatively worse because it pins a full datanode volume set.

h3. Reproduction (unit level, no cluster)

With {{DefaultMetricsSystem.setMiniClusterMode(true)}}, create N 
{{DatanodeStorageMetrics}} over real {{MutableVolumeSet}} instances, shut the 
volume sets down, then call {{unregister()}} on each (as 
{{OzoneContainer.stop()}} does), and force GC. Volume sets held only through 
the leaked metrics sources remain reachable. Measured with 15 clusters of 3 
datanodes: 30 of 45 volume sets survived GC with {{DatanodeStorageMetrics}}, 
versus 0 of 45 for the pre-change baseline.

h3. Proposed fix

Register and unregister under a per-instance unique source name, following the 
existing {{VolumeInfoMetrics}} pattern ({{SOURCE_BASENAME + '-' + 
identifier}}). This keeps register and unregister symmetric so no source or 
volume set is leaked. With the fix the same reproduction retains 0 of 45 volume 
sets.

h3. Testing

Unit test that asserts, in mini-cluster mode, that repeated create plus 
unregister cycles leave no residual {{DatanodeStorageMetrics}} sources and that 
shut-down {{MutableVolumeSet}} instances become unreachable after GC.



--
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