< prev index next >

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

Print this page

        

*** 32,41 **** --- 32,43 ---- #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,66 **** #define fdatasync fsync #endif static int preCloseFD = -1; /* File descriptor to which we dup other fd's before closing them for real */ ! JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl) { int sp[2]; --- 58,68 ---- #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,77 **** --- 70,148 ---- 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,108 **** --- 152,292 ---- 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,137 **** --- 294,416 ---- 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 >