Skip to content

Commit 50e8e49

Browse files
authored
HDDS-4364: [FSO]List FileStatus : startKey can be a non-existed path (#3481)
1 parent f3dc158 commit 50e8e49

3 files changed

Lines changed: 253 additions & 58 deletions

File tree

hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
import static org.apache.hadoop.ozone.OzoneConsts.QUOTA_RESET;
6363
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
64+
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.FILE_NOT_FOUND;
6465

6566
/**
6667
* A class that encapsulates OzoneBucket.
@@ -1107,7 +1108,8 @@ private void getSeekPathsBetweenKeyPrefixAndStartKey(String keyPrefix,
11071108

11081109
String parentStartKeyPath = OzoneFSUtils.getParentDir(startKey);
11091110

1110-
if (StringUtils.compare(parentStartKeyPath, keyPrefix) >= 0) {
1111+
if (StringUtils.isNotBlank(startKey) &&
1112+
StringUtils.compare(parentStartKeyPath, keyPrefix) >= 0) {
11111113
seekPaths.add(new ImmutablePair<>(parentStartKeyPath, startKey));
11121114

11131115
// recursively fetch all the sub-paths between keyPrefix and prevKey
@@ -1132,46 +1134,65 @@ List<OzoneKey> getNextListOfKeys(String prevKey) throws IOException {
11321134
}
11331135
setKeyPrefix(keyPrefixName);
11341136

1135-
if (StringUtils.isNotBlank(prevKey) &&
1136-
StringUtils.startsWith(prevKey, getKeyPrefix())) {
1137-
// 1. Prepare all the seekKeys after the prefixKey.
1138-
// Example case: prefixKey="a1", startKey="a1/b2/d2/f3/f31.tx"
1139-
// Now, stack should be build with all the levels after prefixKey
1140-
// Stack format => <keyPrefix and startKey>, startKey should be an
1141-
// immediate child of keyPrefix.
1142-
// _______________________________________
1143-
// Stack=> top | < a1/b2/d2/f3, a1/b2/d2/f3/f31.tx > |
1144-
// |-------------------------------------|
1145-
// | < a1/b2/d2, a1/b2/d2/f3 > |
1146-
// |-------------------------------------|
1147-
// | < a1/b2, a1/b2/d2 > |
1148-
// |-------------------------------------|
1149-
// bottom | < a1, a1/b2 > |
1150-
// --------------------------------------|
1151-
List<Pair<String, String>> seekPaths = new ArrayList<>();
1152-
1153-
if (StringUtils.isNotBlank(getKeyPrefix())) {
1154-
String parentStartKeyPath = OzoneFSUtils.getParentDir(prevKey);
1155-
if (StringUtils.compare(parentStartKeyPath, getKeyPrefix()) >= 0) {
1156-
// Add the leaf node to the seek path. The idea is to search for
1157-
// sub-paths if the given start key is a directory.
1137+
if (StringUtils.isNotBlank(prevKey)) {
1138+
if (StringUtils.startsWith(prevKey, getKeyPrefix())) {
1139+
// 1. Prepare all the seekKeys after the prefixKey.
1140+
// Example case: prefixKey="a1", startKey="a1/b2/d2/f3/f31.tx"
1141+
// Now, stack should be build with all the levels after prefixKey
1142+
// Stack format => <keyPrefix and startKey>, startKey should be an
1143+
// immediate child of keyPrefix.
1144+
// _______________________________________
1145+
// Stack=> top | < a1/b2/d2/f3, a1/b2/d2/f3/f31.tx > |
1146+
// |-------------------------------------|
1147+
// | < a1/b2/d2, a1/b2/d2/f3 > |
1148+
// |-------------------------------------|
1149+
// | < a1/b2, a1/b2/d2 > |
1150+
// |-------------------------------------|
1151+
// bottom | < a1, a1/b2 > |
1152+
// --------------------------------------|
1153+
List<Pair<String, String>> seekPaths = new ArrayList<>();
1154+
1155+
if (StringUtils.isNotBlank(getKeyPrefix())) {
1156+
String parentStartKeyPath = OzoneFSUtils.getParentDir(prevKey);
1157+
if (StringUtils.compare(parentStartKeyPath, getKeyPrefix()) >=
1158+
0) {
1159+
// Add the leaf node to the seek path. The idea is to search for
1160+
// sub-paths if the given start key is a directory.
1161+
seekPaths.add(new ImmutablePair<>(prevKey, ""));
1162+
removeStartKey = prevKey;
1163+
getSeekPathsBetweenKeyPrefixAndStartKey(getKeyPrefix(), prevKey,
1164+
seekPaths);
1165+
} else if (StringUtils.compare(prevKey, getKeyPrefix()) >= 0) {
1166+
// Add the leaf node to the seek path. The idea is to search for
1167+
// sub-paths if the given start key is a directory.
1168+
seekPaths.add(new ImmutablePair<>(prevKey, ""));
1169+
removeStartKey = prevKey;
1170+
}
1171+
} else {
1172+
// Key Prefix is Blank. The seek all the keys with startKey.
11581173
seekPaths.add(new ImmutablePair<>(prevKey, ""));
11591174
removeStartKey = prevKey;
11601175
getSeekPathsBetweenKeyPrefixAndStartKey(getKeyPrefix(), prevKey,
11611176
seekPaths);
1162-
} else if (StringUtils.compare(prevKey, getKeyPrefix()) >= 0) {
1163-
// Add the leaf node to the seek path. The idea is to search for
1164-
// sub-paths if the given start key is a directory.
1165-
seekPaths.add(new ImmutablePair<>(prevKey, ""));
1166-
removeStartKey = prevKey;
11671177
}
1168-
}
11691178

1170-
// 2. Push elements in reverse order so that the FS tree traversal
1171-
// will occur in left-to-right fashion[Depth-First Search]
1172-
for (int index = seekPaths.size() - 1; index >= 0; index--) {
1173-
Pair<String, String> seekDirPath = seekPaths.get(index);
1174-
stack.push(seekDirPath);
1179+
// 2. Push elements in reverse order so that the FS tree traversal
1180+
// will occur in left-to-right fashion[Depth-First Search]
1181+
for (int index = seekPaths.size() - 1; index >= 0; index--) {
1182+
Pair<String, String> seekDirPath = seekPaths.get(index);
1183+
stack.push(seekDirPath);
1184+
}
1185+
} else if (StringUtils.isNotBlank(getKeyPrefix())) {
1186+
if (!OzoneFSUtils.isSibling(prevKey, getKeyPrefix())) {
1187+
// Case-1 - sibling: keyPrefix="a1/b2", startKey="a0/b123Invalid"
1188+
// Skip traversing, if the startKey is not a sibling.
1189+
return new ArrayList<>();
1190+
} else if (StringUtils.compare(prevKey, getKeyPrefix()) < 0) {
1191+
// Case-2 - compare: keyPrefix="a1/b2", startKey="a1/b123Invalid"
1192+
// Since startKey is lexographically behind keyPrefix,
1193+
// the seek precedence goes to keyPrefix.
1194+
stack.push(new ImmutablePair<>(getKeyPrefix(), ""));
1195+
}
11751196
}
11761197
}
11771198
}
@@ -1374,28 +1395,33 @@ private void addKeyPrefixInfoToResultList(String keyPrefix,
13741395
return;
13751396
}
13761397

1377-
// TODO: HDDS-4859 will fix the case where startKey not started with
1378-
// keyPrefix.
1379-
1380-
OzoneFileStatus status = proxy.getOzoneFileStatus(volumeName, name,
1381-
keyPrefix);
1398+
OzoneFileStatus status = null;
1399+
try {
1400+
status = proxy.getOzoneFileStatus(volumeName, name,
1401+
keyPrefix);
1402+
} catch (OMException ome) {
1403+
if (ome.getResult() == FILE_NOT_FOUND) {
1404+
// keyPrefix path can't be found and skip adding it to result list
1405+
return;
1406+
}
1407+
}
13821408

13831409
if (status != null) {
13841410
OmKeyInfo keyInfo = status.getKeyInfo();
13851411
String keyName = keyInfo.getKeyName();
13861412

1387-
// removeStartKey - as the startKey is a placeholder, which is
1388-
// managed internally to traverse leaf node's sub-paths.
1389-
if (StringUtils.equals(keyName, removeStartKey)) {
1390-
return;
1391-
}
1392-
13931413
if (status.isDirectory()) {
13941414
// add trailing slash to represent directory
13951415
keyName =
13961416
OzoneFSUtils.addTrailingSlashIfNeeded(keyInfo.getKeyName());
13971417
}
13981418

1419+
// removeStartKey - as the startKey is a placeholder, which is
1420+
// managed internally to traverse leaf node's sub-paths.
1421+
if (StringUtils.equals(keyName, removeStartKey)) {
1422+
return;
1423+
}
1424+
13991425
OzoneKey ozoneKey = new OzoneKey(keyInfo.getVolumeName(),
14001426
keyInfo.getBucketName(), keyName,
14011427
keyInfo.getDataSize(), keyInfo.getCreationTime(),

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OzoneFSUtils.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ public static boolean isSibling(String parentKey, String childKey) {
169169
java.nio.file.Path childParent = childPath.getParent();
170170
java.nio.file.Path parentParent = parentPath.getParent();
171171

172+
if (childParent != null && parentParent != null) {
173+
return childParent.equals(parentParent);
174+
}
175+
172176
return childParent == parentParent;
173177
}
174178

0 commit comments

Comments
 (0)