Skip to content

Commit d1f6cc3

Browse files
committed
fix: fix the rename bug.
Signed-off-by: Yang Yu <[email protected]>
1 parent 12fe4f2 commit d1f6cc3

File tree

3 files changed

+53
-66
lines changed

3 files changed

+53
-66
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.qcloud.cos</groupId>
88
<artifactId>hadoop-cos</artifactId>
9-
<version>${hadoop.version}-8.3.22</version>
9+
<version>8.3.22</version>
1010
<packaging>jar</packaging>
1111

1212
<name>Apache Hadoop Tencent Cloud COS Support</name>

src/main/java/org/apache/hadoop/fs/CosNFileSystem.java

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ public FSDataOutputStream append(Path f, int bufferSize,
306306
Progressable progress) throws IOException {
307307
if (this.isPosixBucket) {
308308
throw new UnsupportedOperationException(
309-
"The posix bucket does not support append operation through S3 gateway");
309+
"The posix bucket does not support append operation through S3 gateway");
310310
}
311311

312312
// 如果配置中开启客户端加密,则不支持
@@ -317,7 +317,7 @@ public FSDataOutputStream append(Path f, int bufferSize,
317317

318318
// 如果原文件使用了客户端加密,则不支持
319319
try {
320-
if(this.getXAttr(f, CSE_ALGORITHM_USER_METADATA) != null) {
320+
if (this.getXAttr(f, CSE_ALGORITHM_USER_METADATA) != null) {
321321
throw new UnsupportedOperationException("Not supported currently because the file is encrypted by client side");
322322
}
323323
} catch (IOException e) {
@@ -406,7 +406,7 @@ public boolean truncate(Path f, long newLength) throws IOException {
406406

407407
// 如果原文件使用了客户端加密,则不支持
408408
try {
409-
if(this.getXAttr(f, CSE_ALGORITHM_USER_METADATA) != null) {
409+
if (this.getXAttr(f, CSE_ALGORITHM_USER_METADATA) != null) {
410410
throw new UnsupportedOperationException("Not supported currently because the file is encrypted by client side");
411411
}
412412
} catch (IOException e) {
@@ -1026,105 +1026,86 @@ public boolean rename(Path src, Path dst) throws IOException {
10261026
return false;
10271027
}
10281028

1029-
// the preconditions for the rename operation.
1030-
// reference: https://hadoop.apache.org/docs/r3.3.0/hadoop-project-dist/hadoop-common/filesystem/filesystem.html#rename
1031-
Pair<CosNFileStatus, CosNFileStatus> renameFileStatusPair = renameInitiate(src, dst);
1032-
1033-
// the postconditions for the rename operation.
1034-
// reference: https://hadoop.apache.org/docs/r3.3.0/hadoop-project-dist/hadoop-common/filesystem/filesystem.html#rename
1035-
if (src.equals(dst)) {
1036-
if (renameFileStatusPair.getFirst() != null) {
1037-
if (renameFileStatusPair.getFirst().isDirectory()) {
1038-
//Renaming a directory onto itself is no-op; return value is not specified.
1039-
//In POSIX the result is False; in HDFS the result is True.
1040-
return true;
1041-
}
1042-
if (renameFileStatusPair.getFirst().isFile()) {
1043-
// Renaming a file to itself is a no-op; the result is True.
1044-
return true;
1045-
}
1046-
// For symlink types, the Hadoop file system specification does not provide clear instructions,
1047-
// I tested the symlink in the POSIX file system, and the same behavior is also true.
1048-
return true;
1049-
}
1050-
return false;
1051-
}
1052-
1053-
if (!isPosixBucket) {
1054-
return internalCopyAndDelete(
1055-
src, renameFileStatusPair.getFirst(),
1056-
dst, renameFileStatusPair.getSecond());
1057-
} else {
1058-
return internalRename(src, dst);
1059-
}
1060-
}
1061-
1062-
private Pair<CosNFileStatus, CosNFileStatus> renameInitiate(Path srcPath, Path dstPath)
1063-
throws PathIOException, IOException {
1064-
// Preconditions
1065-
Preconditions.checkNotNull(srcPath);
1066-
Preconditions.checkNotNull(dstPath);
1067-
Preconditions.checkArgument(srcPath.isAbsolute());
1068-
Preconditions.checkArgument(dstPath.isAbsolute());
1069-
1070-
Pair<CosNFileStatus, CosNFileStatus> renameFileStatusPair = new Pair<>();
1071-
10721029
// Hadoop FileSystem Specification: if not exists(FS, src) : raise FileNotFoundException
10731030
CosNFileStatus srcFileStatus = null;
10741031
try {
1075-
srcFileStatus = (CosNFileStatus) this.getFileStatus(srcPath);
1032+
srcFileStatus = (CosNFileStatus) this.getFileStatus(src);
10761033
} catch (FileNotFoundException e) {
1077-
LOG.error("The source path [{}] is not exist.", srcPath);
1034+
LOG.error("The source path [{}] is not exist.", src);
10781035
throw e;
10791036
}
1080-
renameFileStatusPair.setFirst(srcFileStatus);
10811037

10821038
// Hadoop FileSystem Specification: if isDescendant(FS, src, dest) : raise IOException
1083-
Path dstParentPath = dstPath.getParent();
1084-
while (null != dstParentPath && !srcPath.equals(dstParentPath)) {
1039+
Path dstParentPath = dst.getParent();
1040+
while (null != dstParentPath && !src.equals(dstParentPath)) {
10851041
dstParentPath = dstParentPath.getParent();
10861042
}
10871043
if (null != dstParentPath) {
1088-
LOG.error("It is not allowed to rename a parent directory:{} to its subdirectory:{}.", srcPath, dstPath);
1089-
PathIOException pathIOException = new PathIOException(srcPath.toString(),
1044+
LOG.error("It is not allowed to rename a parent directory:{} to its subdirectory:{}.", src, dst);
1045+
PathIOException pathIOException = new PathIOException(src.toString(),
10901046
"It is not allowed to rename a parent directory to its subdirectory");
10911047
pathIOException.setOperation("rename");
1092-
pathIOException.setTargetPath(dstPath.toString());
1048+
pathIOException.setTargetPath(dst.toString());
10931049
throw pathIOException;
10941050
}
10951051

10961052
// Hadoop FileSystem Specification: isRoot(FS, dest) or exists(FS, parent(dest))
10971053
CosNFileStatus dstFileStatus = null;
10981054
try {
1099-
dstFileStatus = (CosNFileStatus) this.getFileStatus(dstPath);
1055+
dstFileStatus = (CosNFileStatus) this.getFileStatus(dst);
11001056
if (dstFileStatus.isFile()) {
1101-
throw new FileAlreadyExistsException(dstPath.toString());
1057+
throw new FileAlreadyExistsException(dst.toString());
11021058
} else {
11031059
// The destination path is an existing directory,
1104-
Path tempDstPath = new Path(dstPath, srcPath.getName());
1060+
dst = new Path(dst, src.getName());
11051061
try {
1106-
FileStatus fileStatus = this.getFileStatus(tempDstPath, FileStatusProbeEnum.LIST_ONLY);
1107-
if (fileStatus != null) {
1108-
throw new FileAlreadyExistsException(dstPath.toString());
1062+
dstFileStatus = (CosNFileStatus) this.getFileStatus(dst, FileStatusProbeEnum.LIST_ONLY);
1063+
if (dstFileStatus != null) {
1064+
throw new FileAlreadyExistsException(dst.toString());
11091065
}
11101066
} catch (FileNotFoundException ignore) {
11111067
// OK, expects Not Found.
11121068
}
11131069
}
1114-
renameFileStatusPair.setSecond(dstFileStatus);
11151070
} catch (FileNotFoundException e) {
11161071
// Hadoop FileSystem Specification: if isFile(FS, parent(dest)) : raise IOException
1117-
Path tempDstParentPath = dstPath.getParent();
1072+
Path tempDstParentPath = dst.getParent();
11181073
FileStatus dstParentStatus = this.getFileStatus(tempDstParentPath);
11191074
if (!dstParentStatus.isDirectory()) {
11201075
PathIOException pathIOException = new PathIOException(tempDstParentPath.toString(),
11211076
String.format("Can not rename into a file [%s]", tempDstParentPath));
1122-
pathIOException.setTargetPath(dstPath.toString());
1077+
pathIOException.setTargetPath(dst.toString());
11231078
throw pathIOException;
11241079
}
11251080
}
11261081

1127-
return renameFileStatusPair;
1082+
// the postconditions for the rename operation.
1083+
// reference: https://hadoop.apache.org/docs/r3.3.0/hadoop-project-dist/hadoop-common/filesystem/filesystem.html#rename
1084+
if (src.equals(dst)) {
1085+
if (srcFileStatus.isDirectory()) {
1086+
//Renaming a directory onto itself is no-op; return value is not specified.
1087+
//In POSIX the result is False; in HDFS the result is True.
1088+
return true;
1089+
}
1090+
if (srcFileStatus.isFile()) {
1091+
// Renaming a file to itself is a no-op; the result is True.
1092+
return true;
1093+
}
1094+
if (srcFileStatus.isSymlink()) {
1095+
// For symlink types, the Hadoop file system specification does not provide clear instructions,
1096+
// I tested the symlink in the POSIX file system, and the same behavior is also true.
1097+
return true;
1098+
}
1099+
return false;
1100+
}
1101+
1102+
if (!isPosixBucket) {
1103+
return internalCopyAndDelete(
1104+
src, srcFileStatus,
1105+
dst, dstFileStatus);
1106+
} else {
1107+
return internalRename(src, dst);
1108+
}
11281109
}
11291110

11301111
private boolean internalCopyAndDelete(Path srcPath, CosNFileStatus srcFileStatus,

src/test/java/org/apache/hadoop/fs/ITestCosNFileSystemRename.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ public void testRenameWithPreExistingDestination() throws Throwable {
3232
createBaseFileWithData(10, src);
3333
Path dest = new Path(testPath, "dest");
3434
createBaseFileWithData(10, dest);
35-
assertRenameOutcome(fs, src, dest, false);
35+
boolean exceptionThrown = false;
36+
try {
37+
assertRenameOutcome(fs, src, dest, false);
38+
} catch (FileAlreadyExistsException e) {
39+
exceptionThrown = true;
40+
}
41+
assertTrue("Expected FileAlreadyExistsException to be thrown", exceptionThrown);
3642
}
3743

3844
@Test

0 commit comments

Comments
 (0)