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

ivandika3 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 afa7f0e667c HDDS-13242. getTrashRoots should not be bounded by 
ozone.fs.listing.page.size.max (#11002)
afa7f0e667c is described below

commit afa7f0e667cccb8cf157f07438c290002b004ffd
Author: Ivan Andika <[email protected]>
AuthorDate: Tue Aug 18 09:19:39 2026 +0800

    HDDS-13242. getTrashRoots should not be bounded by 
ozone.fs.listing.page.size.max (#11002)
---
 .../hadoop/ozone/om/TrashOzoneFileSystem.java      |  34 +++++-
 .../hadoop/ozone/om/TestTrashOzoneFileSystem.java  | 133 +++++++++++++++++++++
 2 files changed, 161 insertions(+), 6 deletions(-)

diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/TrashOzoneFileSystem.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/TrashOzoneFileSystem.java
index e147239a5ad..05485f3b8a3 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/TrashOzoneFileSystem.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/TrashOzoneFileSystem.java
@@ -17,6 +17,9 @@
 
 package org.apache.hadoop.ozone.om;
 
+import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FS_LISTING_PAGE_SIZE_DEFAULT;
+import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FS_LISTING_PAGE_SIZE_MAX;
+import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FS_MAX_LISTING_PAGE_SIZE;
 import static org.apache.hadoop.ozone.OzoneConsts.OZONE_O3TRASH_URI_SCHEME;
 import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
 import static 
org.apache.hadoop.ozone.om.helpers.OzoneFSUtils.addTrailingSlashIfNeeded;
@@ -194,13 +197,32 @@ private boolean deleteFSO(OFSPath srcPath) {
   public FileStatus[] listStatus(Path path) throws  IOException {
     ozoneManager.getMetrics().incNumTrashListStatus();
     List<FileStatus> fileStatuses = new ArrayList<>();
+    int pageSize = ozoneConfiguration.getInt(
+        OZONE_FS_LISTING_PAGE_SIZE_MAX,
+        OZONE_FS_LISTING_PAGE_SIZE_DEFAULT);
+    pageSize = (int) OzoneConfigUtil.limitValue(pageSize,
+        OZONE_FS_LISTING_PAGE_SIZE_MAX,
+        OZONE_FS_LISTING_PAGE_SIZE_MAX,
+        OZONE_FS_MAX_LISTING_PAGE_SIZE);
     OmKeyArgs keyArgs = constructOmKeyArgs(path);
-    List<OzoneFileStatus> list = ozoneManager.
-        listStatus(keyArgs, false, null, Integer.MAX_VALUE);
-    for (OzoneFileStatus status : list) {
-      FileStatus fileStatus = convertToFileStatus(status);
-      fileStatuses.add(fileStatus);
-    }
+    String startKey = null;
+    String lastKeyPath = null;
+    int entriesAdded;
+    do {
+      List<OzoneFileStatus> list = ozoneManager.
+          listStatus(keyArgs, false, startKey, pageSize);
+      entriesAdded = 0;
+      for (OzoneFileStatus status : list) {
+        // The server includes the start key itself in the response.
+        if (status.getPath().equals(lastKeyPath)) {
+          continue;
+        }
+        fileStatuses.add(convertToFileStatus(status));
+        lastKeyPath = status.getPath();
+        startKey = status.getKeyInfo().getKeyName();
+        entriesAdded++;
+      }
+    } while (entriesAdded > 0);
     return fileStatuses.toArray(new FileStatus[0]);
   }
 
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestTrashOzoneFileSystem.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestTrashOzoneFileSystem.java
new file mode 100644
index 00000000000..5ee5067bfe5
--- /dev/null
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/TestTrashOzoneFileSystem.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.om;
+
+import static org.apache.hadoop.fs.FileSystem.TRASH_PREFIX;
+import static 
org.apache.hadoop.hdds.HddsConfigKeys.HDDS_CONTAINER_REPORT_INTERVAL;
+import static 
org.apache.hadoop.ozone.OzoneConfigKeys.OZONE_FS_LISTING_PAGE_SIZE_MAX;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.server.ServerUtils;
+import org.apache.hadoop.hdds.utils.db.DBConfigFromFile;
+import org.apache.hadoop.ozone.om.helpers.BucketLayout;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
+import org.apache.hadoop.ozone.om.helpers.OmVolumeArgs;
+import org.apache.hadoop.ozone.om.protocol.OzoneManagerProtocol;
+import org.apache.hadoop.ozone.om.request.OMRequestTestUtils;
+import org.apache.hadoop.security.SecurityUtil;
+import org.junit.jupiter.api.io.TempDir;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * Unit tests for {@link TrashOzoneFileSystem}.
+ */
+class TestTrashOzoneFileSystem {
+
+  private static final int PAGE_SIZE = 5;
+  private static final int TRASH_ROOT_COUNT = 12;
+
+  private final AtomicInteger objectId = new AtomicInteger();
+
+  private OmTestManagers newOmTestManagers(File testDir) throws Exception {
+    OzoneConfiguration conf = new OzoneConfiguration();
+    System.setProperty(DBConfigFromFile.CONFIG_DIR, "/");
+    ServerUtils.setOzoneMetaDirPath(conf, testDir.toString());
+    conf.setTimeDuration(HDDS_CONTAINER_REPORT_INTERVAL, 200, 
TimeUnit.MILLISECONDS);
+    conf.setQuietMode(false);
+    conf.setInt(OZONE_FS_LISTING_PAGE_SIZE_MAX, PAGE_SIZE);
+    return new OmTestManagers(conf);
+  }
+
+  @ParameterizedTest
+  @ValueSource(strings = {"FILE_SYSTEM_OPTIMIZED", "OBJECT_STORE"})
+  void testGetTrashRootsBeyondPageSize(BucketLayout bucketLayout,
+      @TempDir File testDir) throws Exception {
+    OmTestManagers omTestManagers = newOmTestManagers(testDir);
+    try {
+      OzoneManager om = omTestManagers.getOzoneManager();
+      OzoneManagerProtocol writeClient = omTestManagers.getWriteClient();
+      final String volumeName = "vol-" + objectId.incrementAndGet();
+      final String bucketName = "bucket-" + objectId.incrementAndGet();
+      createVolumeAndBucket(omTestManagers, volumeName, bucketName, 
bucketLayout,
+          writeClient);
+      // Create more trash roots than the configured listing page size so that 
a
+      // single listStatus call cannot return all of them.
+      for (int i = 0; i < TRASH_ROOT_COUNT; i++) {
+        createDirectory(writeClient, volumeName, bucketName,
+            TRASH_PREFIX + "/user" + i);
+      }
+
+      try (FileSystem fs = SecurityUtil.doAsLoginUser(
+          (PrivilegedExceptionAction<FileSystem>)
+              () -> new TrashOzoneFileSystem(om))) {
+        Collection<FileStatus> trashRoots = fs.getTrashRoots(true);
+        assertEquals(TRASH_ROOT_COUNT, trashRoots.size());
+      }
+    } finally {
+      omTestManagers.stop();
+    }
+  }
+
+  private void createVolumeAndBucket(OmTestManagers omTestManagers,
+      String volumeName, String bucketName, BucketLayout bucketLayout,
+      OzoneManagerProtocol writeClient) throws IOException {
+    OMRequestTestUtils.addVolumeToOM(omTestManagers.getMetadataManager(),
+        OmVolumeArgs.newBuilder()
+            .setOwnerName("o")
+            .setAdminName("a")
+            .setVolume(volumeName)
+            .setObjectID(objectId.incrementAndGet())
+            .build());
+    OMRequestTestUtils.addBucketToOM(omTestManagers.getMetadataManager(),
+        OmBucketInfo.newBuilder()
+            .setVolumeName(volumeName)
+            .setBucketName(bucketName)
+            .setBucketLayout(bucketLayout)
+            .setOwner("o")
+            .setObjectID(objectId.incrementAndGet())
+            .build());
+    writeClient.createDirectory(new OmKeyArgs.Builder()
+        .setVolumeName(volumeName)
+        .setBucketName(bucketName)
+        .setKeyName(TRASH_PREFIX)
+        .setOwnerName("test")
+        .build());
+  }
+
+  private void createDirectory(OzoneManagerProtocol writeClient,
+      String volumeName, String bucketName, String dirName) throws IOException 
{
+    OmKeyArgs keyArg = new OmKeyArgs.Builder()
+        .setVolumeName(volumeName)
+        .setBucketName(bucketName)
+        .setKeyName(dirName)
+        .setOwnerName("test")
+        .build();
+    writeClient.createDirectory(keyArg);
+  }
+}


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

Reply via email to