< 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 >