Skip to content

Commit 3246fda

Browse files
authored
feat: rename with overwrite option (#20)
fix to match java signature
1 parent 7fcb163 commit 3246fda

3 files changed

Lines changed: 93 additions & 2 deletions

File tree

c_src/libhdfs/hdfs.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#define JAVA_NET_URI "java/net/URI"
4343
#define JAVA_STRING "java/lang/String"
4444
#define READ_OPTION "org/apache/hadoop/fs/ReadOption"
45+
#define RENAME_OPTION "org/apache/hadoop/fs/Options$Rename"
4546

4647
#define JAVA_VOID "V"
4748

@@ -2025,6 +2026,82 @@ int hdfsRename(hdfsFS fs, const char *oldPath, const char *newPath)
20252026
return ret;
20262027
}
20272028

2029+
int hdfsRenameOverwrite(hdfsFS fs, const char *oldPath, const char *newPath)
2030+
{
2031+
// JAVA EQUIVALENT:
2032+
// Path old = new Path(oldPath);
2033+
// Path new = new Path(newPath);
2034+
// fs.rename(old, new, overwrite = true);
2035+
2036+
jobject jFS = (jobject)fs;
2037+
jthrowable jthr;
2038+
jobject jOldPath = NULL, jNewPath = NULL;
2039+
int ret = -1;
2040+
jvalue jVal;
2041+
jobject enumInst = NULL, enumSetObj = NULL;
2042+
2043+
//Get the JNIEnv* corresponding to current thread
2044+
JNIEnv* env = getJNIEnv();
2045+
if (env == NULL) {
2046+
errno = EINTERNAL;
2047+
return -1;
2048+
}
2049+
2050+
jthr = fetchEnumInstance(env, RENAME_OPTION,
2051+
"OVERWRITE", &enumInst);
2052+
if (jthr) {
2053+
errno = printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
2054+
"hdfsRename: fetchEnumInstance(" RENAME_OPTION ", OVERWRITE)");
2055+
goto done;
2056+
}
2057+
jthr = invokeMethod(env, &jVal, STATIC, NULL,
2058+
"java/util/EnumSet", "of",
2059+
"(Ljava/lang/Enum;)Ljava/util/EnumSet;", enumInst);
2060+
if (jthr) {
2061+
goto done;
2062+
}
2063+
enumSetObj = jVal.l;
2064+
2065+
jclass enumSetClass = (*env)->FindClass(env, "java/util/EnumSet");
2066+
jmethodID toArrayTypedMethodID = (*env)->GetMethodID(env, enumSetClass, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;");
2067+
jclass renameOptionClass = (*env)->FindClass(env, "org/apache/hadoop/fs/Options$Rename");
2068+
jobjectArray typedArray = (*env)->NewObjectArray(env, 1, renameOptionClass, NULL);
2069+
jobjectArray enumArray = (jobjectArray)(*env)->CallObjectMethod(env, enumSetObj, toArrayTypedMethodID, typedArray);
2070+
2071+
jthr = constructNewObjectOfPath(env, oldPath, &jOldPath);
2072+
if (jthr) {
2073+
errno = printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
2074+
"hdfsRename: constructNewObjectOfPath(%s)", oldPath);
2075+
goto done;
2076+
}
2077+
jthr = constructNewObjectOfPath(env, newPath, &jNewPath);
2078+
if (jthr) {
2079+
errno = printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
2080+
"hdfsRename: constructNewObjectOfPath(%s)", newPath);
2081+
goto done;
2082+
}
2083+
2084+
// Rename the file
2085+
// TODO: use rename2 here? (See HDFS-3592)
2086+
jthr = invokeMethod(env, &jVal, INSTANCE, jFS, HADOOP_FS, "rename",
2087+
"(Lorg/apache/hadoop/fs/Path;Lorg/apache/hadoop/fs/Path;[Lorg/apache/hadoop/fs/Options$Rename;)V",
2088+
jOldPath, jNewPath, enumArray);
2089+
if (jthr) {
2090+
errno = printExceptionAndFree(env, jthr, PRINT_EXC_ALL,
2091+
"hdfsRename(oldPath=%s, newPath=%s): FileSystem#rename",
2092+
oldPath, newPath);
2093+
goto done;
2094+
}
2095+
ret = 0;
2096+
2097+
done:
2098+
destroyLocalReference(env, jOldPath);
2099+
destroyLocalReference(env, jNewPath);
2100+
destroyLocalReference(env, enumInst);
2101+
destroyLocalReference(env, enumSetObj);
2102+
return ret;
2103+
}
2104+
20282105

20292106

20302107
char* hdfsGetWorkingDirectory(hdfsFS fs, char* buffer, size_t bufferSize)

c_src/libhdfs/hdfs.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,16 @@ extern "C" {
712712
LIBHDFS_EXTERNAL
713713
int hdfsRename(hdfsFS fs, const char* oldPath, const char* newPath);
714714

715+
/**
716+
* hdfsRename - Rename file and overwrite if exists.
717+
* @param fs The configured filesystem handle.
718+
* @param oldPath The path of the source file.
719+
* @param newPath The path of the destination file.
720+
* @return Returns 0 on success, -1 on error.
721+
*/
722+
LIBHDFS_EXTERNAL
723+
int hdfsRenameOverwrite(hdfsFS fs, const char* oldPath, const char* newPath);
724+
715725

716726
/**
717727
* hdfsGetWorkingDirectory - Get the current working directory for

src/hdfs.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,15 @@ impl HdfsFs {
440440
}
441441

442442
/// Rename file.
443-
pub fn rename(&self, old_path: &str, new_path: &str) -> Result<bool, HdfsErr> {
443+
pub fn rename(&self, old_path: &str, new_path: &str, overwrite: bool) -> Result<bool, HdfsErr> {
444444
if unsafe {
445445
let cstr_old_path = CString::new(old_path).unwrap();
446446
let cstr_new_path = CString::new(new_path).unwrap();
447-
hdfsRename(self.raw, cstr_old_path.as_ptr(), cstr_new_path.as_ptr())
447+
if overwrite {
448+
hdfsRenameOverwrite(self.raw, cstr_old_path.as_ptr(), cstr_new_path.as_ptr())
449+
} else {
450+
hdfsRename(self.raw, cstr_old_path.as_ptr(), cstr_new_path.as_ptr())
451+
}
448452
} == 0
449453
{
450454
Ok(true)

0 commit comments

Comments
 (0)