@@ -814,11 +814,72 @@ public void rename(RenameRequest renameRequest)
814814 "region is null, region in clientConfig must be specified when rename" );
815815 rejectEmpty (renameRequest .getSrcObject (), "The length of the src key must be greater than 0" );
816816 rejectEmpty (renameRequest .getDstObject (), "The length of the dst key must be greater than 0" );
817+
818+ String srcInodeId = "" ;
819+ if (clientConfig .isRenameFaultTolerant ()) {
820+ srcInodeId = getObjectInodeId (renameRequest .getBucketName (), renameRequest .getSrcObject (), renameRequest .getFixedEndpointAddr (),
821+ renameRequest .getCustomRequestHeaders ());
822+ }
823+
817824 CosHttpRequest <RenameRequest > request = createRequest (renameRequest .getBucketName (),
818825 renameRequest .getDstObject (), renameRequest , HttpMethodName .PUT );
819826 request .addParameter ("rename" , null );
820827 request .addHeader ("x-cos-rename-source" , UrlEncoderUtils .encodeEscapeDelimiter (renameRequest .getSrcObject ()));
821- invoke (request , voidCosResponseHandler );
828+ try {
829+ invoke (request , voidCosResponseHandler );
830+ } catch (CosServiceException cse ) {
831+ if (clientConfig .isRenameFaultTolerant () && cse .getStatusCode () == 404 && !srcInodeId .isEmpty ()) {
832+ if (!checkResultForRenameObject (srcInodeId , renameRequest )) {
833+ throw cse ;
834+ }
835+ } else {
836+ throw cse ;
837+ }
838+ }
839+ }
840+
841+ private boolean checkResultForRenameObject (String srcInodeId , RenameRequest renameRequest ) {
842+ /**
843+ * try to head src object and dst object, and check their inode ids when catch exception
844+ * rename request is successful only if src object does not exist and the inode ids of the source object and the target object are the same
845+ * */
846+ try {
847+ getObjectInodeId (renameRequest .getBucketName (), renameRequest .getSrcObject (), renameRequest .getFixedEndpointAddr (), renameRequest .getCustomRequestHeaders ());
848+ } catch (CosServiceException cse ) {
849+ if (cse .getStatusCode () != 404 ) {
850+ log .info ("catch CosServiceException and status code is not 404 when getting the inode id of the source object, exp: " , cse );
851+ return false ;
852+ }
853+ } catch (CosClientException cce ) {
854+ log .info ("catch CosClientException when getting the inode id of the source object, exp: " , cce );
855+ return false ;
856+ }
857+
858+ String dstInodeId ;
859+ try {
860+ dstInodeId = getObjectInodeId (renameRequest .getBucketName (), renameRequest .getDstObject (), renameRequest .getFixedEndpointAddr (), renameRequest .getCustomRequestHeaders ());
861+ } catch (Exception e ) {
862+ log .info ("catch exception when getting the inode id of the target object, exp: " , e );
863+ return false ;
864+ }
865+ return Objects .equals (dstInodeId , srcInodeId );
866+ }
867+
868+ private String getObjectInodeId (String bucketName , String key , String fixedEndpointAddr , Map <String , String > customHeaders )
869+ throws CosServiceException , CosClientException {
870+ GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest (bucketName , key );
871+ if (fixedEndpointAddr != null && !fixedEndpointAddr .isEmpty ()) {
872+ getObjectMetadataRequest .setFixedEndpointAddr (fixedEndpointAddr );
873+ }
874+
875+ if (customHeaders != null ) {
876+ for (Map .Entry <String , String > e : customHeaders .entrySet ()) {
877+ getObjectMetadataRequest .putCustomRequestHeader (e .getKey (), e .getValue ());
878+ }
879+ }
880+
881+ ObjectMetadata objectMetadata = getObjectMetadata (getObjectMetadataRequest );
882+ return objectMetadata .getInodeId () == null ? "" : objectMetadata .getInodeId ();
822883 }
823884
824885 protected <UploadObjectRequest extends PutObjectRequest >
0 commit comments