Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ void testNodesInDecommissionOrMaintenance(
// a new replica-copy is made to another node.
// For maintenance, there is no replica-copy in this case.
if (!isMaintenance) {
OzoneTestHelper.waitForReplicaCount(containerIdR3, 4, cluster);
OzoneTestHelper.waitForStableReplicaCount(containerIdR3, 4, cluster);
}

compareRMReportToReconResponse(underReplicatedState);
Expand All @@ -299,7 +299,7 @@ void testNodesInDecommissionOrMaintenance(
// There will be a replica copy for both maintenance and decommission.
// maintenance 3 -> 4, decommission 4 -> 5.
int expectedReplicaNum = isMaintenance ? 4 : 5;
OzoneTestHelper.waitForReplicaCount(containerIdR3, expectedReplicaNum, cluster);
OzoneTestHelper.waitForStableReplicaCount(containerIdR3, expectedReplicaNum, cluster);

compareRMReportToReconResponse(underReplicatedState);
compareRMReportToReconResponse(overReplicatedState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.apache.hadoop.hdds.scm.container.ContainerManager;
import org.apache.hadoop.hdds.scm.container.ContainerNotFoundException;
import org.apache.hadoop.hdds.scm.container.ContainerReplica;
import org.apache.hadoop.hdds.scm.container.replication.ReplicationManager;
import org.apache.hadoop.hdds.scm.events.SCMEvents;
import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
import org.apache.hadoop.hdds.scm.pipeline.PipelineNotFoundException;
Expand Down Expand Up @@ -465,6 +466,22 @@ public static void waitForReplicaCount(long containerID, int count,
200, 30000);
}

/**
* Like {@link #waitForReplicaCount(long, int, MiniOzoneCluster)}, but only returns once
* replication has quiesced: no pending add or delete ops remain for the container, so the count
* has settled at {@code count} instead of being observed transiently while SCM is still adding or
* removing replicas. This removes the race where the count passes through {@code count} between
* polls under a loaded runner (HDDS-10582, HDDS-11128).
*/
public static void waitForStableReplicaCount(long containerID, int count, MiniOzoneCluster cluster)
throws TimeoutException, InterruptedException {
ReplicationManager replicationManager = cluster.getStorageContainerManager().getReplicationManager();
ContainerID cid = ContainerID.valueOf(containerID);
GenericTestUtils.waitFor(() ->
replicationManager.getPendingReplicationOps(cid).isEmpty() && countReplicas(containerID, cluster) == count,
200, 30000);
}

/**
* Wait until SCM reports exactly {@code count} replicas for the container and every replica is in {@code state}.
* Unlike {@link #waitForContainerStateInSCM}, which checks the container's aggregate state (it flips as soon as the
Expand Down
Loading