From: Noah Watkins Date: Thu, 21 Mar 2013 22:41:10 +0000 (-0700) Subject: java: support ceph_get_file_extent_osds X-Git-Tag: v0.62~172^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=60fe1367fe31792216627499a7a5414db36cd7a9;p=ceph.git java: support ceph_get_file_extent_osds Signed-off-by: Noah Watkins --- diff --git a/src/java/Makefile.am b/src/java/Makefile.am index b8ab5f4b3f53..d37e700aeb4b 100644 --- a/src/java/Makefile.am +++ b/src/java/Makefile.am @@ -9,7 +9,8 @@ JAVA_SRC = \ java/com/ceph/fs/CephFileAlreadyExistsException.java \ java/com/ceph/fs/CephAlreadyMountedException.java \ java/com/ceph/fs/CephNotDirectoryException.java \ - java/com/ceph/fs/CephPoolException.java + java/com/ceph/fs/CephPoolException.java \ + java/com/ceph/fs/CephFileExtent.java JAVA_TEST_SRC = \ test/com/ceph/fs/CephDoubleMountTest.java \ diff --git a/src/java/java/com/ceph/fs/CephFileExtent.java b/src/java/java/com/ceph/fs/CephFileExtent.java new file mode 100644 index 000000000000..e15ce51796a5 --- /dev/null +++ b/src/java/java/com/ceph/fs/CephFileExtent.java @@ -0,0 +1,56 @@ +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +package com.ceph.fs; + +/** + * Holds information about a file extent in CephFS. + */ +public class CephFileExtent { + private long offset; + private long length; + private int[] osds; + + CephFileExtent(long offset, long length, int[] osds) { + this.offset = offset; + this.length = length; + this.osds = osds; + } + + /** + * Get starting offset of extent. + */ + public long getOffset() { + return offset; + } + + /** + * Get length of extent. + */ + public long getLength() { + return length; + } + + /** + * Get list of OSDs with this extent. + */ + public int[] getOSDs() { + return osds; + } +} diff --git a/src/java/java/com/ceph/fs/CephMount.java b/src/java/java/com/ceph/fs/CephMount.java index 6051cf635d0c..e6a3721ccd63 100644 --- a/src/java/java/com/ceph/fs/CephMount.java +++ b/src/java/java/com/ceph/fs/CephMount.java @@ -988,4 +988,22 @@ public class CephMount { } private static native int native_ceph_get_pool_replication(long mountp, int pool_id) throws FileNotFoundException; + + /** + * Get file extent containing a given offset. + * + * @param fd The file descriptor. + * @param offset Offset in file. + * @return A CephFileExtent object. + */ + public CephFileExtent get_file_extent(int fd, long offset) { + rlock.lock(); + try { + return native_ceph_get_file_extent_osds(instance_ptr, fd, offset); + } finally { + rlock.unlock(); + } + } + + private static native CephFileExtent native_ceph_get_file_extent_osds(long mountp, int fd, long offset); } diff --git a/src/java/native/libcephfs_jni.cc b/src/java/native/libcephfs_jni.cc index 2ce8cd3db191..4a205b903717 100644 --- a/src/java/native/libcephfs_jni.cc +++ b/src/java/native/libcephfs_jni.cc @@ -34,6 +34,7 @@ #define CEPH_STAT_CP "com/ceph/fs/CephStat" #define CEPH_STAT_VFS_CP "com/ceph/fs/CephStatVFS" +#define CEPH_FILE_EXTENT_CP "com/ceph/fs/CephFileExtent" #define CEPH_MOUNT_CP "com/ceph/fs/CephMount" #define CEPH_NOTMOUNTED_CP "com/ceph/fs/CephNotMountedException" #define CEPH_FILEEXISTS_CP "com/ceph/fs/CephFileAlreadyExistsException" @@ -149,6 +150,10 @@ static jfieldID cephstatvfs_namemax_fid; /* Cached field IDs for com.ceph.fs.CephMount */ static jfieldID cephmount_instance_ptr_fid; +/* Cached field IDs for com.ceph.fs.CephFileExtent */ +static jclass cephfileextent_cls; +static jmethodID cephfileextent_ctor_fid; + /* * Exception throwing helper. Adapted from Apache Hadoop header * org_apache_hadoop.h by adding the do {} while (0) construct. @@ -260,6 +265,7 @@ static void setup_field_ids(JNIEnv *env, jclass clz) { jclass cephstat_cls; jclass cephstatvfs_cls; + jclass tmp_cephfileextent_cls; /* * Get a fieldID from a class with a specific type @@ -312,6 +318,19 @@ static void setup_field_ids(JNIEnv *env, jclass clz) GETFID(cephstatvfs, fsid, J); GETFID(cephstatvfs, namemax, J); + /* Cache CephFileExtent fields */ + + tmp_cephfileextent_cls = env->FindClass(CEPH_FILE_EXTENT_CP); + if (!tmp_cephfileextent_cls) + return; + + cephfileextent_cls = (jclass)env->NewGlobalRef(tmp_cephfileextent_cls); + env->DeleteLocalRef(tmp_cephfileextent_cls); + + cephfileextent_ctor_fid = env->GetMethodID(cephfileextent_cls, "", "(JJ[I)V"); + if (!cephfileextent_ctor_fid) + return; + #undef GETFID cephmount_instance_ptr_fid = env->GetFieldID(clz, "instance_ptr", "J"); @@ -2627,3 +2646,70 @@ JNIEXPORT jint JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1pool_1repli return ret; } + +/* + * Class: com_ceph_fs_CephMount + * Method: native_ceph_get_file_extent_osds + * Signature: (JIJ)Lcom/ceph/fs/CephFileExtent; + */ +JNIEXPORT jobject JNICALL Java_com_ceph_fs_CephMount_native_1ceph_1get_1file_1extent_1osds + (JNIEnv *env, jclass clz, jlong mntp, jint fd, jlong off) +{ + struct ceph_mount_info *cmount = get_ceph_mount(mntp); + CephContext *cct = ceph_get_mount_context(cmount); + jobject extent = NULL; + int ret, nosds, *osds = NULL; + jintArray osd_array; + loff_t len; + + CHECK_MOUNTED(cmount, NULL); + + ldout(cct, 10) << "jni: get_file_extent_osds: fd " << fd << " off " << off << dendl; + + for (;;) { + /* get pg size */ + ret = ceph_get_file_extent_osds(cmount, fd, off, NULL, NULL, 0); + if (ret < 0) + break; + + /* alloc osd id array */ + if (osds) + delete [] osds; + nosds = ret; + osds = new int[nosds]; + + /* get osd ids */ + ret = ceph_get_file_extent_osds(cmount, fd, off, &len, osds, nosds); + if (ret == -ERANGE) + continue; + else + break; + } + + ldout(cct, 10) << "jni: get_file_extent_osds: ret " << ret << dendl; + + if (ret < 0) { + handle_error(env, ret); + goto out; + } + + nosds = ret; + + osd_array = env->NewIntArray(nosds); + if (!osd_array) + goto out; + + env->SetIntArrayRegion(osd_array, 0, nosds, osds); + if (env->ExceptionOccurred()) + goto out; + + extent = env->NewObject(cephfileextent_cls, cephfileextent_ctor_fid, off, len, osd_array); + if (!extent) + goto out; + +out: + if (osds) + delete [] osds; + + return extent; +} diff --git a/src/java/test/com/ceph/fs/CephMountTest.java b/src/java/test/com/ceph/fs/CephMountTest.java index 7fbc94c77933..22274d1905c5 100644 --- a/src/java/test/com/ceph/fs/CephMountTest.java +++ b/src/java/test/com/ceph/fs/CephMountTest.java @@ -953,4 +953,32 @@ public class CephMountTest { public void test_get_file_pool_name_ebadf() throws Exception { String pool = mount.get_file_pool_name(-40); } + + @Test + public void test_get_file_exist() throws Exception { + int stripe_unit = 1<<18; + String path = makePath(); + int fd = mount.open(path, CephMount.O_WRONLY|CephMount.O_CREAT, 0, + stripe_unit, 2, stripe_unit*2, null); + + CephFileExtent e = mount.get_file_extent(fd, 0); + assertTrue(e.getOSDs().length > 0); + + assertTrue(e.getOffset() == 0); + assertTrue(e.getLength() == stripe_unit); + + e = mount.get_file_extent(fd, stripe_unit/2); + assertTrue(e.getOffset() == stripe_unit/2); + assertTrue(e.getLength() == stripe_unit/2); + + e = mount.get_file_extent(fd, 3*stripe_unit/2-1); + assertTrue(e.getOffset() == 3*stripe_unit/2-1); + assertTrue(e.getLength() == stripe_unit/2+1); + + e = mount.get_file_extent(fd, 3*stripe_unit/2+1); + assertTrue(e.getLength() == stripe_unit/2-1); + + mount.close(fd); + mount.unlink(path); + } }