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

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 77680bda7d5 HDDS-12094. OzoneKey isFile returns true for directories 
(#8838)
77680bda7d5 is described below

commit 77680bda7d59c526be823a7f8127abfc091a020e
Author: Anastasia Kostryukova <[email protected]>
AuthorDate: Mon Nov 17 15:16:24 2025 +0300

    HDDS-12094. OzoneKey isFile returns true for directories (#8838)
    
    Co-authored-by: Rishabh Patel <[email protected]>
---
 .../hadoop/ozone/om/helpers/BasicOmKeyInfo.java    | 15 ++++++--
 .../src/main/smoketest/compatibility/read.robot    | 13 +++++++
 .../ozone/client/rpc/OzoneRpcClientTests.java      | 40 ++++++++++++++++++++++
 .../src/main/proto/OmClientProtocol.proto          |  1 +
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/BasicOmKeyInfo.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/BasicOmKeyInfo.java
index 371e4f38c7b..420bac76664 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/BasicOmKeyInfo.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/BasicOmKeyInfo.java
@@ -202,6 +202,7 @@ public BasicKeyInfo getProtobuf() {
         .setDataSize(dataSize)
         .setCreationTime(creationTime)
         .setModificationTime(modificationTime)
+        .setIsFile(isFile)
         .setType(replicationConfig.getReplicationType())
         .setIsEncrypted(isEncrypted);
     if (ownerName != null) {
@@ -241,10 +242,15 @@ public static BasicOmKeyInfo getFromProtobuf(BasicKeyInfo 
basicKeyInfo,
             basicKeyInfo.getFactor(),
             basicKeyInfo.getEcReplicationConfig()))
         .setETag(basicKeyInfo.getETag())
-        .setIsFile(!keyName.endsWith("/"))
         .setOwnerName(basicKeyInfo.getOwnerName())
         .setIsEncrypted(basicKeyInfo.getIsEncrypted());
 
+    if (basicKeyInfo.hasIsFile()) {
+      builder.setIsFile(basicKeyInfo.getIsFile());
+    } else {
+      builder.setIsFile(!keyName.endsWith("/"));
+    }
+
     return builder.build();
   }
 
@@ -268,10 +274,15 @@ public static BasicOmKeyInfo getFromProtobuf(String 
volumeName,
             basicKeyInfo.getFactor(),
             basicKeyInfo.getEcReplicationConfig()))
         .setETag(basicKeyInfo.getETag())
-        .setIsFile(!keyName.endsWith("/"))
         .setOwnerName(basicKeyInfo.getOwnerName())
         .setIsEncrypted(basicKeyInfo.getIsEncrypted());
 
+    if (basicKeyInfo.hasIsFile()) {
+      builder.setIsFile(basicKeyInfo.getIsFile());
+    } else {
+      builder.setIsFile(!keyName.endsWith("/"));
+    }
+
     return builder.build();
   }
 
diff --git a/hadoop-ozone/dist/src/main/smoketest/compatibility/read.robot 
b/hadoop-ozone/dist/src/main/smoketest/compatibility/read.robot
index b5dfbb9739e..406b19fbe4c 100644
--- a/hadoop-ozone/dist/src/main/smoketest/compatibility/read.robot
+++ b/hadoop-ozone/dist/src/main/smoketest/compatibility/read.robot
@@ -155,3 +155,16 @@ HSync Lease Recover Can Be Used
     Pass Execution If    '${CLIENT_VERSION}' < '${HSYNC_VERSION}'    Client 
does not support HSYNC
     Pass Execution If    '${CLUSTER_VERSION}' < '${HSYNC_VERSION}'   Cluster 
does not support HSYNC
     Execute    ozone admin om lease recover 
--path=ofs://om/vol1/fso-bucket-${DATA_VERSION}/dir/subdir/file
+
+Key Info File Flag Should Be Set Correctly
+    Pass Execution If    '${CLUSTER_VERSION}' <= '${EC_VERSION}'   Cluster 
does not support 'file' flag
+    Pass Execution If    '${CLIENT_VERSION}' <= '${EC_VERSION}'    Client does 
not support 'file' flag
+
+    ${dirpath} =      Set Variable    
/vol1/fso-bucket-${DATA_VERSION}/dir/subdir/
+    ${filepath} =     Set Variable    ${dirpath}file
+
+    ${key_info} =     Execute    ozone sh key info ${filepath}
+    Should Contain    ${key_info}    \"file\" : true
+
+    ${dir_info} =     Execute    ozone sh key info ${dirpath}
+    Should Contain    ${dir_info}    \"file\" : false
diff --git 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
index 5cc2e8ec435..554b125ddbe 100644
--- 
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
+++ 
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/client/rpc/OzoneRpcClientTests.java
@@ -2927,6 +2927,46 @@ public void testListKey()
     assertFalse(volABucketBIter.hasNext());
   }
 
+  @Test
+  public void testListKeyDirectoriesAreNotFiles()
+      throws IOException {
+    // Test that directories in multilevel keys are not marked as files
+
+    String volumeA = "volume-a-" + RandomStringUtils.randomNumeric(5);
+    String bucketA = "bucket-a-" + RandomStringUtils.randomNumeric(5);
+    store.createVolume(volumeA);
+    OzoneVolume volA = store.getVolume(volumeA);
+    volA.createBucket(bucketA);
+    OzoneBucket volAbucketA = volA.getBucket(bucketA);
+
+    String keyBaseA = "key-a/";
+    for (int i = 0; i < 10; i++) {
+      byte[] value = RandomStringUtils.randomAscii(10240).getBytes(UTF_8);
+      OzoneOutputStream one = volAbucketA.createKey(
+          keyBaseA + i + "-" + RandomStringUtils.randomNumeric(5),
+          value.length, RATIS, ONE,
+          new HashMap<>());
+      one.write(value);
+      one.close();
+    }
+
+    Iterator<? extends OzoneKey> volABucketAIter1 = volAbucketA.listKeys(null);
+    while (volABucketAIter1.hasNext()) {
+      OzoneKey key = volABucketAIter1.next();
+      if (key.getName().endsWith("/")) {
+        assertFalse(key.isFile(), "Key '" + key.getName() + "' is not a file");
+      }
+    }
+
+    Iterator<? extends OzoneKey> volABucketAIter2 = 
volAbucketA.listKeys("key-");
+    while (volABucketAIter2.hasNext()) {
+      OzoneKey key = volABucketAIter2.next();
+      if (key.getName().endsWith("/")) {
+        assertFalse(key.isFile(), "Key '" + key.getName() + "' is not a file");
+      }
+    }
+  }
+
   @Test
   public void testListKeyOnEmptyBucket()
       throws IOException {
diff --git 
a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto 
b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
index 1e5675f612e..9d417700537 100644
--- a/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
+++ b/hadoop-ozone/interface-client/src/main/proto/OmClientProtocol.proto
@@ -1205,6 +1205,7 @@ message BasicKeyInfo {
     optional string eTag = 8;
     optional string ownerName = 9;
     optional bool isEncrypted = 10;
+    optional bool isFile = 11;
 }
 
 message DirectoryInfo {


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

Reply via email to