This is an automated email from the ASF dual-hosted git repository.
adoroszlai 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 82105bab836 HDDS-15305. `ozone admin container list --all` returns
duplicate containers due to sort/pagination key mismatch (#10300)
82105bab836 is described below
commit 82105bab8360782cf801a149e2a3901bc6937103
Author: sreejasahithi <[email protected]>
AuthorDate: Tue May 19 22:05:16 2026 +0530
HDDS-15305. `ozone admin container list --all` returns duplicate containers
due to sort/pagination key mismatch (#10300)
---
.../hdds/scm/server/SCMClientProtocolServer.java | 3 +-
.../scm/server/TestSCMClientProtocolServer.java | 52 ++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletion(-)
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index 156eed688d8..4a83e9543bc 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -40,6 +40,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -512,7 +513,7 @@ private ContainerListResult listContainerInternal(long
startContainerID, int cou
List<ContainerInfo> containerInfos =
containerStream.filter(info -> info.containerID().getId() >=
startContainerID)
- .sorted().collect(Collectors.toList());
+
.sorted(Comparator.comparing(ContainerInfo::containerID)).collect(Collectors.toList());
List<ContainerInfo> limitedContainers =
containerInfos.stream().limit(count).collect(Collectors.toList());
long totalCount = (long) containerInfos.size();
diff --git
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
index 7d2f399d1fa..964fcb3b0d0 100644
---
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/server/TestSCMClientProtocolServer.java
@@ -29,7 +29,12 @@
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneOffset;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import org.apache.hadoop.hdds.client.RatisReplicationConfig;
import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -155,12 +160,49 @@ public void testScmGetContainerCount() throws IOException
{
scmServer.stop();
}
}
+
+ @Test
+ public void testListContainerPaginationHasNoDuplicates() throws Exception {
+ Instant base = Instant.parse("2026-01-01T00:00:00Z");
+ List<ContainerInfo> infos = new ArrayList<>();
+ infos.add(newContainerWithLastUsedTime(100, base));
+ infos.add(newContainerWithLastUsedTime(5, base.plusMillis(1)));
+ infos.add(newContainerWithLastUsedTime(10, base.plusMillis(2)));
+
+ SCMClientProtocolServer scmServer = new SCMClientProtocolServer(new
OzoneConfiguration(),
+ mockStorageContainerManager(infos),
mock(ReconfigurationHandler.class));
+ try {
+ List<Long> ids = new ArrayList<>();
+ long start = 0;
+ int batchSize = 2;
+ while (true) {
+ List<ContainerInfo> page =
+ scmServer.listContainer(start, batchSize, null, null,
null).getContainerInfoList();
+ if (page.isEmpty()) {
+ break;
+ }
+ for (ContainerInfo c : page) {
+ ids.add(c.getContainerID());
+ }
+ start = page.get(page.size() - 1).getContainerID() + 1;
+ }
+ List<Long> expectedIds = Arrays.asList(5L, 10L, 100L);
+ assertEquals(ids.size(), new HashSet<>(ids).size());
+ assertEquals(expectedIds, ids);
+ } finally {
+ scmServer.stop();
+ }
+ }
private StorageContainerManager mockStorageContainerManager() {
List<ContainerInfo> infos = new ArrayList<>();
for (int i = 0; i < 10; i++) {
infos.add(newContainerInfoForTest());
}
+ return mockStorageContainerManager(infos);
+ }
+
+ private StorageContainerManager
mockStorageContainerManager(List<ContainerInfo> infos) {
ContainerManagerImpl containerManager = mock(ContainerManagerImpl.class);
when(containerManager.getContainers()).thenReturn(infos);
when(containerManager.getContainerStateCount(any(LifeCycleState.class))).thenReturn(infos.size());
@@ -174,6 +216,16 @@ private StorageContainerManager
mockStorageContainerManager() {
return storageContainerManager;
}
+ private ContainerInfo newContainerWithLastUsedTime(long containerId,
+ Instant fixedLastUsedInstant) {
+ return new ContainerInfo.Builder()
+ .setContainerID(containerId)
+ .setClock(Clock.fixed(fixedLastUsedInstant, ZoneOffset.UTC))
+ .setPipelineID(PipelineID.randomId())
+
.setReplicationConfig(RatisReplicationConfig.getInstance(HddsProtos.ReplicationFactor.THREE))
+ .build();
+ }
+
private ContainerInfo newContainerInfoForTest() {
return new ContainerInfo.Builder()
.setContainerID(1)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]