< prev index next >

src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c

Print this page

        

@@ -32,10 +32,12 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <fcntl.h>
 #include <sys/uio.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
 #if defined(__linux__)
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #endif
 #include "nio.h"

@@ -56,11 +58,11 @@
 #define fdatasync fsync
 #endif
 
 static int preCloseFD = -1;     /* File descriptor to which we dup other fd's
                                    before closing them for real */
-
+static int pageSize = -1;
 
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)
 {
     int sp[2];

@@ -68,10 +70,79 @@
         JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
         return;
     }
     preCloseFD = sp[0];
     close(sp[1]);
+    
+    pageSize = getpagesize();
+}
+
+jint readDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize)
+{
+    int gap = 0;
+    int newLen = -1;
+    long newStartLocation = -1;
+    void *bytes = NULL;
+    int nread = -1;
+
+    newStartLocation = offset;
+    if ((newStartLocation % pageSize) != 0) {
+        newStartLocation = offset / pageSize * pageSize;
+        gap = offset - newStartLocation;
+    }
+
+    lseek(fd, newStartLocation, SEEK_SET);
+
+    newLen = len;
+    if ((newLen % pageSize) != 0) {
+        newLen = (len / pageSize + 1) * pageSize;
+    }
+
+    if ((newLen - gap) < len) {
+        newLen = newLen + pageSize;
+    }
+
+    posix_memalign(&bytes, pageSize, newLen);
+
+    nread = read(fd, bytes, newLen);
+
+    if (nread > gap) {
+        if ((nread - gap) >= len) {
+            memcpy(buf, bytes+gap, len);
+            nread = len;
+        } else {
+            memcpy(buf, bytes+gap, (nread-gap));
+            nread = nread - gap;
+        }
+    } else if (nread == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "Read error");
+    } else { /*EOF*/
+        nread = 0;
+    }
+
+    free(bytes);
+  
+    return nread;
+}
+
+jint writeDirect(JNIEnv *env, jclass clazz, jint fd, jlong offset, jint len, void *buf, jint pageSize)
+{
+    void *bytes = NULL;
+    int nwrite = -1;
+    posix_memalign(&bytes, pageSize, len);
+    memcpy(bytes, buf, len);
+
+    lseek(fd, offset, SEEK_SET);
+
+    nwrite = write(fd, bytes, len);
+    if (nwrite == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "Write error");
+    }
+
+    free(bytes);
+
+    return nwrite;
 }
 
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz,
                              jobject fdo, jlong address, jint len)

