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 \
--- /dev/null
+/*
+ * 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;
+ }
+}
}
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);
}
#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"
/* 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.
{
jclass cephstat_cls;
jclass cephstatvfs_cls;
+ jclass tmp_cephfileextent_cls;
/*
* Get a fieldID from a class with a specific type
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");
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;
+}
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);
+ }
}