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

smengcl 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 80ffb62a841 HDDS-16066. replicas after re-replication should span at 
least 2 racks (#10944)
80ffb62a841 is described below

commit 80ffb62a8413f87cd75c19390c729f0ed53ed421
Author: Han-Wen Hsu <[email protected]>
AuthorDate: Mon Aug 10 04:00:41 2026 +0800

    HDDS-16066. replicas after re-replication should span at least 2 racks 
(#10944)
---
 .../dev-support/findbugsExcludeFile.xml            | 12 -----
 .../hadoop/hdds/scm/TestRackAwarePlacement.java    | 58 ++++++++++++++++------
 2 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/hadoop-ozone/integration-test/dev-support/findbugsExcludeFile.xml 
b/hadoop-ozone/integration-test/dev-support/findbugsExcludeFile.xml
index bbc0b6b17af..55abc263017 100644
--- a/hadoop-ozone/integration-test/dev-support/findbugsExcludeFile.xml
+++ b/hadoop-ozone/integration-test/dev-support/findbugsExcludeFile.xml
@@ -16,16 +16,4 @@
    limitations under the License.
 -->
 <FindBugsFilter>
-  <Match>
-    <Class 
name="org.apache.hadoop.hdds.scm.TestRackAwarePlacement$WithRacksAndHosts"/>
-    <Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/>
-  </Match>
-  <Match>
-    <Class 
name="org.apache.hadoop.hdds.scm.TestRackAwarePlacement$WithRacksOnly"/>
-    <Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/>
-  </Match>
-  <Match>
-    <Class 
name="org.apache.hadoop.hdds.scm.TestRackAwarePlacement$WithHostsOnly"/>
-    <Bug pattern="SIC_INNER_SHOULD_BE_STATIC"/>
-  </Match>
 </FindBugsFilter>
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestRackAwarePlacement.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestRackAwarePlacement.java
index c8258eb0e43..6df252fdc79 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestRackAwarePlacement.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/hdds/scm/TestRackAwarePlacement.java
@@ -28,6 +28,7 @@
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.hadoop.hdds.client.RatisReplicationConfig;
@@ -287,7 +288,9 @@ private static void assertContainerReplicationIsRackAware(
     for (ContainerInfo c : scm.getContainerManager().getContainers()) {
       Set<ContainerReplica> r =
           scm.getContainerManager().getContainerReplicas(c.containerID());
-      if (r.size() >= 3) {
+      // Start with a normally replicated container so stopping one datanode
+      // must trigger creation of a replacement replica.
+      if (r.size() == 3) {
         targetContainer = c;
         replicas = r;
         break;
@@ -311,29 +314,52 @@ private static void assertContainerReplicationIsRackAware(
       }
     }, 500, 30_000);
 
+    waitForRackAwareReplication(scm, containerID, stoppedDn);
+
+    Set<String> racks = getReplicaRacks(scm.getContainerManager()
+        .getContainerReplicas(containerID));
+
+    assertTrue(racks.size() >= 2,
+        "Container replicas after re-replication should span at least "
+            + "2 racks, but were on: " + racks);
+  }
+
+  private static void waitForRackAwareReplication(
+      StorageContainerManager scm, ContainerID containerID,
+      DatanodeDetails stoppedDn)
+      throws TimeoutException, InterruptedException {
     GenericTestUtils.waitFor(() -> {
       try {
-        return scm.getContainerManager()
-            .getContainerReplicas(containerID)
-            .size() >= 3;
+        Set<ContainerReplica> current = scm.getContainerManager()
+            .getContainerReplicas(containerID);
+
+        // Starting with exactly 3 replicas ensures that removing the dead
+        // replica requires a replacement. Use >= here to allow temporary
+        // over-replication while placement repair converges.
+        boolean deadReplicaRemoved = current.stream()
+            .noneMatch(replica -> stoppedDn.equals(
+                replica.getDatanodeDetails()));
+        boolean replicaCountRestored = current.size() >= 3;
+        boolean rackAware = getReplicaRacks(current).size() >= 2;
+
+        // Replica reports and placement repair are asynchronous. Wait for the
+        // replacement and the resulting rack-aware placement to be visible.
+        return deadReplicaRemoved && replicaCountRestored && rackAware;
       } catch (Exception e) {
         return false;
       }
     }, 1_000, 60_000);
+  }
 
-    Set<String> racks = scm.getContainerManager()
-        .getContainerReplicas(containerID)
-        .stream()
-        .map(r -> r.getDatanodeDetails().getNetworkLocation())
+  private static Set<String> getReplicaRacks(
+      Set<ContainerReplica> replicas) {
+    return replicas.stream()
+        .map(replica -> replica.getDatanodeDetails().getNetworkLocation())
         .collect(Collectors.toSet());
-
-    assertTrue(racks.size() >= 2,
-        "Container replicas after re-replication should span at least "
-            + "2 racks, but were on: " + racks);
   }
 
-  private static void assertRackAssignments(MiniOzoneCluster cluster,
-                                            String[] expectedRacks) {
+  private void assertRackAssignments(MiniOzoneCluster cluster,
+                                     String[] expectedRacks) {
     NodeManager nodeManager =
         cluster.getStorageContainerManager().getScmNodeManager();
     List<? extends DatanodeDetails> allNodes = nodeManager.getAllNodes();
@@ -368,8 +394,8 @@ private static void assertRackAssignments(MiniOzoneCluster 
cluster,
     }
   }
 
-  private static void assertHostnameAssignments(MiniOzoneCluster cluster,
-                                                String[] expectedHosts) {
+  private void assertHostnameAssignments(MiniOzoneCluster cluster,
+                                         String[] expectedHosts) {
     NodeManager nodeManager =
         cluster.getStorageContainerManager().getScmNodeManager();
     List<? extends DatanodeDetails> allNodes = nodeManager.getAllNodes();


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

Reply via email to