Skip to content

Commit

Permalink
HDDS-11561. Refactor Open Key Search Endpoint and Consolidate with Om…
Browse files Browse the repository at this point in the history
…DBInsightEndpoint Using StartPrefix Parameter. (apache#7336)
  • Loading branch information
ArafatKhan2198 authored Nov 26, 2024
1 parent a99ab27 commit f98eac2
Show file tree
Hide file tree
Showing 5 changed files with 367 additions and 536 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
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;
Expand All @@ -78,8 +79,12 @@

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;
Expand Down Expand Up @@ -392,6 +397,100 @@ public static StringBuilder constructFullPathPrefix(long initialParentId, String
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 -> {
Expand Down
Loading

0 comments on commit f98eac2

Please sign in to comment.