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

pifta 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 5a3b798662 HDDS-11235. Spare InfoBucket RPC call in FileSystem#mkdir() 
call. (#6990)
5a3b798662 is described below

commit 5a3b7986629d12b823cde7e31cc99f2db59cb6fa
Author: Istvan Fajth <[email protected]>
AuthorDate: Mon Aug 5 09:53:31 2024 +0200

    HDDS-11235. Spare InfoBucket RPC call in FileSystem#mkdir() call. (#6990)
---
 .../apache/hadoop/ozone/client/rpc/RpcClient.java  |   2 +
 .../ozone/BasicRootedOzoneClientAdapterImpl.java   | 121 +++++++++++----------
 2 files changed, 65 insertions(+), 58 deletions(-)

diff --git 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
index 3ddceadb46..288e5eef9a 100644
--- 
a/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
+++ 
b/hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java
@@ -2171,6 +2171,8 @@ public class RpcClient implements ClientProtocol {
   @Override
   public void createDirectory(String volumeName, String bucketName,
       String keyName) throws IOException {
+    verifyVolumeName(volumeName);
+    verifyBucketName(bucketName);
     String ownerName = getRealUserInfo().getShortUserName();
     OmKeyArgs keyArgs = new OmKeyArgs.Builder().setVolumeName(volumeName)
         .setBucketName(bucketName)
diff --git 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
index 890efd56e8..836c986ec9 100644
--- 
a/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
+++ 
b/hadoop-ozone/ozonefs-common/src/main/java/org/apache/hadoop/fs/ozone/BasicRootedOzoneClientAdapterImpl.java
@@ -241,11 +241,8 @@ public class BasicRootedOzoneClientAdapterImpl
     }
   }
 
-  OzoneBucket getBucket(OFSPath ofsPath, boolean createIfNotExist)
-      throws IOException {
-
-    return getBucket(ofsPath.getVolumeName(), ofsPath.getBucketName(),
-        createIfNotExist);
+  OzoneBucket getBucket(OFSPath ofsPath, boolean createIfNotExist)throws 
IOException {
+    return getBucket(ofsPath.getVolumeName(), ofsPath.getBucketName(), 
createIfNotExist);
   }
 
   /**
@@ -257,8 +254,7 @@ public class BasicRootedOzoneClientAdapterImpl
    * @throws IOException Exceptions other than OMException with result code
    *                     VOLUME_NOT_FOUND or BUCKET_NOT_FOUND.
    */
-  private OzoneBucket getBucket(String volumeStr, String bucketStr,
-      boolean createIfNotExist) throws IOException {
+  private OzoneBucket getBucket(String volumeStr, String bucketStr, boolean 
createIfNotExist) throws IOException {
     Preconditions.checkNotNull(volumeStr);
     Preconditions.checkNotNull(bucketStr);
 
@@ -268,7 +264,7 @@ public class BasicRootedOzoneClientAdapterImpl
           "getBucket: Invalid argument: given bucket string is empty.");
     }
 
-    OzoneBucket bucket;
+    OzoneBucket bucket = null;
     try {
       bucket = proxy.getBucketDetails(volumeStr, bucketStr);
 
@@ -280,44 +276,8 @@ public class BasicRootedOzoneClientAdapterImpl
       OzoneFSUtils.validateBucketLayout(bucket.getName(), 
resolvedBucketLayout);
     } catch (OMException ex) {
       if (createIfNotExist) {
-        // getBucketDetails can throw VOLUME_NOT_FOUND when the parent volume
-        // doesn't exist and ACL is enabled; it can only throw BUCKET_NOT_FOUND
-        // when ACL is disabled. Both exceptions need to be handled.
-        switch (ex.getResult()) {
-        case VOLUME_NOT_FOUND:
-          // Create the volume first when the volume doesn't exist
-          try {
-            objectStore.createVolume(volumeStr);
-          } catch (OMException newVolEx) {
-            // Ignore the case where another client created the volume
-            if (!newVolEx.getResult().equals(VOLUME_ALREADY_EXISTS)) {
-              throw newVolEx;
-            }
-          }
-          // No break here. Proceed to create the bucket
-        case BUCKET_NOT_FOUND:
-          // When BUCKET_NOT_FOUND is thrown, we expect the parent volume
-          // exists, so that we don't call create volume and incur
-          // unnecessary ACL checks which could lead to unwanted behavior.
-          OzoneVolume volume = proxy.getVolumeDetails(volumeStr);
-          // Create the bucket
-          try {
-            // Buckets created by OFS should be in FSO layout
-            volume.createBucket(bucketStr,
-                BucketArgs.newBuilder().setBucketLayout(
-                    this.defaultOFSBucketLayout).build());
-          } catch (OMException newBucEx) {
-            // Ignore the case where another client created the bucket
-            if (!newBucEx.getResult().equals(BUCKET_ALREADY_EXISTS)) {
-              throw newBucEx;
-            }
-          }
-          break;
-        default:
-          // Throw unhandled exception
-          throw ex;
-        }
-        // Try get bucket again
+        handleVolumeOrBucketCreationOnException(volumeStr, bucketStr, ex);
+        // Try to get the bucket again
         bucket = proxy.getBucketDetails(volumeStr, bucketStr);
       } else {
         throw ex;
@@ -327,6 +287,41 @@ public class BasicRootedOzoneClientAdapterImpl
     return bucket;
   }
 
+  private void handleVolumeOrBucketCreationOnException(String volumeStr, 
String bucketStr, OMException ex)
+      throws IOException {
+    // OM can throw VOLUME_NOT_FOUND when the parent volume does not exist, 
and in this case we may create the volume,
+    // OM can also throw BUCKET_NOT_FOUND when the parent bucket does not 
exist, and so we also may create the bucket.
+    // This method creates the volume and the bucket when an exception marks 
that they don't exist.
+    switch (ex.getResult()) {
+    case VOLUME_NOT_FOUND:
+      // Create the volume first when the volume doesn't exist
+      try {
+        objectStore.createVolume(volumeStr);
+      } catch (OMException newVolEx) {
+        // Ignore the case where another client created the volume
+        if (!newVolEx.getResult().equals(VOLUME_ALREADY_EXISTS)) {
+          throw newVolEx;
+        }
+      }
+      // No break here. Proceed to create the bucket
+    case BUCKET_NOT_FOUND:
+      // Create the bucket
+      try {
+        // Buckets created by OFS should be in FSO layout
+        BucketArgs defaultBucketArgs = 
BucketArgs.newBuilder().setBucketLayout(this.defaultOFSBucketLayout).build();
+        proxy.createBucket(volumeStr, bucketStr, defaultBucketArgs);
+      } catch (OMException newBucEx) {
+        // Ignore the case where another client created the bucket
+        if (!newBucEx.getResult().equals(BUCKET_ALREADY_EXISTS)) {
+          throw newBucEx;
+        }
+      }
+      break;
+    default:
+      throw ex;
+    }
+  }
+
   /**
    * This API returns the value what is configured at client side only. It 
could
    * differ from the server side default values. If no replication config
@@ -496,30 +491,40 @@ public class BasicRootedOzoneClientAdapterImpl
     LOG.trace("creating dir for path: {}", pathStr);
     incrementCounter(Statistic.OBJECTS_CREATED, 1);
     OFSPath ofsPath = new OFSPath(pathStr, config);
-    if (ofsPath.getVolumeName().isEmpty()) {
+
+    String volumeName = ofsPath.getVolumeName();
+    if (volumeName.isEmpty()) {
       // Volume name unspecified, invalid param, return failure
       return false;
     }
-    if (ofsPath.getBucketName().isEmpty()) {
-      // Create volume only
-      objectStore.createVolume(ofsPath.getVolumeName());
+
+    String bucketName = ofsPath.getBucketName();
+    if (bucketName.isEmpty()) {
+      // Create volume only as path only contains one element the volume.
+      objectStore.createVolume(volumeName);
       return true;
     }
+
     String keyStr = ofsPath.getKeyName();
     try {
-      OzoneBucket bucket = getBucket(ofsPath, true);
-      // Empty keyStr here indicates only volume and bucket is
-      // given in pathStr, so getBucket above should handle the creation
-      // of volume and bucket. We won't feed empty keyStr to
-      // bucket.createDirectory as that would be a NPE.
-      if (keyStr != null && keyStr.length() > 0) {
-        bucket.createDirectory(keyStr);
+      if (keyStr == null || keyStr.isEmpty()) {
+        // This is the case when the given path only contains volume and 
bucket.
+        // If the bucket does not exist, then this will throw and bucket will 
be created
+        // in handleVolumeOrBucketCreationOnException later.
+        proxy.getBucketDetails(volumeName, bucketName);
+      } else {
+        proxy.createDirectory(volumeName, bucketName, keyStr);
       }
     } catch (OMException e) {
       if (e.getResult() == OMException.ResultCodes.FILE_ALREADY_EXISTS) {
         throw new FileAlreadyExistsException(e.getMessage());
       }
-      throw e;
+      // Create volume and bucket if they do not exist, and retry key creation.
+      // This call will throw an exception if it fails, or the exception is 
different than it handles.
+      handleVolumeOrBucketCreationOnException(volumeName, bucketName, e);
+      if (keyStr != null && !keyStr.isEmpty()) {
+        proxy.createDirectory(volumeName, bucketName, keyStr);
+      }
     }
     return true;
   }


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

Reply via email to