luigidemasi commented on code in PR #20100:
URL: https://github.com/apache/camel/pull/20100#discussion_r2581200058


##########
components/camel-smb/src/main/java/org/apache/camel/component/smb/SmbOperations.java:
##########
@@ -192,27 +193,63 @@ public boolean existsFile(String name) throws 
GenericFileOperationFailedExceptio
 
     @Override
     public boolean renameFile(String from, String to) throws 
GenericFileOperationFailedException {
+        boolean renamed;
         connectIfNecessary();
-        try (File src
-                = share.openFile(from, EnumSet.of(AccessMask.GENERIC_READ, 
AccessMask.DELETE), null,
-                        SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, 
null)) {
-
-            try (File dst
-                    = share.openFile(to, EnumSet.of(AccessMask.GENERIC_WRITE), 
EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL),
-                            SMB2ShareAccess.ALL, 
SMB2CreateDisposition.FILE_CREATE,
-                            
EnumSet.of(SMB2CreateOptions.FILE_DIRECTORY_FILE))) {
-
-                src.remoteCopyTo(dst);
-            } catch (Exception e) {
-                throw new GenericFileOperationFailedException(e.getMessage(), 
e);
+        try (File src = share.openFile(from, 
EnumSet.of(AccessMask.GENERIC_READ, AccessMask.DELETE), null,
+                SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null)) {
+            if (configuration.isRenameUsingCopy()) {
+                renamed = copyAndDeleteRenameStrategy(src, to);
+            } else {
+                renamed = atomicRenameFile(src, to);
+                if (!renamed && configuration.isCopyAndDeleteOnRenameFail()) {
+                    // we could not rename using atomic rename strategy, so 
lets fallback and do a copy/delete approach.
+                    LOG.debug("Cannot rename file from: {} to: {}, will now 
use a copy/delete approach instead",
+                            src.getUncPath(), to);
+                    renamed = copyAndDeleteRenameStrategy(src, to);
+                }
             }
-
-            src.deleteOnClose();
         } catch (SMBRuntimeException smbre) {
             safeDisconnect(smbre);
             throw smbre;
         }
-        return true;
+        return renamed;
+    }
+
+    public boolean atomicRenameFile(File src, String to)
+            throws GenericFileOperationFailedException {
+        try {
+            src.rename(to);
+            LOG.debug("Renamed file: {} to: {} using atomic rename", 
src.getUncPath(), to);
+            return true;
+        } catch (Throwable e) {
+            if (configuration.isCopyAndDeleteOnRenameFail()) {
+                // Fallback is enabled, log warning and return false to 
trigger fallback
+                LOG.warn(
+                        "Failed to rename file: {} to: {} using atomic rename. 
Will fallback to copy+delete strategy. Reason: {}",
+                        src.getUncPath(), to, e.getMessage());
+                return false;
+            } else {
+                // Fallback is disabled, throw exception to fail the operation
+                throw new GenericFileOperationFailedException(
+                        "Failed to rename file: " + src.getUncPath() + " to: " 
+ to + " using atomic rename", e);
+            }
+        }
+    }
+
+    public boolean copyAndDeleteRenameStrategy(File src, String to) throws 
SMBApiException {
+        try (File dst
+                = share.openFile(to, EnumSet.of(AccessMask.GENERIC_WRITE), 
EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL),
+                        SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_CREATE,
+                        
EnumSet.of(SMB2CreateOptions.FILE_NON_DIRECTORY_FILE))) {
+
+            src.remoteCopyTo(dst);
+            src.deleteOnClose();
+            LOG.debug("Renamed file: {} to: {} using copy+delete strategy", 
src.getUncPath(), to);
+            return true;
+        } catch (Exception e) {

Review Comment:
   Actually, SMBRuntimeException isn't the only exception that could be thrown 
here. I kept the generic Exception catch to ensure we cover all failure 
scenarios, consistent with the previous implementation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to