This is an automated email from the ASF dual-hosted git repository.

devesh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 29ff00a8f56 HDDS-14368. Recon showing wrong pipelines for containers. 
(#9707)
29ff00a8f56 is described below

commit 29ff00a8f56d97e039009a065a49cd4abd68cde6
Author: Devesh Kumar Singh <[email protected]>
AuthorDate: Thu Feb 5 09:20:38 2026 +0530

    HDDS-14368. Recon showing wrong pipelines for containers. (#9707)
---
 .../hadoop/ozone/recon/api/ContainerEndpoint.java  |  2 +-
 .../ozone/recon/api/TestContainerEndpoint.java     | 98 ++++++++++++++++++++++
 2 files changed, 99 insertions(+), 1 deletion(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ContainerEndpoint.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ContainerEndpoint.java
index 49fab38fcf2..c1818b84fae 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ContainerEndpoint.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/ContainerEndpoint.java
@@ -659,11 +659,11 @@ public Response getContainerMisMatchInsights(
           }
         }
 
-        List<Pipeline> pipelines = new ArrayList<>();
         nonOMContainers.forEach(containerInfo -> {
           ContainerDiscrepancyInfo containerDiscrepancyInfo = new 
ContainerDiscrepancyInfo();
           
containerDiscrepancyInfo.setContainerID(containerInfo.getContainerID());
           containerDiscrepancyInfo.setNumberOfKeys(0);
+          List<Pipeline> pipelines = new ArrayList<>();
           PipelineID pipelineID = null;
           try {
             pipelineID = containerInfo.getPipelineID();
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
index 3b0764ba3fc..19f1593db66 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestContainerEndpoint.java
@@ -26,8 +26,10 @@
 import static 
org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.writeKeyToOm;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -1596,6 +1598,102 @@ public void testContainerMissingFilter()
     assertThat(missingContainerIdsSCM).contains(2L);
   }
 
+  /**
+   * Helper to create a container in SCM with a specific pipeline.
+   */
+  private void createContainerInSCM(long containerId, Pipeline targetPipeline)
+      throws IOException, TimeoutException {
+    ContainerInfo containerInfo = new ContainerInfo.Builder()
+        .setContainerID(containerId)
+        .setReplicationConfig(
+            RatisReplicationConfig.getInstance(ReplicationFactor.THREE))
+        .setState(HddsProtos.LifeCycleState.OPEN)
+        .setOwner("owner" + containerId)
+        .setNumberOfKeys(0)
+        .setPipelineID(targetPipeline.getId())
+        .build();
+    reconContainerManager.addNewContainer(
+        new ContainerWithPipeline(containerInfo, targetPipeline));
+  }
+
+  /**
+   * Helper to verify pipeline isolation for a container missing in OM.
+   */
+  private void verifyPipelineIsolation(ContainerDiscrepancyInfo info,
+      long containerId, PipelineID expectedPipelineId,
+      List<List<Pipeline>> otherPipelineLists) {
+    List<Pipeline> pipelines = info.getPipelines();
+    assertNotNull(pipelines);
+    assertEquals(1, pipelines.size(),
+        "Container " + containerId + " should have exactly 1 pipeline");
+    assertEquals(expectedPipelineId, pipelines.get(0).getId(),
+        "Container " + containerId + " should have correct pipeline");
+    assertEquals("SCM", info.getExistsAt());
+    assertEquals(0, info.getNumberOfKeys());
+    // Verify list isolation
+    for (List<Pipeline> other : otherPipelineLists) {
+      if (other != null) {
+        assertNotSame(pipelines, other,
+            "Container " + containerId + " should have independent list");
+      }
+    }
+  }
+
+  @Test
+  public void testGetContainerInsightsNonOMContainersPipelineIsolation()
+      throws IOException, TimeoutException {
+    // Verifies fix for pipeline accumulation bug: containers missing in OM
+    // should each have their own isolated pipeline list, not shared.
+    
+    // Create 3 different pipelines
+    Pipeline[] pipelines = {
+        getRandomPipeline(), getRandomPipeline(), getRandomPipeline()
+    };
+    for (Pipeline p : pipelines) {
+      reconPipelineManager.addPipeline(p);
+    }
+    
+    // Create 3 containers in SCM with different pipelines (not in OM)
+    long[] containerIds = {501L, 502L, 503L};
+    for (int i = 0; i < containerIds.length; i++) {
+      createContainerInSCM(containerIds[i], pipelines[i]);
+      
assertFalse(reconContainerMetadataManager.doesContainerExists(containerIds[i]),
+          "Container " + containerIds[i] + " should NOT exist in OM");
+    }
+    
+    // Call API
+    Response response = containerEndpoint.getContainerMisMatchInsights(10, 
500, "OM");
+    assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+    
+    Map<String, Object> responseMap = (Map<String, Object>) 
response.getEntity();
+    List<ContainerDiscrepancyInfo> discrepancies =
+        (List<ContainerDiscrepancyInfo>) 
responseMap.get("containerDiscrepancyInfo");
+    assertNotNull(discrepancies);
+    
+    // Find containers in response
+    ContainerDiscrepancyInfo[] infos = new ContainerDiscrepancyInfo[3];
+    for (int i = 0; i < containerIds.length; i++) {
+      final long id = containerIds[i];
+      infos[i] = discrepancies.stream()
+          .filter(d -> d.getContainerID() == id)
+          .findFirst()
+          .orElseThrow(() -> new AssertionError(
+              "Container " + id + " not found in mismatch list"));
+    }
+    
+    // Verify pipeline isolation for each container
+    List<Pipeline> pipelineList1 = infos[0].getPipelines();
+    List<Pipeline> pipelineList2 = infos[1].getPipelines();
+    List<Pipeline> pipelineList3 = infos[2].getPipelines();
+    
+    verifyPipelineIsolation(infos[0], containerIds[0], pipelines[0].getId(),
+        Arrays.asList(pipelineList2, pipelineList3));
+    verifyPipelineIsolation(infos[1], containerIds[1], pipelines[1].getId(),
+        Arrays.asList(pipelineList1, pipelineList3));
+    verifyPipelineIsolation(infos[2], containerIds[2], pipelines[2].getId(),
+        Arrays.asList(pipelineList1, pipelineList2));
+  }
+
   @Test
   public void testGetOmContainersDeletedInSCM() throws Exception {
     Map<Long, ContainerMetadata> omContainers =


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to