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 f98eac2099 HDDS-11561. Refactor Open Key Search Endpoint and 
Consolidate with OmDBInsightEndpoint Using StartPrefix Parameter. (#7336)
f98eac2099 is described below

commit f98eac2099ff979364a501bdb219bc5f9be4a595
Author: Arafat2198 <[email protected]>
AuthorDate: Tue Nov 26 20:36:39 2024 +0530

    HDDS-11561. Refactor Open Key Search Endpoint and Consolidate with 
OmDBInsightEndpoint Using StartPrefix Parameter. (#7336)
---
 .../org/apache/hadoop/ozone/recon/ReconUtils.java  |  99 ++++++
 .../ozone/recon/api/OMDBInsightEndpoint.java       | 227 +++++++------
 .../ozone/recon/api/OMDBInsightSearchEndpoint.java | 350 ---------------------
 .../ozone/recon/api/TestOmDBInsightEndPoint.java   |  57 ++--
 ...dpoint.java => TestOpenKeysSearchEndpoint.java} | 170 ++++++----
 5 files changed, 367 insertions(+), 536 deletions(-)

diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
index 407694bf85..12139e1772 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/ReconUtils.java
@@ -55,6 +55,7 @@ import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
 import org.apache.hadoop.hdds.scm.ScmUtils;
 import org.apache.hadoop.hdds.scm.ha.SCMNodeDetails;
+import org.apache.hadoop.hdds.scm.server.OzoneStorageContainerManager;
 import org.apache.hadoop.hdds.scm.server.SCMDatanodeHeartbeatDispatcher;
 import org.apache.hadoop.hdds.utils.HddsServerUtil;
 import org.apache.hadoop.hdds.utils.db.Table;
@@ -78,8 +79,12 @@ import static org.jooq.impl.DSL.using;
 
 import org.apache.hadoop.ozone.OmUtils;
 import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.recon.api.handlers.EntityHandler;
 import org.apache.hadoop.ozone.om.helpers.BucketLayout;
+import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
+import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
 import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
+import org.apache.hadoop.ozone.recon.api.handlers.BucketHandler;
 import org.apache.hadoop.ozone.recon.api.ServiceNotReadyException;
 import org.apache.hadoop.ozone.recon.api.types.NSSummary;
 import org.apache.hadoop.ozone.recon.api.types.DUResponse;
@@ -392,6 +397,100 @@ public class ReconUtils {
     return fullPath;
   }
 
+  /**
+   * Converts a key prefix into an object path for FSO buckets, using IDs.
+   *
+   * This method transforms a user-provided path (e.g., "volume/bucket/dir1") 
into
+   * a database-friendly format ("/volumeID/bucketID/ParentId/") by replacing 
names
+   * with their corresponding IDs. It simplifies database queries for FSO 
bucket operations.
+   * <pre>
+   * {@code
+   * Examples:
+   * - Input: "volume/bucket/key" -> Output: 
"/volumeID/bucketID/parentDirID/key"
+   * - Input: "volume/bucket/dir1" -> Output: "/volumeID/bucketID/dir1ID/"
+   * - Input: "volume/bucket/dir1/key1" -> Output: 
"/volumeID/bucketID/dir1ID/key1"
+   * - Input: "volume/bucket/dir1/dir2" -> Output: "/volumeID/bucketID/dir2ID/"
+   * }
+   * </pre>
+   * @param prevKeyPrefix The path to be converted.
+   * @return The object path as "/volumeID/bucketID/ParentId/" or an empty 
string if an error occurs.
+   * @throws IOException If database access fails.
+   * @throws IllegalArgumentException If the provided path is invalid or 
cannot be converted.
+   */
+  public static String convertToObjectPathForOpenKeySearch(String 
prevKeyPrefix,
+                                                           
ReconOMMetadataManager omMetadataManager,
+                                                           
ReconNamespaceSummaryManager reconNamespaceSummaryManager,
+                                                           
OzoneStorageContainerManager reconSCM)
+      throws IOException {
+    try {
+      String[] names = 
EntityHandler.parseRequestPath(EntityHandler.normalizePath(
+          prevKeyPrefix, BucketLayout.FILE_SYSTEM_OPTIMIZED));
+      Table<String, OmKeyInfo> openFileTable = 
omMetadataManager.getOpenKeyTable(
+          BucketLayout.FILE_SYSTEM_OPTIMIZED);
+
+      // Root-Level: Return the original path
+      if (names.length == 0 || names[0].isEmpty()) {
+        return prevKeyPrefix;
+      }
+
+      // Volume-Level: Fetch the volumeID
+      String volumeName = names[0];
+      validateNames(volumeName);
+      String volumeKey = omMetadataManager.getVolumeKey(volumeName);
+      long volumeId = 
omMetadataManager.getVolumeTable().getSkipCache(volumeKey).getObjectID();
+      if (names.length == 1) {
+        return constructObjectPathWithPrefix(volumeId);
+      }
+
+      // Bucket-Level: Fetch the bucketID
+      String bucketName = names[1];
+      validateNames(bucketName);
+      String bucketKey = omMetadataManager.getBucketKey(volumeName, 
bucketName);
+      OmBucketInfo bucketInfo = 
omMetadataManager.getBucketTable().getSkipCache(bucketKey);
+      long bucketId = bucketInfo.getObjectID();
+      if (names.length == 2 || bucketInfo.getBucketLayout() != 
BucketLayout.FILE_SYSTEM_OPTIMIZED) {
+        return constructObjectPathWithPrefix(volumeId, bucketId);
+      }
+
+      // Directory or Key-Level: Check both key and directory
+      BucketHandler handler =
+          BucketHandler.getBucketHandler(reconNamespaceSummaryManager, 
omMetadataManager, reconSCM, bucketInfo);
+
+      if (names.length >= 3) {
+        String lastEntiry = names[names.length - 1];
+
+        // Check if the directory exists
+        OmDirectoryInfo dirInfo = handler.getDirInfo(names);
+        if (dirInfo != null && dirInfo.getName().equals(lastEntiry)) {
+          return constructObjectPathWithPrefix(volumeId, bucketId, 
dirInfo.getObjectID()) + OM_KEY_PREFIX;
+        }
+
+        // Check if the key exists
+        long dirID = handler.getDirObjectId(names, names.length);
+        String keyKey = constructObjectPathWithPrefix(volumeId, bucketId, 
dirID) +
+            OM_KEY_PREFIX + lastEntiry;
+        OmKeyInfo keyInfo = openFileTable.getSkipCache(keyKey);
+        if (keyInfo != null && keyInfo.getFileName().equals(lastEntiry)) {
+          return constructObjectPathWithPrefix(volumeId, bucketId,
+              keyInfo.getParentObjectID()) + OM_KEY_PREFIX + lastEntiry;
+        }
+
+        return prevKeyPrefix;
+      }
+    } catch (IllegalArgumentException e) {
+      log.error(
+          "IllegalArgumentException encountered while converting key prefix to 
object path: {}",
+          prevKeyPrefix, e);
+      throw e;
+    } catch (RuntimeException e) {
+      log.error(
+          "RuntimeException encountered while converting key prefix to object 
path: {}",
+          prevKeyPrefix, e);
+      return prevKeyPrefix;
+    }
+    return prevKeyPrefix;
+  }
+
   private static void triggerRebuild(ReconNamespaceSummaryManager 
reconNamespaceSummaryManager,
                                      ReconOMMetadataManager omMetadataManager) 
{
     ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
index d7cb691253..64da15db41 100644
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
+++ 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightEndpoint.java
@@ -56,9 +56,10 @@ import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.io.IOException;
+import java.util.Collections;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -80,8 +81,6 @@ import static 
org.apache.hadoop.ozone.recon.ReconConstants.RECON_QUERY_PREVKEY;
 import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.createBadRequestResponse;
 import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.createInternalServerErrorResponse;
 import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.noMatchedKeysResponse;
-import static org.apache.hadoop.ozone.recon.ReconUtils.extractKeysFromTable;
-import static org.apache.hadoop.ozone.recon.ReconUtils.validateStartPrefix;
 import static 
org.apache.hadoop.ozone.recon.api.handlers.BucketHandler.getBucketHandler;
 import static 
org.apache.hadoop.ozone.recon.api.handlers.EntityHandler.normalizePath;
 import static 
org.apache.hadoop.ozone.recon.api.handlers.EntityHandler.parseRequestPath;
@@ -179,102 +178,133 @@ public class OMDBInsightEndpoint {
   @Path("/open")
   public Response getOpenKeyInfo(
       @DefaultValue(DEFAULT_FETCH_COUNT) @QueryParam(RECON_QUERY_LIMIT)
-          int limit,
+      int limit,
       @DefaultValue(StringUtils.EMPTY) @QueryParam(RECON_QUERY_PREVKEY)
-          String prevKey,
-      @DefaultValue(DEFAULT_OPEN_KEY_INCLUDE_FSO)
-      @QueryParam(RECON_OPEN_KEY_INCLUDE_FSO)
-          boolean includeFso,
-      @DefaultValue(DEFAULT_OPEN_KEY_INCLUDE_NON_FSO)
-      @QueryParam(RECON_OPEN_KEY_INCLUDE_NON_FSO)
-          boolean includeNonFso) {
+      String prevKey,
+      @DefaultValue(StringUtils.EMPTY) @QueryParam(RECON_QUERY_START_PREFIX)
+      String startPrefix,
+      @DefaultValue(DEFAULT_OPEN_KEY_INCLUDE_FSO) 
@QueryParam(RECON_OPEN_KEY_INCLUDE_FSO)
+      boolean includeFso,
+      @DefaultValue(DEFAULT_OPEN_KEY_INCLUDE_NON_FSO) 
@QueryParam(RECON_OPEN_KEY_INCLUDE_NON_FSO)
+      boolean includeNonFso) {
+
     KeyInsightInfoResponse openKeyInsightInfo = new KeyInsightInfoResponse();
-    List<KeyEntityInfo> nonFSOKeyInfoList =
-        openKeyInsightInfo.getNonFSOKeyInfoList();
-
-    boolean skipPrevKeyDone = false;
-    boolean isLegacyBucketLayout = true;
-    boolean recordsFetchedLimitReached = false;
-
-    String lastKey = "";
-    List<KeyEntityInfo> fsoKeyInfoList = 
openKeyInsightInfo.getFsoKeyInfoList();
-    for (BucketLayout layout : Arrays.asList(
-        BucketLayout.LEGACY, BucketLayout.FILE_SYSTEM_OPTIMIZED)) {
-      isLegacyBucketLayout = (layout == BucketLayout.LEGACY);
-      // Skip bucket iteration based on parameters includeFso and includeNonFso
-      if ((!includeFso && !isLegacyBucketLayout) ||
-          (!includeNonFso && isLegacyBucketLayout)) {
-        continue;
+
+    try {
+      long replicatedTotal = 0;
+      long unreplicatedTotal = 0;
+      boolean skipPrevKeyDone = false;  // Tracks if prevKey was used earlier
+      boolean keysFound = false; // Flag to track if any keys are found
+      String lastKey = null;
+      Map<String, OmKeyInfo> obsKeys = Collections.emptyMap();
+      Map<String, OmKeyInfo> fsoKeys = Collections.emptyMap();
+
+      // Validate startPrefix if it's provided
+      if (isNotBlank(startPrefix) && !validateStartPrefix(startPrefix)) {
+        return createBadRequestResponse("Invalid startPrefix: Path must be at 
the bucket level or deeper.");
       }
 
-      Table<String, OmKeyInfo> openKeyTable =
-          omMetadataManager.getOpenKeyTable(layout);
-      try (
-          TableIterator<String, ? extends Table.KeyValue<String, OmKeyInfo>>
-              keyIter = openKeyTable.iterator()) {
-        boolean skipPrevKey = false;
-        String seekKey = prevKey;
-        if (!skipPrevKeyDone && isNotBlank(prevKey)) {
-          skipPrevKey = true;
-          Table.KeyValue<String, OmKeyInfo> seekKeyValue =
-              keyIter.seek(seekKey);
-          // check if RocksDB was able to seek correctly to the given key 
prefix
-          // if not, then return empty result
-          // In case of an empty prevKeyPrefix, all the keys are returned
-          if (seekKeyValue == null ||
-              (isNotBlank(prevKey) &&
-                  !seekKeyValue.getKey().equals(prevKey))) {
-            continue;
-          }
+      // Use searchOpenKeys logic with adjustments for FSO and Non-FSO 
filtering
+      if (includeNonFso) {
+        // Search for non-FSO keys in KeyTable
+        Table<String, OmKeyInfo> openKeyTable = 
omMetadataManager.getOpenKeyTable(BucketLayout.LEGACY);
+        obsKeys = ReconUtils.extractKeysFromTable(openKeyTable, startPrefix, 
limit, prevKey);
+        for (Map.Entry<String, OmKeyInfo> entry : obsKeys.entrySet()) {
+          keysFound = true;
+          skipPrevKeyDone = true; // Don't use the prevKey for the file table
+          KeyEntityInfo keyEntityInfo = 
createKeyEntityInfoFromOmKeyInfo(entry.getKey(), entry.getValue());
+          openKeyInsightInfo.getNonFSOKeyInfoList().add(keyEntityInfo); // Add 
to non-FSO list
+          replicatedTotal += entry.getValue().getReplicatedSize();
+          unreplicatedTotal += entry.getValue().getDataSize();
+          lastKey = entry.getKey(); // Update lastKey
         }
-        while (keyIter.hasNext()) {
-          Table.KeyValue<String, OmKeyInfo> kv = keyIter.next();
-          String key = kv.getKey();
-          lastKey = key;
-          OmKeyInfo omKeyInfo = kv.getValue();
-          // skip the prev key if prev key is present
-          if (skipPrevKey && key.equals(prevKey)) {
-            skipPrevKeyDone = true;
-            continue;
-          }
-          KeyEntityInfo keyEntityInfo = new KeyEntityInfo();
-          keyEntityInfo.setIsKey(omKeyInfo.isFile());
-          keyEntityInfo.setKey(key);
-          keyEntityInfo.setPath(omKeyInfo.getKeyName());
-          keyEntityInfo.setInStateSince(omKeyInfo.getCreationTime());
-          keyEntityInfo.setSize(omKeyInfo.getDataSize());
-          keyEntityInfo.setReplicatedSize(omKeyInfo.getReplicatedSize());
-          keyEntityInfo.setReplicationConfig(omKeyInfo.getReplicationConfig());
-          openKeyInsightInfo.setUnreplicatedDataSize(
-              openKeyInsightInfo.getUnreplicatedDataSize() +
-                  keyEntityInfo.getSize());
-          openKeyInsightInfo.setReplicatedDataSize(
-              openKeyInsightInfo.getReplicatedDataSize() +
-                  keyEntityInfo.getReplicatedSize());
-          boolean added =
-              isLegacyBucketLayout ? nonFSOKeyInfoList.add(keyEntityInfo) :
-                  fsoKeyInfoList.add(keyEntityInfo);
-          if ((nonFSOKeyInfoList.size() + fsoKeyInfoList.size()) == limit) {
-            recordsFetchedLimitReached = true;
-            break;
-          }
+      }
+
+      if (includeFso) {
+        // Search for FSO keys in FileTable
+        // If prevKey was used for non-FSO keys, skip it for FSO keys.
+        String effectivePrevKey = skipPrevKeyDone ? "" : prevKey;
+        // If limit = -1 then we need to fetch all keys without limit
+        int effectiveLimit = limit == -1 ? limit : limit - obsKeys.size();
+        fsoKeys = searchOpenKeysInFSO(startPrefix, effectiveLimit, 
effectivePrevKey);
+        for (Map.Entry<String, OmKeyInfo> entry : fsoKeys.entrySet()) {
+          keysFound = true;
+          KeyEntityInfo keyEntityInfo = 
createKeyEntityInfoFromOmKeyInfo(entry.getKey(), entry.getValue());
+          openKeyInsightInfo.getFsoKeyInfoList().add(keyEntityInfo); // Add to 
FSO list
+          replicatedTotal += entry.getValue().getReplicatedSize();
+          unreplicatedTotal += entry.getValue().getDataSize();
+          lastKey = entry.getKey(); // Update lastKey
         }
-      } catch (IOException ex) {
-        throw new WebApplicationException(ex,
-            Response.Status.INTERNAL_SERVER_ERROR);
-      } catch (IllegalArgumentException e) {
-        throw new WebApplicationException(e, Response.Status.BAD_REQUEST);
-      } catch (Exception ex) {
-        throw new WebApplicationException(ex,
-            Response.Status.INTERNAL_SERVER_ERROR);
       }
-      if (recordsFetchedLimitReached) {
-        break;
+
+      // If no keys were found, return a response indicating that no keys 
matched
+      if (!keysFound) {
+        return noMatchedKeysResponse(startPrefix);
       }
+
+      // Set the aggregated totals in the response
+      openKeyInsightInfo.setReplicatedDataSize(replicatedTotal);
+      openKeyInsightInfo.setUnreplicatedDataSize(unreplicatedTotal);
+      openKeyInsightInfo.setLastKey(lastKey);
+
+      // Return the response with the matched keys and their data sizes
+      return Response.ok(openKeyInsightInfo).build();
+    } catch (IOException e) {
+      // Handle IO exceptions and return an internal server error response
+      return createInternalServerErrorResponse("Error searching open keys in 
OM DB: " + e.getMessage());
+    } catch (IllegalArgumentException e) {
+      // Handle illegal argument exceptions and return a bad request response
+      return createBadRequestResponse("Invalid argument: " + e.getMessage());
     }
+  }
 
-    openKeyInsightInfo.setLastKey(lastKey);
-    return Response.ok(openKeyInsightInfo).build();
+  public Map<String, OmKeyInfo> searchOpenKeysInFSO(String startPrefix,
+                                                    int limit, String prevKey)
+      throws IOException, IllegalArgumentException {
+    Map<String, OmKeyInfo> matchedKeys = new LinkedHashMap<>();
+    // Convert the search prefix to an object path for FSO buckets
+    String startPrefixObjectPath = 
ReconUtils.convertToObjectPathForOpenKeySearch(
+            startPrefix, omMetadataManager, reconNamespaceSummaryManager, 
reconSCM);
+    String[] names = parseRequestPath(startPrefixObjectPath);
+    Table<String, OmKeyInfo> openFileTable =
+        omMetadataManager.getOpenKeyTable(BucketLayout.FILE_SYSTEM_OPTIMIZED);
+
+    // If names.length <= 2, then the search prefix is at the volume or bucket 
level hence
+    // no need to find parent or extract id's or find subpaths as the 
openFileTable is
+    // suitable for volume and bucket level search
+    if (names.length > 2 && startPrefixObjectPath.endsWith(OM_KEY_PREFIX)) {
+      // Fetch the parent ID to search for
+      long parentId = Long.parseLong(names[names.length - 1]);
+
+      // Fetch the nameSpaceSummary for the parent ID
+      NSSummary parentSummary = 
reconNamespaceSummaryManager.getNSSummary(parentId);
+      if (parentSummary == null) {
+        return matchedKeys;
+      }
+      List<String> subPaths = new ArrayList<>();
+      // Add the initial search prefix object path because it can have both 
openFiles
+      // and subdirectories with openFiles
+      subPaths.add(startPrefixObjectPath);
+
+      // Recursively gather all subpaths
+      ReconUtils.gatherSubPaths(parentId, subPaths, Long.parseLong(names[0]), 
Long.parseLong(names[1]),
+          reconNamespaceSummaryManager);
+
+      // Iterate over the subpaths and retrieve the open files
+      for (String subPath : subPaths) {
+        matchedKeys.putAll(
+            ReconUtils.extractKeysFromTable(openFileTable, subPath, limit - 
matchedKeys.size(), prevKey));
+        if (matchedKeys.size() >= limit) {
+          break;
+        }
+      }
+      return matchedKeys;
+    }
+
+    // If the search level is at the volume, bucket or key level, directly 
search the openFileTable
+    matchedKeys.putAll(
+        ReconUtils.extractKeysFromTable(openFileTable, startPrefixObjectPath, 
limit, prevKey));
+    return matchedKeys;
   }
 
   /**
@@ -481,7 +511,7 @@ public class OMDBInsightEndpoint {
     // Search for deleted keys in DeletedTable
     Table<String, RepeatedOmKeyInfo> deletedTable = 
omMetadataManager.getDeletedTable();
     Map<String, RepeatedOmKeyInfo> deletedKeys =
-        extractKeysFromTable(deletedTable, startPrefix, limit, prevKey);
+        ReconUtils.extractKeysFromTable(deletedTable, startPrefix, limit, 
prevKey);
 
     // Iterate over the retrieved keys and populate the response
     for (Map.Entry<String, RepeatedOmKeyInfo> entry : deletedKeys.entrySet()) {
@@ -1265,8 +1295,7 @@ public class OMDBInsightEndpoint {
     KeyEntityInfo keyEntityInfo = new KeyEntityInfo();
     keyEntityInfo.setKey(dbKey); // Set the DB key
     keyEntityInfo.setIsKey(keyInfo.isFile());
-    keyEntityInfo.setPath(ReconUtils.constructFullPath(keyInfo, 
reconNamespaceSummaryManager,
-        omMetadataManager));
+    keyEntityInfo.setPath(ReconUtils.constructFullPath(keyInfo, 
reconNamespaceSummaryManager, omMetadataManager));
     keyEntityInfo.setSize(keyInfo.getDataSize());
     keyEntityInfo.setCreationTime(keyInfo.getCreationTime());
     keyEntityInfo.setModificationTime(keyInfo.getModificationTime());
@@ -1284,6 +1313,20 @@ public class OMDBInsightEndpoint {
     dirSummary.put("totalDeletedDirectories", deletedDirCount);
   }
 
+  private boolean validateStartPrefix(String startPrefix) {
+
+    // Ensure startPrefix starts with '/' for non-empty values
+    startPrefix = startPrefix.startsWith("/") ? startPrefix : "/" + 
startPrefix;
+
+    // Split the path to ensure it's at least at the bucket level 
(volume/bucket).
+    String[] pathComponents = startPrefix.split("/");
+    if (pathComponents.length < 3 || pathComponents[2].isEmpty()) {
+      return false; // Invalid if not at bucket level or deeper
+    }
+
+    return true;
+  }
+
   private String createPath(OmKeyInfo omKeyInfo) {
     return omKeyInfo.getVolumeName() + OM_KEY_PREFIX +
         omKeyInfo.getBucketName() + OM_KEY_PREFIX + omKeyInfo.getKeyName();
diff --git 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightSearchEndpoint.java
 
b/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightSearchEndpoint.java
deleted file mode 100644
index fcd73fbe72..0000000000
--- 
a/hadoop-ozone/recon/src/main/java/org/apache/hadoop/ozone/recon/api/OMDBInsightSearchEndpoint.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.recon.api;
-
-import org.apache.hadoop.hdds.scm.server.OzoneStorageContainerManager;
-import org.apache.hadoop.hdds.utils.db.Table;
-import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
-import org.apache.hadoop.ozone.om.helpers.OmDirectoryInfo;
-import org.apache.hadoop.ozone.om.helpers.OmKeyInfo;
-import org.apache.hadoop.ozone.om.helpers.BucketLayout;
-import org.apache.hadoop.ozone.recon.api.handlers.BucketHandler;
-import org.apache.hadoop.ozone.recon.api.types.KeyEntityInfo;
-import org.apache.hadoop.ozone.recon.api.types.KeyInsightInfoResponse;
-import org.apache.hadoop.ozone.recon.api.types.NSSummary;
-import org.apache.hadoop.ozone.recon.recovery.ReconOMMetadataManager;
-import org.apache.hadoop.ozone.recon.spi.impl.ReconNamespaceSummaryManagerImpl;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.inject.Inject;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import java.io.IOException;
-import java.util.Map;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.ArrayList;
-
-import static org.apache.hadoop.ozone.OzoneConsts.OM_KEY_PREFIX;
-import static 
org.apache.hadoop.ozone.recon.ReconConstants.RECON_OM_INSIGHTS_DEFAULT_START_PREFIX;
-import static 
org.apache.hadoop.ozone.recon.ReconConstants.RECON_OM_INSIGHTS_DEFAULT_SEARCH_LIMIT;
-import static 
org.apache.hadoop.ozone.recon.ReconConstants.RECON_OM_INSIGHTS_DEFAULT_SEARCH_PREV_KEY;
-import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.noMatchedKeysResponse;
-import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.createBadRequestResponse;
-import static 
org.apache.hadoop.ozone.recon.ReconResponseUtils.createInternalServerErrorResponse;
-import static org.apache.hadoop.ozone.recon.ReconUtils.validateStartPrefix;
-import static 
org.apache.hadoop.ozone.recon.ReconUtils.constructObjectPathWithPrefix;
-import static org.apache.hadoop.ozone.recon.ReconUtils.extractKeysFromTable;
-import static org.apache.hadoop.ozone.recon.ReconUtils.gatherSubPaths;
-import static org.apache.hadoop.ozone.recon.ReconUtils.validateNames;
-import static 
org.apache.hadoop.ozone.recon.api.handlers.BucketHandler.getBucketHandler;
-import static 
org.apache.hadoop.ozone.recon.api.handlers.EntityHandler.normalizePath;
-import static 
org.apache.hadoop.ozone.recon.api.handlers.EntityHandler.parseRequestPath;
-
-/**
- * REST endpoint for search implementation in OM DB Insight.
- *
- * This class provides endpoints for searching keys in the Ozone Manager 
database.
- * It supports searching for both open and deleted keys across File System 
Optimized (FSO)
- * and Object Store (non-FSO) bucket layouts. The results include matching 
keys and their
- * data sizes.
- */
-@Path("/keys")
-@Produces(MediaType.APPLICATION_JSON)
-@AdminOnly
-public class OMDBInsightSearchEndpoint {
-
-  private OzoneStorageContainerManager reconSCM;
-  private final ReconOMMetadataManager omMetadataManager;
-  private static final Logger LOG =
-      LoggerFactory.getLogger(OMDBInsightSearchEndpoint.class);
-  private ReconNamespaceSummaryManagerImpl reconNamespaceSummaryManager;
-
-
-  @Inject
-  public OMDBInsightSearchEndpoint(OzoneStorageContainerManager reconSCM,
-                                   ReconOMMetadataManager omMetadataManager,
-                                   ReconNamespaceSummaryManagerImpl 
reconNamespaceSummaryManager) {
-    this.reconSCM = reconSCM;
-    this.omMetadataManager = omMetadataManager;
-    this.reconNamespaceSummaryManager = reconNamespaceSummaryManager;
-  }
-
-
-  /**
-   * Performs a search for open keys in the Ozone Manager OpenKey and OpenFile 
table using a specified search prefix.
-   * This endpoint searches across both File System Optimized (FSO) and Object 
Store (non-FSO) layouts,
-   * compiling a list of keys that match the given prefix along with their 
data sizes.
-   *
-   * The search prefix must start from the bucket level 
('/volumeName/bucketName/') or any specific directory
-   * or key level (e.g., '/volA/bucketA/dir1' for everything under 'dir1' 
inside 'bucketA' of 'volA').
-   * The search operation matches the prefix against the start of keys' names 
within the OM DB.
-   *
-   * Example Usage:
-   * 1. A startPrefix of "/volA/bucketA/" retrieves every key under bucket 
'bucketA' in volume 'volA'.
-   * 2. Specifying "/volA/bucketA/dir1" focuses the search within 'dir1' 
inside 'bucketA' of 'volA'.
-   *
-   * @param startPrefix The prefix for searching keys, starting from the 
bucket level or any specific path.
-   * @param limit       Limits the number of returned keys.
-   * @param prevKey     The key to start after for the next set of records.
-   * @return A KeyInsightInfoResponse, containing matching keys and their data 
sizes.
-   * @throws IOException On failure to access the OM database or process the 
operation.
-   * @throws IllegalArgumentException If the provided startPrefix or other 
arguments are invalid.
-   */
-  @GET
-  @Path("/open/search")
-  public Response searchOpenKeys(
-      @DefaultValue(RECON_OM_INSIGHTS_DEFAULT_START_PREFIX) 
@QueryParam("startPrefix")
-      String startPrefix,
-      @DefaultValue(RECON_OM_INSIGHTS_DEFAULT_SEARCH_LIMIT) 
@QueryParam("limit")
-      int limit,
-      @DefaultValue(RECON_OM_INSIGHTS_DEFAULT_SEARCH_PREV_KEY) 
@QueryParam("prevKey")
-      String prevKey) throws IOException {
-
-    try {
-      // Validate the request parameters
-      if (!validateStartPrefix(startPrefix)) {
-        return createBadRequestResponse("Invalid startPrefix: Path must be at 
the bucket level or deeper.");
-      }
-
-      // Ensure the limit is non-negative
-      limit = Math.max(0, limit);
-
-      // Initialize response object
-      KeyInsightInfoResponse insightResponse = new KeyInsightInfoResponse();
-      long replicatedTotal = 0;
-      long unreplicatedTotal = 0;
-      boolean keysFound = false; // Flag to track if any keys are found
-      String lastKey = null;
-
-      // Search for non-fso keys in KeyTable
-      Table<String, OmKeyInfo> openKeyTable =
-          omMetadataManager.getOpenKeyTable(BucketLayout.LEGACY);
-      Map<String, OmKeyInfo> obsKeys =
-          extractKeysFromTable(openKeyTable, startPrefix, limit, prevKey);
-      for (Map.Entry<String, OmKeyInfo> entry : obsKeys.entrySet()) {
-        keysFound = true;
-        KeyEntityInfo keyEntityInfo =
-            createKeyEntityInfoFromOmKeyInfo(entry.getKey(), entry.getValue());
-        insightResponse.getNonFSOKeyInfoList()
-            .add(keyEntityInfo); // Add to non-FSO list
-        replicatedTotal += entry.getValue().getReplicatedSize();
-        unreplicatedTotal += entry.getValue().getDataSize();
-        lastKey = entry.getKey(); // Update lastKey
-      }
-
-      // Search for fso keys in FileTable
-      Map<String, OmKeyInfo> fsoKeys = searchOpenKeysInFSO(startPrefix, limit, 
prevKey);
-      for (Map.Entry<String, OmKeyInfo> entry : fsoKeys.entrySet()) {
-        keysFound = true;
-        KeyEntityInfo keyEntityInfo =
-            createKeyEntityInfoFromOmKeyInfo(entry.getKey(), entry.getValue());
-        insightResponse.getFsoKeyInfoList()
-            .add(keyEntityInfo); // Add to FSO list
-        replicatedTotal += entry.getValue().getReplicatedSize();
-        unreplicatedTotal += entry.getValue().getDataSize();
-        lastKey = entry.getKey(); // Update lastKey
-      }
-
-      // If no keys were found, return a response indicating that no keys 
matched
-      if (!keysFound) {
-        return noMatchedKeysResponse(startPrefix);
-      }
-
-      // Set the aggregated totals in the response
-      insightResponse.setReplicatedDataSize(replicatedTotal);
-      insightResponse.setUnreplicatedDataSize(unreplicatedTotal);
-      insightResponse.setLastKey(lastKey);
-
-      // Return the response with the matched keys and their data sizes
-      return Response.ok(insightResponse).build();
-    } catch (IOException e) {
-      // Handle IO exceptions and return an internal server error response
-      return createInternalServerErrorResponse(
-          "Error searching open keys in OM DB: " + e.getMessage());
-    } catch (IllegalArgumentException e) {
-      // Handle illegal argument exceptions and return a bad request response
-      return createBadRequestResponse(
-          "Invalid startPrefix: " + e.getMessage());
-    }
-  }
-
-  public Map<String, OmKeyInfo> searchOpenKeysInFSO(String startPrefix,
-                                                    int limit, String prevKey)
-      throws IOException, IllegalArgumentException {
-    Map<String, OmKeyInfo> matchedKeys = new LinkedHashMap<>();
-    // Convert the search prefix to an object path for FSO buckets
-    String startPrefixObjectPath = convertToObjectPath(startPrefix);
-    String[] names = parseRequestPath(startPrefixObjectPath);
-    Table<String, OmKeyInfo> openFileTable =
-        omMetadataManager.getOpenKeyTable(BucketLayout.FILE_SYSTEM_OPTIMIZED);
-
-    // If names.length <= 2, then the search prefix is at the volume or bucket 
level hence
-    // no need to find parent or extract id's or find subpaths as the 
openFileTable is
-    // suitable for volume and bucket level search
-    if (names.length > 2 && startPrefixObjectPath.endsWith(OM_KEY_PREFIX)) {
-      // Fetch the parent ID to search for
-      long parentId = Long.parseLong(names[names.length - 1]);
-
-      // Fetch the nameSpaceSummary for the parent ID
-      NSSummary parentSummary = 
reconNamespaceSummaryManager.getNSSummary(parentId);
-      if (parentSummary == null) {
-        return matchedKeys;
-      }
-      List<String> subPaths = new ArrayList<>();
-      // Add the initial search prefix object path because it can have both 
openFiles
-      // and subdirectories with openFiles
-      subPaths.add(startPrefixObjectPath);
-
-      // Recursively gather all subpaths
-      gatherSubPaths(parentId, subPaths, Long.parseLong(names[0]), 
Long.parseLong(names[1]),
-          reconNamespaceSummaryManager);
-
-      // Iterate over the subpaths and retrieve the open files
-      for (String subPath : subPaths) {
-        matchedKeys.putAll(
-            extractKeysFromTable(openFileTable, subPath, limit - 
matchedKeys.size(), prevKey));
-        if (matchedKeys.size() >= limit) {
-          break;
-        }
-      }
-      return matchedKeys;
-    }
-
-    // If the search level is at the volume, bucket or key level, directly 
search the openFileTable
-    matchedKeys.putAll(
-        extractKeysFromTable(openFileTable, startPrefixObjectPath, limit, 
prevKey));
-    return matchedKeys;
-  }
-
-  /**
-   * Converts a key prefix into an object path for FSO buckets, using IDs.
-   *
-   * This method transforms a user-provided path (e.g., "volume/bucket/dir1") 
into
-   * a database-friendly format ("/volumeID/bucketID/ParentId/") by replacing 
names
-   * with their corresponding IDs. It simplifies database queries for FSO 
bucket operations.
-   * <pre>
-   * {@code
-   * Examples:
-   * - Input: "volume/bucket/key" -> Output: 
"/volumeID/bucketID/parentDirID/key"
-   * - Input: "volume/bucket/dir1" -> Output: "/volumeID/bucketID/dir1ID/"
-   * - Input: "volume/bucket/dir1/key1" -> Output: 
"/volumeID/bucketID/dir1ID/key1"
-   * - Input: "volume/bucket/dir1/dir2" -> Output: "/volumeID/bucketID/dir2ID/"
-   * }
-   * </pre>
-   * @param prevKeyPrefix The path to be converted.
-   * @return The object path as "/volumeID/bucketID/ParentId/" or an empty 
string if an error occurs.
-   * @throws IOException If database access fails.
-   * @throws IllegalArgumentException If the provided path is invalid or 
cannot be converted.
-   */
-  public String convertToObjectPath(String prevKeyPrefix) throws IOException {
-    try {
-      String[] names = parseRequestPath(normalizePath(prevKeyPrefix, 
BucketLayout.FILE_SYSTEM_OPTIMIZED));
-      Table<String, OmKeyInfo> openFileTable = 
omMetadataManager.getOpenKeyTable(BucketLayout.FILE_SYSTEM_OPTIMIZED);
-
-      // Root-Level: Return the original path
-      if (names.length == 0) {
-        return prevKeyPrefix;
-      }
-
-      // Volume-Level: Fetch the volumeID
-      String volumeName = names[0];
-      validateNames(volumeName);
-      String volumeKey = omMetadataManager.getVolumeKey(volumeName);
-      long volumeId = 
omMetadataManager.getVolumeTable().getSkipCache(volumeKey).getObjectID();
-      if (names.length == 1) {
-        return constructObjectPathWithPrefix(volumeId);
-      }
-
-      // Bucket-Level: Fetch the bucketID
-      String bucketName = names[1];
-      validateNames(bucketName);
-      String bucketKey = omMetadataManager.getBucketKey(volumeName, 
bucketName);
-      OmBucketInfo bucketInfo = 
omMetadataManager.getBucketTable().getSkipCache(bucketKey);
-      long bucketId = bucketInfo.getObjectID();
-      if (names.length == 2 || bucketInfo.getBucketLayout() != 
BucketLayout.FILE_SYSTEM_OPTIMIZED) {
-        return constructObjectPathWithPrefix(volumeId, bucketId);
-      }
-
-      // Directory or Key-Level: Check both key and directory
-      BucketHandler handler =
-          getBucketHandler(reconNamespaceSummaryManager, omMetadataManager, 
reconSCM, bucketInfo);
-
-      if (names.length >= 3) {
-        String lastEntiry = names[names.length - 1];
-
-        // Check if the directory exists
-        OmDirectoryInfo dirInfo = handler.getDirInfo(names);
-        if (dirInfo != null && dirInfo.getName().equals(lastEntiry)) {
-          return constructObjectPathWithPrefix(volumeId, bucketId, 
dirInfo.getObjectID()) + OM_KEY_PREFIX;
-        }
-
-        // Check if the key exists
-        long dirID = handler.getDirObjectId(names, names.length);
-        String keyKey = constructObjectPathWithPrefix(volumeId, bucketId, 
dirID) +
-                OM_KEY_PREFIX + lastEntiry;
-        OmKeyInfo keyInfo = openFileTable.getSkipCache(keyKey);
-        if (keyInfo != null && keyInfo.getFileName().equals(lastEntiry)) {
-          return constructObjectPathWithPrefix(volumeId, bucketId,
-              keyInfo.getParentObjectID()) + OM_KEY_PREFIX + lastEntiry;
-        }
-
-        return prevKeyPrefix;
-      }
-    } catch (IllegalArgumentException e) {
-      LOG.error(
-          "IllegalArgumentException encountered while converting key prefix to 
object path: {}",
-          prevKeyPrefix, e);
-      throw e;
-    } catch (RuntimeException e) {
-      LOG.error(
-          "RuntimeException encountered while converting key prefix to object 
path: {}",
-          prevKeyPrefix, e);
-      return prevKeyPrefix;
-    }
-    return prevKeyPrefix;
-  }
-
-  /**
-   * Creates a KeyEntityInfo object from an OmKeyInfo object and the 
corresponding key.
-   *
-   * @param dbKey   The key in the database corresponding to the OmKeyInfo 
object.
-   * @param keyInfo The OmKeyInfo object to create the KeyEntityInfo from.
-   * @return The KeyEntityInfo object created from the OmKeyInfo object and 
the key.
-   */
-  private KeyEntityInfo createKeyEntityInfoFromOmKeyInfo(String dbKey,
-                                                         OmKeyInfo keyInfo) {
-    KeyEntityInfo keyEntityInfo = new KeyEntityInfo();
-    keyEntityInfo.setKey(dbKey); // Set the DB key
-    keyEntityInfo.setIsKey(keyInfo.isFile());
-    keyEntityInfo.setPath(keyInfo.getKeyName()); // Assuming path is the same 
as key name
-    keyEntityInfo.setInStateSince(keyInfo.getCreationTime());
-    keyEntityInfo.setSize(keyInfo.getDataSize());
-    keyEntityInfo.setReplicatedSize(keyInfo.getReplicatedSize());
-    keyEntityInfo.setReplicationConfig(keyInfo.getReplicationConfig());
-    return keyEntityInfo;
-  }
-
-}
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
index ed4b82fa3e..61a9711876 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOmDBInsightEndPoint.java
@@ -90,6 +90,7 @@ import static 
org.apache.hadoop.ozone.recon.OMMetadataManagerTestUtils.writeKeyT
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -897,11 +898,11 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
             .get("/sampleVol/bucketOne/key_one");
     assertEquals("key_one", omKeyInfo1.getKeyName());
     Response openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(-1, "", true, true);
+        omdbInsightEndpoint.getOpenKeyInfo(-1, "", "", true, true);
     KeyInsightInfoResponse keyInsightInfoResp =
         (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
-    assertEquals("key_one",
+    assertEquals("sampleVol/bucketOne/key_one",
         keyInsightInfoResp.getNonFSOKeyInfoList().get(0).getPath());
   }
 
@@ -1044,7 +1045,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     reconOMMetadataManager.getOpenKeyTable(getBucketLayout())
         .put("/sampleVol/bucketOne/key_three", omKeyInfo3);
     Response openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(2, "", true, true);
+        omdbInsightEndpoint.getOpenKeyInfo(2, "", "", true, true);
     KeyInsightInfoResponse keyInsightInfoResp =
         (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
@@ -1053,10 +1054,10 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     assertEquals(0, keyInsightInfoResp.getFsoKeyInfoList().size());
     assertEquals(2, keyInsightInfoResp.getFsoKeyInfoList().size() +
         keyInsightInfoResp.getNonFSOKeyInfoList().size());
-    assertEquals("key_three",
+    assertEquals("sampleVol/bucketOne/key_three",
         keyInsightInfoResp.getNonFSOKeyInfoList().get(1).getPath());
 
-    openKeyInfoResp = omdbInsightEndpoint.getOpenKeyInfo(3, "", true, true);
+    openKeyInfoResp = omdbInsightEndpoint.getOpenKeyInfo(3, "", "", true, 
true);
     keyInsightInfoResp =
         (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
@@ -1065,7 +1066,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     assertEquals(1, keyInsightInfoResp.getFsoKeyInfoList().size());
     assertEquals(3, keyInsightInfoResp.getFsoKeyInfoList().size() +
         keyInsightInfoResp.getNonFSOKeyInfoList().size());
-    assertEquals("key_three",
+    assertEquals("sampleVol/bucketOne/key_three",
         keyInsightInfoResp.getNonFSOKeyInfoList().get(1).getPath());
   }
 
@@ -1107,7 +1108,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     // CASE 1 :- Display only FSO keys in response
     // includeFsoKeys=true, includeNonFsoKeys=false
     Response openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(10, "", true, false);
+        omdbInsightEndpoint.getOpenKeyInfo(10, "", "", true, false);
     KeyInsightInfoResponse keyInsightInfoResp =
         (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
@@ -1119,7 +1120,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     // CASE 2 :- Display only Non-FSO keys in response
     // includeFsoKeys=false, includeNonFsoKeys=true
     openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(10, "", false, true);
+        omdbInsightEndpoint.getOpenKeyInfo(10, "", "", false, true);
     keyInsightInfoResp = (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
     assertEquals(0,
@@ -1130,7 +1131,7 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     // CASE 3 :- Display both FSO and Non-FSO keys in response
     // includeFsoKeys=true, includeNonFsoKeys=true
     openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(10, "", true, true);
+        omdbInsightEndpoint.getOpenKeyInfo(10, "", "", true, true);
     keyInsightInfoResp = (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
     assertEquals(4,
@@ -1141,45 +1142,39 @@ public class TestOmDBInsightEndPoint extends 
AbstractReconSqlDBTest {
     // CASE 4 :- Don't Display both FSO and Non-FSO keys in response
     // includeFsoKeys=false, includeNonFsoKeys=false
     openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(10, "", false, false);
-    keyInsightInfoResp = (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
-    assertNotNull(keyInsightInfoResp);
-    assertEquals(0,
-        keyInsightInfoResp.getFsoKeyInfoList().size());
-    assertEquals(0,
-        keyInsightInfoResp.getNonFSOKeyInfoList().size());
+        omdbInsightEndpoint.getOpenKeyInfo(10, "", "", false, false);
+    assertEquals(204, openKeyInfoResp.getStatus());
+    String entity = (String) openKeyInfoResp.getEntity();
+    assertTrue(entity.contains("No keys matched the search prefix"),
+        "Expected a message indicating no keys were found");
   }
 
   @Test
   public void testGetOpenKeyInfoPrevKeyParam() throws Exception {
     OmKeyInfo omKeyInfo1 =
-        getOmKeyInfo("sampleVol", "bucketOne", "key_one", true);
+        getOmKeyInfo("sampleVol", "bucketOne", "key_1", true);
     OmKeyInfo omKeyInfo2 =
-        getOmKeyInfo("sampleVol", "bucketOne", "key_two", true);
+        getOmKeyInfo("sampleVol", "bucketOne", "key_2", true);
     OmKeyInfo omKeyInfo3 =
-        getOmKeyInfo("sampleVol", "bucketOne", "key_three", true);
+        getOmKeyInfo("sampleVol", "bucketOne", "key_3", true);
 
     reconOMMetadataManager.getOpenKeyTable(getBucketLayout())
-        .put("/sampleVol/bucketOne/key_one", omKeyInfo1);
+        .put("/sampleVol/bucketOne/key_1", omKeyInfo1);
     reconOMMetadataManager.getOpenKeyTable(BucketLayout.FILE_SYSTEM_OPTIMIZED)
-        .put("/sampleVol/bucketOne/key_two", omKeyInfo2);
+        .put("/sampleVol/bucketOne/key_2", omKeyInfo2);
     reconOMMetadataManager.getOpenKeyTable(getBucketLayout())
-        .put("/sampleVol/bucketOne/key_three", omKeyInfo3);
+        .put("/sampleVol/bucketOne/key_3", omKeyInfo3);
     Response openKeyInfoResp =
-        omdbInsightEndpoint.getOpenKeyInfo(-1, "/sampleVol/bucketOne/key_one",
+        omdbInsightEndpoint.getOpenKeyInfo(-1, "/sampleVol/bucketOne/key_1", 
"",
             true, true);
     KeyInsightInfoResponse keyInsightInfoResp =
         (KeyInsightInfoResponse) openKeyInfoResp.getEntity();
     assertNotNull(keyInsightInfoResp);
-    assertEquals(1,
-        keyInsightInfoResp.getNonFSOKeyInfoList().size());
+    assertEquals(1, keyInsightInfoResp.getNonFSOKeyInfoList().size());
     assertEquals(1, keyInsightInfoResp.getFsoKeyInfoList().size());
-    assertEquals(2, keyInsightInfoResp.getFsoKeyInfoList().size() +
-        keyInsightInfoResp.getNonFSOKeyInfoList().size());
-    assertEquals("key_three",
-        keyInsightInfoResp.getNonFSOKeyInfoList().get(0).getPath());
-    assertEquals("key_two",
-        keyInsightInfoResp.getFsoKeyInfoList().get(0).getPath());
+    assertEquals(2, keyInsightInfoResp.getFsoKeyInfoList().size() + 
keyInsightInfoResp.getNonFSOKeyInfoList().size());
+    assertEquals("sampleVol/bucketOne/key_3", 
keyInsightInfoResp.getNonFSOKeyInfoList().get(0).getPath());
+    assertEquals("sampleVol/bucketOne/key_2", 
keyInsightInfoResp.getFsoKeyInfoList().get(0).getPath());
   }
 
   @Test
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOMDBInsightSearchEndpoint.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOpenKeysSearchEndpoint.java
similarity index 83%
rename from 
hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOMDBInsightSearchEndpoint.java
rename to 
hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOpenKeysSearchEndpoint.java
index c3c2fe5deb..f55d988cfe 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOMDBInsightSearchEndpoint.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/TestOpenKeysSearchEndpoint.java
@@ -81,12 +81,12 @@ import static 
org.apache.hadoop.ozone.om.OMConfigKeys.OZONE_OM_DB_DIRS;
  * 11. Test Search Open Keys with Pagination: Verifies paginated search 
results.
  * 12. Test Search in Empty Bucket: Checks the response for searching within 
an empty bucket.
  */
-public class TestOMDBInsightSearchEndpoint extends AbstractReconSqlDBTest {
+public class TestOpenKeysSearchEndpoint extends AbstractReconSqlDBTest {
 
   @TempDir
   private Path temporaryFolder;
   private ReconOMMetadataManager reconOMMetadataManager;
-  private OMDBInsightSearchEndpoint omdbInsightSearchEndpoint;
+  private OMDBInsightEndpoint omdbInsightEndpoint;
   private OzoneConfiguration ozoneConfiguration;
   private static final String ROOT_PATH = "/";
   private static final String TEST_USER = "TestUser";
@@ -116,11 +116,8 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
             .addBinding(OMDBInsightEndpoint.class)
             .addBinding(ContainerHealthSchemaManager.class)
             .build();
-    reconNamespaceSummaryManager =
-        reconTestInjector.getInstance(ReconNamespaceSummaryManager.class);
-    omdbInsightSearchEndpoint = reconTestInjector.getInstance(
-        OMDBInsightSearchEndpoint.class);
-
+    reconNamespaceSummaryManager = 
reconTestInjector.getInstance(ReconNamespaceSummaryManager.class);
+    omdbInsightEndpoint = 
reconTestInjector.getInstance(OMDBInsightEndpoint.class);
     // populate OM DB and reprocess into Recon RocksDB
     populateOMDB();
     NSSummaryTaskWithFSO nSSummaryTaskWithFso =
@@ -150,26 +147,19 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   public void testRootLevelSearchRestriction() throws IOException {
     // Test with root level path
     String rootPath = "/";
-    Response response = omdbInsightSearchEndpoint.searchOpenKeys(rootPath, 20, 
"");
+    Response response =
+        omdbInsightEndpoint.getOpenKeyInfo(-1, "", rootPath, true, true);
     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
         "Expected a message indicating the path must be at the bucket level or 
deeper");
-
-    // Test with root level path without trailing slash
-    rootPath = "";
-    response = omdbInsightSearchEndpoint.searchOpenKeys(rootPath, 20, "");
-    assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
-    entity = (String) response.getEntity();
-    assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
-        "Expected a message indicating the path must be at the bucket level or 
deeper");
   }
 
   @Test
   public void testVolumeLevelSearchRestriction() throws IOException {
     // Test with volume level path
     String volumePath = "/vola";
-    Response response = omdbInsightSearchEndpoint.searchOpenKeys(volumePath, 
20, "");
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(20, "", volumePath, 
true, true);
     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
@@ -177,7 +167,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
     // Test with another volume level path
     volumePath = "/volb";
-    response = omdbInsightSearchEndpoint.searchOpenKeys(volumePath, 20, "");
+    response = omdbInsightEndpoint.getOpenKeyInfo(20, "", volumePath, true, 
true);
     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
     entity = (String) response.getEntity();
     assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
@@ -188,7 +178,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   public void testBucketLevelSearch() throws IOException {
     // Search inside FSO bucket
     Response response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1", 20, "");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/vola/bucketa1", true, 
true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -200,7 +190,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
     // Search inside OBS bucket
     response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb1", 20, "");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/volb/bucketb1", true, 
true);
     assertEquals(200, response.getStatus());
     result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -212,13 +202,13 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
     // Search Inside LEGACY bucket
     response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/volc/bucketc1", 20, "");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/volc/bucketc1", true, 
true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(7, result.getNonFSOKeyInfoList().size());
 
     // Test with bucket that does not exist
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/nonexistentbucket", 20, "");
+    response = omdbInsightEndpoint.getOpenKeyInfo(20, "", 
"/vola/nonexistentbucket", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
@@ -228,7 +218,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   @Test
   public void testDirectoryLevelSearch() throws IOException {
     Response response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira1", 20, 
"");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/vola/bucketa1/dira1", 
true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -239,7 +229,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
     response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira2", 20, 
"");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/vola/bucketa1/dira2", 
true, true);
     assertEquals(200, response.getStatus());
     result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -250,7 +240,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
     response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira3", 20, 
"");
+        omdbInsightEndpoint.getOpenKeyInfo(20, "", "/vola/bucketa1/dira3", 
true, true);
     assertEquals(200, response.getStatus());
     result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -261,7 +251,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(10000 * 3, result.getReplicatedDataSize());
 
     // Test with non-existent directory
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/nonexistentdir", 20, 
"");
+    response = omdbInsightEndpoint.getOpenKeyInfo(20, "", 
"/vola/bucketa1/nonexistentdir", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
@@ -271,7 +261,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   @Test
   public void testKeyLevelSearch() throws IOException {
     // FSO Bucket key-level search
-    Response response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/filea1", 10, "");
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(10, "", 
"/vola/bucketa1/filea1", true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
@@ -280,7 +270,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000, result.getUnreplicatedDataSize());
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/filea2", 10, "");
+    response = omdbInsightEndpoint.getOpenKeyInfo(10, "", 
"/vola/bucketa1/filea2", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
@@ -290,7 +280,8 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
     // OBS Bucket key-level search
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb1/fileb1", 10, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/volb/bucketb1/fileb1", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(0, result.getFsoKeyInfoList().size());
@@ -299,7 +290,8 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000, result.getUnreplicatedDataSize());
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb1/fileb2", 10, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/volb/bucketb1/fileb2", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(0, result.getFsoKeyInfoList().size());
@@ -309,13 +301,15 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertEquals(1000 * 3, result.getReplicatedDataSize());
 
     // Test with non-existent key
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/nonexistentfile", 1, 
"");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/volb/bucketb1/nonexistentfile", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
         "Expected a message indicating no keys were found");
 
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb1/nonexistentfile", 1, 
"");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/volb/bucketb1/nonexistentfile", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
@@ -326,29 +320,31 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   @Test
   public void testKeyLevelSearchUnderDirectory() throws IOException {
     // FSO Bucket key-level search
-    Response response =
-        
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira1/innerfile", 10, 
"");
+    Response response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/vola/bucketa1/dira1/innerfile", true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
-    response =
-        
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira2/innerfile", 10, 
"");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/vola/bucketa1/dira2/innerfile", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Test for unknown file in fso bucket
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira1/unknownfile", 
10, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/vola/bucketa1/dira1/unknownfile", true, 
true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
         "Expected a message indicating no keys were found");
 
     // Test for unknown file in fso bucket
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira2/unknownfile", 
10, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(10, "", "/vola/bucketa1/dira2/unknownfile", true, 
true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
@@ -358,55 +354,55 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
   @Test
   public void testSearchUnderNestedDirectory() throws IOException {
-    Response response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira3", 20,
-        "");
+    Response response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", "/vola/bucketa1/dira3", true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
     assertEquals(10, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Search under dira31
-    response = 
omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1/dira3/dira31",
-        20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", "/vola/bucketa1/dira3/dira31", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(6, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Search under dira32
-    response = omdbInsightSearchEndpoint.searchOpenKeys(
-        "/vola/bucketa1/dira3/dira31/dira32", 20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", "/vola/bucketa1/dira3/dira31/dira32", true, 
true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(3, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Search under dira33
-    response = omdbInsightSearchEndpoint.searchOpenKeys(
-        "/vola/bucketa1/dira3/dira31/dira32/dira33", 20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", "/vola/bucketa1/dira3/dira31/dira32/dira33", 
true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Search for the exact file under dira33
-    response = omdbInsightSearchEndpoint.searchOpenKeys(
-        "/vola/bucketa1/dira3/dira31/dira32/dira33/file33_1", 20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", 
"/vola/bucketa1/dira3/dira31/dira32/dira33/file33_1", true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(1, result.getFsoKeyInfoList().size());
     assertEquals(0, result.getNonFSOKeyInfoList().size());
 
     // Search for a non existant file under each nested directory
-    response = omdbInsightSearchEndpoint.searchOpenKeys(
-        "/vola/bucketa1/dira3/dira31/dira32/dira33/nonexistentfile", 20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", 
"/vola/bucketa1/dira3/dira31/dira32/dira33/nonexistentfile", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
         "Expected a message indicating no keys were found");
 
-    response = omdbInsightSearchEndpoint.searchOpenKeys(
-        "/vola/bucketa1/dira3/dira31/dira32/nonexistentfile", 20, "");
+    response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", 
"/vola/bucketa1/dira3/dira31/dira32/nonexistentfile", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
@@ -416,7 +412,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   @Test
   public void testLimitSearch() throws IOException {
     Response response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/vola/bucketa1", 2, "");
+        omdbInsightEndpoint.getOpenKeyInfo(2, "", "/vola/bucketa1", true, 
true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -428,8 +424,8 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   public void testSearchOpenKeysWithBadRequest() throws IOException {
     // Give a negative limit
     int negativeLimit = -1;
-    Response response = omdbInsightSearchEndpoint.searchOpenKeys("@323232", 
negativeLimit, "");
-
+    Response response = omdbInsightEndpoint
+        .getOpenKeyInfo(negativeLimit, "", "@323232", true, true);
     // Then the response should indicate that the request was bad
     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(),
         response.getStatus(), "Expected a 400 BAD REQUEST status");
@@ -438,7 +434,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
         "Expected a message indicating the path must be at the bucket level or 
deeper");
 
-    response = omdbInsightSearchEndpoint.searchOpenKeys("///", 20, "");
+    response = omdbInsightEndpoint.getOpenKeyInfo(20, "", "///", true, true);
     assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), 
response.getStatus());
     entity = (String) response.getEntity();
     assertTrue(entity.contains("Invalid startPrefix: Path must be at the 
bucket level or deeper"),
@@ -447,8 +443,8 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
   @Test
   public void testLastKeyInResponse() throws IOException {
-    Response response =
-        omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb1", 20, "");
+    Response response = omdbInsightEndpoint
+        .getOpenKeyInfo(20, "", "/volb/bucketb1", true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result =
         (KeyInsightInfoResponse) response.getEntity();
@@ -470,7 +466,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     String prevKey = "";
 
     // Perform the first search request
-    Response response = omdbInsightSearchEndpoint.searchOpenKeys(startPrefix, 
limit, prevKey);
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(limit, prevKey, 
startPrefix, true, true);
     assertEquals(200, response.getStatus());
     KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
     assertEquals(2, result.getNonFSOKeyInfoList().size());
@@ -481,7 +477,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertNotNull(prevKey, "Last key should not be null");
 
     // Perform the second search request using the last key
-    response = omdbInsightSearchEndpoint.searchOpenKeys(startPrefix, limit, 
prevKey);
+    response = omdbInsightEndpoint.getOpenKeyInfo(limit, prevKey, startPrefix, 
true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(2, result.getNonFSOKeyInfoList().size());
@@ -492,7 +488,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
     assertNotNull(prevKey, "Last key should not be null");
 
     // Perform the third search request using the last key
-    response = omdbInsightSearchEndpoint.searchOpenKeys(startPrefix, limit, 
prevKey);
+    response = omdbInsightEndpoint.getOpenKeyInfo(limit, prevKey, startPrefix, 
true, true);
     assertEquals(200, response.getStatus());
     result = (KeyInsightInfoResponse) response.getEntity();
     assertEquals(1, result.getNonFSOKeyInfoList().size());
@@ -504,13 +500,61 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
   @Test
   public void testSearchInEmptyBucket() throws IOException {
     // Search in empty bucket bucketb2
-    Response response = 
omdbInsightSearchEndpoint.searchOpenKeys("/volb/bucketb2", 20, "");
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(20, "", 
"/volb/bucketb2", true, true);
     assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
     String entity = (String) response.getEntity();
     assertTrue(entity.contains("No keys matched the search prefix"),
         "Expected a message indicating no keys were found");
   }
 
+  @Test
+  public void testSearchWithPrevKeyOnly() throws IOException {
+    String prevKey = "/volb/bucketb1/fileb1";  // Key exists in volb/bucketb1
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(4, prevKey, "", 
true, true);
+
+    assertEquals(200, response.getStatus());
+
+    KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
+    assertEquals(4, result.getNonFSOKeyInfoList().size(), "Expected 4 
remaining keys after 'fileb1'");
+    assertEquals("/volb/bucketb1/fileb5", result.getLastKey(), "Expected last 
key to be 'fileb5'");
+  }
+
+  @Test
+  public void testSearchWithEmptyPrevKeyAndStartPrefix() throws IOException {
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(-1, "", "", true, 
true);
+
+    assertEquals(200, response.getStatus());
+
+    KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
+    // Assert all the keys are returned
+    assertEquals(12, result.getNonFSOKeyInfoList().size(), "Expected all keys 
to be returned");
+  }
+
+  @Test
+  public void testSearchWithStartPrefixOnly() throws IOException {
+    String startPrefix = "/volb/bucketb1/";
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(10, "", 
startPrefix, true, true);
+
+    assertEquals(200, response.getStatus());
+
+    KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
+    assertEquals(5, result.getNonFSOKeyInfoList().size(), "Expected 5 keys 
starting with 'fileb1'");
+    assertEquals("/volb/bucketb1/fileb5", result.getLastKey(), "Expected last 
key to be 'fileb5'");
+  }
+
+  @Test
+  public void testSearchWithPrevKeyAndStartPrefix() throws IOException {
+    String startPrefix = "/volb/bucketb1/";
+    String prevKey = "/volb/bucketb1/fileb1";
+    Response response = omdbInsightEndpoint.getOpenKeyInfo(10, prevKey, 
startPrefix, true, true);
+
+    assertEquals(200, response.getStatus());
+
+    KeyInsightInfoResponse result = (KeyInsightInfoResponse) 
response.getEntity();
+    assertEquals(4, result.getNonFSOKeyInfoList().size(), "Expected 4 keys 
after 'fileb1'");
+    assertEquals("/volb/bucketb1/fileb5", result.getLastKey(), "Expected last 
key to be 'fileb5'");
+  }
+
   /**
    * Tests the NSSummaryEndpoint for a given volume, bucket, and directory 
structure.
    * The test setup mimics the following filesystem structure with specified 
sizes:
@@ -566,7 +610,7 @@ public class TestOMDBInsightSearchEndpoint extends 
AbstractReconSqlDBTest {
 
     // Create Bucket in volb
     createBucket("volb", "bucketb1", 1000 + 1000 + 1000 + 1000 + 1000,
-            getOBSBucketLayout());
+        getOBSBucketLayout());
     createBucket("volb", "bucketb2", 0, getOBSBucketLayout()); // Empty Bucket
 
     // Create Bucket in volc


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

Reply via email to