]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
java: support ceph_get_file_extent_osds
authorNoah Watkins <noahwatkins@gmail.com>
Thu, 21 Mar 2013 22:41:10 +0000 (15:41 -0700)
committerNoah Watkins <noahwatkins@gmail.com>
Sun, 24 Mar 2013 17:51:06 +0000 (10:51 -0700)
Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
src/java/Makefile.am
src/java/java/com/ceph/fs/CephFileExtent.java [new file with mode: 0644]
src/java/java/com/ceph/fs/CephMount.java
src/java/native/libcephfs_jni.cc
src/java/test/com/ceph/fs/CephMountTest.java

index b8ab5f4b3f5386c5fa43b809cae90a0a2461d9d9..d37e700aeb4ba7a0375061be71e20b4d545bb491 100644 (file)
@@ -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 (file)
index 0000000..e15ce51
--- /dev/null
@@ -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;
+  }
+}
index 6051cf635d0c3eabf12271157998afedc6725533..e6a3721ccd631a3a68d354724144b44ce43f36a8 100644 (file)
@@ -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);
 }
index 2ce8cd3db19175f793fc917caea2cc3c058f5734..4a205b9037171ef2805b00d275d255d9a2744eb9 100644 (file)
@@ -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, "<init>", "(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;
+}
index 7fbc94c77933cd97eb7ed32a74bdb95f8afc3cb7..22274d1905c5def86ebf3d96aa1eda3d1369c700 100644 (file)
@@ -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);
+  }
 }