From 20aacf3ab4e68aeaaba066dfcd0f839ab657f96a Mon Sep 17 00:00:00 2001 From: Xavier Roche Date: Sun, 15 Feb 2015 10:53:23 +0100 Subject: [PATCH] Added CephMount.flock() Also added corresponding unit tests --- src/java/java/com/ceph/fs/CephMount.java | 30 ++++++++++++ src/java/native/libcephfs_jni.cc | 51 ++++++++++++++++++++ src/java/test/com/ceph/fs/CephMountTest.java | 29 +++++++++++ 3 files changed, 110 insertions(+) diff --git a/src/java/java/com/ceph/fs/CephMount.java b/src/java/java/com/ceph/fs/CephMount.java index 79a48b3d9b8f..07819efa68f8 100644 --- a/src/java/java/com/ceph/fs/CephMount.java +++ b/src/java/java/com/ceph/fs/CephMount.java @@ -79,6 +79,15 @@ public class CephMount { public static final int XATTR_REPLACE = 2; public static final int XATTR_NONE = 3; + /* + * Flags for flock(); + * + * Must be synchronized with JNI if changed. + */ + public static final int LOCK_SH = 1; + public static final int LOCK_EX = 2; + public static final int LOCK_NB = 4; + public static final int LOCK_UN = 8; /* * This is run by the class loader and will report early any problems @@ -685,6 +694,27 @@ public class CephMount { private static native int native_ceph_fsync(long mountp, int fd, boolean dataonly); + /** + * Apply or remove an advisory lock. + * + * @param fd File descriptor to synchronize. + * @param operation the advisory lock operation to be performed on the file + * descriptor among LOCK_SH (shared lock), LOCK_EX (exclusive lock), + * or LOCK_UN (remove lock). The LOCK_NB value can be ORed to perform a + * non-blocking operation. + * @param owner the user-supplied owner identifier (an arbitrary integer) + */ + public void flock(int fd, int operation, long owner) throws IOException { + rlock.lock(); + try { + native_ceph_flock(instance_ptr, fd, operation, owner); + } finally { + rlock.unlock(); + } + } + + private static native int native_ceph_flock(long mountp, int fd, int operation, long owner); + /** * Get file status. * diff --git a/src/java/native/libcephfs_jni.cc b/src/java/native/libcephfs_jni.cc index 99ab3f48c10e..050acc3f8a0a 100644 --- a/src/java/native/libcephfs_jni.cc +++ b/src/java/native/libcephfs_jni.cc @@ -87,6 +87,14 @@ #define JAVA_XATTR_REPLACE 2 #define JAVA_XATTR_NONE 3 +/* + * flock flags. sync with CephMount.java if changed. + */ +#define JAVA_LOCK_SH 1 +#define JAVA_LOCK_EX 2 +#define JAVA_LOCK_NB 4 +#define JAVA_LOCK_UN 8 + /* Map JAVA_O_* open flags to values in libc */ static inline int fixup_open_flags(jint jflags) { @@ -1765,6 +1773,49 @@ JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1fsync return ret; } +/* + * Class: com_ceph_fs_CephMount + * Method: native_ceph_flock + * Signature: (JIZ)I + */ +JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1flock + (JNIEnv *env, jclass clz, jlong j_mntp, jint j_fd, jint j_operation, jlong j_owner) +{ + struct ceph_mount_info *cmount = get_ceph_mount(j_mntp); + CephContext *cct = ceph_get_mount_context(cmount); + int ret; + + ldout(cct, 10) << "jni: flock: fd " << (int)j_fd << + " operation " << j_operation << " owner " << j_owner << dendl; + + int operation = 0; + +#define MAP_FLOCK_FLAG(JNI_MASK, NATIVE_MASK) do { \ + if ((j_operation & JNI_MASK) != 0) { \ + operation |= NATIVE_MASK; \ + j_operation &= ~JNI_MASK; \ + } \ + } while(0) + MAP_FLOCK_FLAG(JAVA_LOCK_SH, LOCK_SH); + MAP_FLOCK_FLAG(JAVA_LOCK_EX, LOCK_EX); + MAP_FLOCK_FLAG(JAVA_LOCK_NB, LOCK_NB); + MAP_FLOCK_FLAG(JAVA_LOCK_UN, LOCK_UN); + if (j_operation != 0) { + cephThrowIllegalArg(env, "flock flags"); + return -EINVAL; + } +#undef MAP_FLOCK_FLAG + + ret = ceph_flock(cmount, (int)j_fd, operation, (uint64_t) j_owner); + + ldout(cct, 10) << "jni: flock: exit ret " << ret << dendl; + + if (ret) + handle_error(env, ret); + + return ret; +} + /* * Class: com_ceph_fs_CephMount * Method: native_ceph_fstat diff --git a/src/java/test/com/ceph/fs/CephMountTest.java b/src/java/test/com/ceph/fs/CephMountTest.java index 82c3f1b64579..9315c4b9191f 100644 --- a/src/java/test/com/ceph/fs/CephMountTest.java +++ b/src/java/test/com/ceph/fs/CephMountTest.java @@ -790,6 +790,35 @@ public class CephMountTest { mount.unlink(path); } + /* + * flock + */ + + @Test + public void test_flock() throws Exception { + String path = makePath(); + int fd = createFile(path, 123); + mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 42); + mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 43); + mount.flock(fd, CephMount.LOCK_UN, 42); + mount.flock(fd, CephMount.LOCK_UN, 43); + mount.flock(fd, CephMount.LOCK_EX | CephMount.LOCK_NB, 42); + try { + mount.flock(fd, CephMount.LOCK_SH | CephMount.LOCK_NB, 43); + assertTrue(false); + } catch(IOException io) {} + try { + mount.flock(fd, CephMount.LOCK_EX | CephMount.LOCK_NB, 43); + assertTrue(false); + } catch(IOException io) {} + mount.flock(fd, CephMount.LOCK_SH, 42); // downgrade + mount.flock(fd, CephMount.LOCK_SH, 43); + mount.flock(fd, CephMount.LOCK_UN, 42); + mount.flock(fd, CephMount.LOCK_UN, 43); + mount.close(fd); + mount.unlink(path); + } + /* * fstat * -- 2.47.3