@@ -1560,12 +1560,17 @@ private AbfsClientRenameResult renameWithCTIdRecovery(String source,
1560
1560
try {
1561
1561
incrementAbfsRenamePath ();
1562
1562
op .execute (tracingContext );
1563
+ // AbfsClientResult contains the AbfsOperation, If recovery happened or
1564
+ // not, and the incompleteMetaDataState is true or false.
1565
+ // If we successfully rename a path and isMetadataIncompleteState was
1566
+ // true, then rename was recovered, else it didn't, this is why
1567
+ // isMetadataIncompleteState is used for renameRecovery(as the 2nd param).
1563
1568
return new AbfsClientRenameResult (op , isMetadataIncompleteState ,
1564
1569
isMetadataIncompleteState );
1565
1570
} catch (AzureBlobFileSystemException e ) {
1566
- if (! op . hasResult ()) {
1567
- throw e ;
1568
- }
1571
+ // Handle rename exceptions and retry if applicable
1572
+ handleRenameException ( source , destination , continuation ,
1573
+ tracingContext , sourceEtag , op , isMetadataIncompleteState , e );
1569
1574
1570
1575
// Check if the operation is a retried request and if the error code indicates
1571
1576
// that the source path was not found. If so, attempt recovery using CTId.
@@ -1580,10 +1585,6 @@ private AbfsClientRenameResult renameWithCTIdRecovery(String source,
1580
1585
}
1581
1586
}
1582
1587
1583
- // Handle rename exceptions and retry if applicable
1584
- handleRenameException (source , destination , continuation ,
1585
- tracingContext , sourceEtag , op , isMetadataIncompleteState );
1586
-
1587
1588
// Attempt recovery using ETag if applicable
1588
1589
if (recoveryUsingEtag (source , destination , sourceEtag ,
1589
1590
op , tracingContext , true )) {
@@ -1617,6 +1618,9 @@ private AbfsClientRenameResult renameWithETagRecovery(String source,
1617
1618
boolean hasEtag = !isEmpty (sourceEtag );
1618
1619
boolean shouldAttemptRecovery = isRenameResilience () && getIsNamespaceEnabled ();
1619
1620
if (!hasEtag && shouldAttemptRecovery ) {
1621
+ // in case eTag is already not supplied to the API
1622
+ // and rename resilience is expected and it is an HNS enabled account
1623
+ // fetch the source etag to be used later in recovery
1620
1624
try {
1621
1625
final AbfsRestOperation srcStatusOp = getPathStatus (source ,
1622
1626
false , tracingContext , null );
@@ -1648,16 +1652,17 @@ private AbfsClientRenameResult renameWithETagRecovery(String source,
1648
1652
try {
1649
1653
incrementAbfsRenamePath ();
1650
1654
op .execute (tracingContext );
1655
+ // AbfsClientResult contains the AbfsOperation, If recovery happened or
1656
+ // not, and the incompleteMetaDataState is true or false.
1657
+ // If we successfully rename a path and isMetadataIncompleteState was
1658
+ // true, then rename was recovered, else it didn't, this is why
1659
+ // isMetadataIncompleteState is used for renameRecovery(as the 2nd param).
1651
1660
return new AbfsClientRenameResult (op , isMetadataIncompleteState ,
1652
1661
isMetadataIncompleteState );
1653
1662
} catch (AzureBlobFileSystemException e ) {
1654
- if (!op .hasResult ()) {
1655
- throw e ;
1656
- }
1657
-
1658
1663
// Handle rename exceptions and retry if applicable
1659
1664
handleRenameException (source , destination , continuation ,
1660
- tracingContext , sourceEtag , op , isMetadataIncompleteState );
1665
+ tracingContext , sourceEtag , op , isMetadataIncompleteState , e );
1661
1666
1662
1667
// Attempt recovery using ETag if applicable
1663
1668
if (recoveryUsingEtag (source , destination , sourceEtag ,
@@ -1781,18 +1786,22 @@ private boolean recoveryUsingEtag(String source, String destination,
1781
1786
private void handleRenameException (final String source ,
1782
1787
final String destination , final String continuation ,
1783
1788
final TracingContext tracingContext , final String sourceEtag ,
1784
- final AbfsRestOperation op , boolean isMetadataIncompleteState )
1785
- throws IOException {
1786
- // Check if the rename operation failed due to unauthorized overwrite
1787
- // and if so, throw a FileAlreadyExistsException.
1789
+ final AbfsRestOperation op , boolean isMetadataIncompleteState ,
1790
+ AzureBlobFileSystemException e ) throws IOException {
1791
+ if (!op .hasResult ()) {
1792
+ throw e ;
1793
+ }
1794
+
1795
+ // ref: HADOOP-19393. Write permission checks can occur before validating
1796
+ // rename operation's validity. If there is an existing destination path, it may be rejected
1797
+ // with an authorization error. Catching and throwing FileAlreadyExistsException instead.
1788
1798
if (UNAUTHORIZED_BLOB_OVERWRITE .getErrorCode ()
1789
1799
.equals (op .getResult ().getStorageErrorCode ())) {
1790
1800
throw new FileAlreadyExistsException (ERR_FILE_ALREADY_EXISTS );
1791
1801
}
1792
1802
1793
- // Check if the destination parent path is not found
1794
- // and if the metadata state is incomplete.
1795
- // If so, retry the rename operation.
1803
+ // ref: HADOOP-18242. Rename failure occurring due to a rare case of
1804
+ // tracking metadata being in incomplete state.
1796
1805
if (RENAME_DESTINATION_PARENT_PATH_NOT_FOUND .getErrorCode ()
1797
1806
.equals (op .getResult ().getStorageErrorCode ())
1798
1807
&& !isMetadataIncompleteState ) {
0 commit comments