@@ -81,28 +152,141 @@
 
     return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_readDirect0(JNIEnv *env, jclass clazz,
+                             jobject fdo, jlong address, jint len)
+{
+    jint fd = fdval(env, fdo);
+    void *buf = (void *)jlong_to_ptr(address);
+    long currentLocation = lseek(fd, 0, SEEK_CUR);
+
+    if (currentLocation % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) {
+        return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
+    }
+
+    int nread = readDirect(env, clazz, fd, currentLocation, len, buf, pageSize);
+    lseek(fd, (currentLocation + nread), SEEK_SET);
+    return convertReturnVal(env, nread, JNI_TRUE);
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo,
                             jlong address, jint len, jlong offset)
 {
     jint fd = fdval(env, fdo);
     void *buf = (void *)jlong_to_ptr(address);
 
     return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_preadDirect0(JNIEnv *env, jclass clazz, jobject fdo,
+                            jlong address, jint len, jlong offset)
+{
+    jint fd = fdval(env, fdo);
+    void *buf = (void *)jlong_to_ptr(address);
+
+    long currentLocation = lseek(fd, 0, SEEK_CUR);
+
+    if (offset % pageSize == 0 && len % pageSize == 0 && address % pageSize == 0) {
+        return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
+    }
+
+    int nread = readDirect(env, clazz, fd, offset, len, buf, pageSize);
+    lseek(fd, currentLocation, SEEK_SET);
+    return convertReturnVal(env, nread, JNI_TRUE);
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz,
                               jobject fdo, jlong address, jint len)
 {
     jint fd = fdval(env, fdo);
     struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+
     return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE);
 }
 
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_readvDirect0(JNIEnv *env, jclass clazz,
+                              jobject fdo, jlong address, jint len)
+{
+    int i;
+    int totalLen = 0;
+    int newLen = 0;
+    int gap = 0;
+    int nread = 0;
+    int result = 0;
+    void *bytes = NULL;
+    long currentLocation = -1;
+    long newStartLocation = -1;
+
+    jint fd = fdval(env, fdo);
+    struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+
+    currentLocation = lseek(fd, 0, SEEK_CUR);
+    newStartLocation = currentLocation;
+    if ((newStartLocation % pageSize) != 0) {
+        newStartLocation = currentLocation / pageSize * pageSize;
+        gap = currentLocation - newStartLocation;
+    }
+
+    lseek(fd, newStartLocation, SEEK_SET);
+
+    for (i = 0; i < len; i++) {
+        totalLen += iov[i].iov_len;
+    }
+
+    newLen = totalLen;
+    if ((newLen % pageSize) != 0) {
+        newLen = (totalLen / pageSize + 1) * pageSize;
+    }
+
+    if ((newLen - gap) < totalLen) {
+        newLen += pageSize;
+    }
+
+    posix_memalign(&bytes, pageSize, newLen);
+    nread = read(fd, bytes, newLen);
+
+    if (nread > gap) {
+        if ((nread - gap) >= totalLen) {
+            nread = totalLen;
+        } else {
+            nread -=  gap;
+        }
+    } else if (nread == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "Read error");
+    } else { /*EOF*/
+        nread = 0;
+    }
+
+    i = 0;
+    int tempLen;
+    while (nread > 0) {
+        tempLen = iov[i].iov_len;
+        if (nread >= tempLen) {
+            memcpy(iov[i].iov_base, (bytes + gap + result), tempLen);
+            result += tempLen;
+            nread -= tempLen;
+        } else {
+            memcpy(iov[i].iov_base, (bytes + gap + result), nread);
+            result += nread;
+            nread = 0;
+        }
+        i++;
+    }
+
+    free(bytes);
+
+    lseek(fd, (currentLocation + result), SEEK_SET);
+
+    return convertLongReturnVal(env, result, JNI_TRUE);
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz,
                               jobject fdo, jlong address, jint len)
 {
     jint fd = fdval(env, fdo);

@@ -110,28 +294,123 @@
 
     return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_writeDirect0(JNIEnv *env, jclass clazz,
+                              jobject fdo, jlong address, jint len)
+{
+    jint fd = fdval(env, fdo);
+    void *buf = (void *)jlong_to_ptr(address);
+
+    long currentLocation = lseek(fd, 0, SEEK_CUR);
+
+    if ((len % pageSize != 0) || (currentLocation % pageSize != 0)) {
+        JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
+            "In DirectIO mode, the IO size and currentLocation must be aligned with kernel page size");
+    }
+
+    if (address % pageSize == 0) {
+        return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
+    }
+
+    int nwrite = writeDirect(env, clazz, fd, currentLocation, len, buf, pageSize);
+
+    lseek(fd, (currentLocation + nwrite), SEEK_SET);
+
+    return convertReturnVal(env, nwrite, JNI_FALSE);
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo,
                             jlong address, jint len, jlong offset)
 {
     jint fd = fdval(env, fdo);
     void *buf = (void *)jlong_to_ptr(address);
 
     return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_pwriteDirect0(JNIEnv *env, jclass clazz, jobject fdo,
+                            jlong address, jint len, jlong offset)
+{
+    jint fd = fdval(env, fdo);
+    void *buf = (void *)jlong_to_ptr(address);
+
+    if ((len % pageSize != 0) || (offset % pageSize != 0)) {
+        JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
+            "In DirectIO mode, the IO size and offset must be aligned with kernel page size");
+    }
+
+    if (address % pageSize == 0) {
+        return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
+    }
+
+    long currentLocation = lseek(fd, 0, SEEK_CUR);
+
+    int nwrite = writeDirect(env, clazz, fd, offset, len, buf, pageSize);
+
+    lseek(fd, currentLocation, SEEK_SET);
+
+    return convertReturnVal(env, nwrite, JNI_FALSE);
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz,
                                        jobject fdo, jlong address, jint len)
 {
     jint fd = fdval(env, fdo);
     struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+
     return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE);
 }
 
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_writevDirect0(JNIEnv *env, jclass clazz,
+                                       jobject fdo, jlong address, jint len)
+{
+    int i;
+    int totalLen = 0;
+    int currentLocation = -1;
+    int nwrite = 0;
+    int result = 0;
+    void *bytes = NULL;
+
+    jint fd = fdval(env, fdo);
+    struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+
+    for (i = 0; i < len; i++) {
+        totalLen += iov[i].iov_len;
+    }
+
+    currentLocation = lseek(fd, 0, SEEK_CUR);
+
+    if ((totalLen % pageSize != 0) || (currentLocation % pageSize != 0)) {
+        JNU_ThrowByNameWithMessageAndLastError(env, "java/io/IOException",
+            "In DirectIO mode, the IO size and offset must be aligned with kernel page size");
+    }
+
+    posix_memalign(&bytes, pageSize, totalLen);
+
+    int tempLen;
+    for (i = 0; i < len; i++) {
+        tempLen = iov[i].iov_len;
+        memcpy((bytes + result), iov[i].iov_base, tempLen);
+        result += tempLen;
+    }
+    nwrite = write(fd, bytes, totalLen);
+    if (nwrite == -1) {
+        JNU_ThrowIOExceptionWithLastError(env, "Write error");
+    }
+
+    free(bytes);
+
+    return convertLongReturnVal(env, nwrite, JNI_FALSE);
+
+}
+
 static jlong
 handle(JNIEnv *env, jlong rv, char *msg)
 {
     if (rv >= 0)
         return rv;
< prev index next >