mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8293331: Refactor FileDispatcherImpl into operating system-specific components
Reviewed-by: alanb
This commit is contained in:
parent
f751e6087d
commit
48cc15602b
14 changed files with 959 additions and 704 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -25,22 +25,29 @@
|
|||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import java.io.File;
|
||||
import java.nio.CharBuffer;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
class FileDispatcherImpl extends FileDispatcher {
|
||||
private static final int MAP_INVALID = -1;
|
||||
private static final int MAP_RO = 0;
|
||||
private static final int MAP_RW = 1;
|
||||
private static final int MAP_PV = 2;
|
||||
|
||||
private static final long ALLOCATION_GRANULARITY;
|
||||
private static final int MAX_DIRECT_TRANSFER_SIZE;
|
||||
|
||||
// set to true if fast file transmission (TransmitFile) is enabled
|
||||
private static final boolean FAST_FILE_TRANSFER;
|
||||
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
// set to true if fast file transmission (TransmitFile) is enabled
|
||||
private static final boolean fastFileTransfer;
|
||||
|
||||
FileDispatcherImpl() { }
|
||||
|
||||
@Override
|
||||
|
@ -118,7 +125,7 @@ class FileDispatcherImpl extends FileDispatcher {
|
|||
}
|
||||
|
||||
boolean canTransferToDirectly(java.nio.channels.SelectableChannel sc) {
|
||||
return fastFileTransfer && sc.isBlocking();
|
||||
return FAST_FILE_TRANSFER && sc.isBlocking();
|
||||
}
|
||||
|
||||
boolean transferToDirectlyNeedsPositionLock() {
|
||||
|
@ -129,6 +136,36 @@ class FileDispatcherImpl extends FileDispatcher {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
long allocationGranularity() {
|
||||
return ALLOCATION_GRANULARITY;
|
||||
}
|
||||
|
||||
long map(FileDescriptor fd, int prot, long position, long length,
|
||||
boolean isSync)
|
||||
throws IOException
|
||||
{
|
||||
return map0(fd, prot, position, length, isSync);
|
||||
}
|
||||
|
||||
int unmap(long address, long length) {
|
||||
return unmap0(address, length);
|
||||
}
|
||||
|
||||
int maxDirectTransferSize() {
|
||||
return MAX_DIRECT_TRANSFER_SIZE;
|
||||
}
|
||||
|
||||
long transferTo(FileDescriptor src, long position, long count,
|
||||
FileDescriptor dst, boolean append) {
|
||||
return transferTo0(src, position, count, dst, append);
|
||||
}
|
||||
|
||||
long transferFrom(FileDescriptor src, FileDescriptor dst,
|
||||
long position, long count, boolean append) {
|
||||
return IOStatus.UNSUPPORTED;
|
||||
}
|
||||
|
||||
int setDirectIO(FileDescriptor fd, String path) {
|
||||
int result = -1;
|
||||
String filePath = path.substring(0, path.lastIndexOf(File.separator));
|
||||
|
@ -151,7 +188,9 @@ class FileDispatcherImpl extends FileDispatcher {
|
|||
|
||||
static {
|
||||
IOUtil.load();
|
||||
fastFileTransfer = isFastFileTransferRequested();
|
||||
FAST_FILE_TRANSFER = isFastFileTransferRequested();
|
||||
ALLOCATION_GRANULARITY = allocationGranularity0();
|
||||
MAX_DIRECT_TRANSFER_SIZE = maxDirectTransferSize0();
|
||||
}
|
||||
|
||||
//-- Native methods
|
||||
|
@ -194,5 +233,19 @@ class FileDispatcherImpl extends FileDispatcher {
|
|||
|
||||
static native long duplicateHandle(long fd) throws IOException;
|
||||
|
||||
static native long allocationGranularity0();
|
||||
|
||||
static native long map0(FileDescriptor fd, int prot, long position,
|
||||
long length, boolean isSync)
|
||||
throws IOException;
|
||||
|
||||
static native int unmap0(long address, long length);
|
||||
|
||||
static native int maxDirectTransferSize0();
|
||||
|
||||
static native long transferTo0(FileDescriptor src, long position,
|
||||
long count, FileDescriptor dst,
|
||||
boolean append);
|
||||
|
||||
static native int setDirect0(FileDescriptor fd, CharBuffer buffer) throws IOException;
|
||||
}
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
#include <io.h>
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
#include "sun_nio_ch_FileChannelImpl.h"
|
||||
#include "java_lang_Integer.h"
|
||||
|
||||
#include <Mswsock.h>
|
||||
#pragma comment(lib, "Mswsock.lib")
|
||||
|
||||
/**************************************************************
|
||||
* static method to retrieve the allocation granularity
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_allocationGranularity0(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
jint align;
|
||||
GetSystemInfo(&si);
|
||||
align = si.dwAllocationGranularity;
|
||||
return align;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* Channel
|
||||
*/
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, jobject fdo,
|
||||
jint prot, jlong off, jlong len, jboolean map_sync)
|
||||
{
|
||||
void *mapAddress = 0;
|
||||
jint lowOffset = (jint)off;
|
||||
jint highOffset = (jint)(off >> 32);
|
||||
jlong maxSize = off + len;
|
||||
jint lowLen = (jint)(maxSize);
|
||||
jint highLen = (jint)(maxSize >> 32);
|
||||
HANDLE fileHandle = (HANDLE)(handleval(env, fdo));
|
||||
HANDLE mapping;
|
||||
DWORD mapAccess = FILE_MAP_READ;
|
||||
DWORD fileProtect = PAGE_READONLY;
|
||||
DWORD mapError;
|
||||
BOOL result;
|
||||
|
||||
if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) {
|
||||
fileProtect = PAGE_READONLY;
|
||||
mapAccess = FILE_MAP_READ;
|
||||
} else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) {
|
||||
fileProtect = PAGE_READWRITE;
|
||||
mapAccess = FILE_MAP_WRITE;
|
||||
} else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) {
|
||||
fileProtect = PAGE_WRITECOPY;
|
||||
mapAccess = FILE_MAP_COPY;
|
||||
}
|
||||
|
||||
if (map_sync) {
|
||||
JNU_ThrowInternalError(env, "should never call map on platform where MAP_SYNC is unimplemented");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
mapping = CreateFileMapping(
|
||||
fileHandle, /* Handle of file */
|
||||
NULL, /* Not inheritable */
|
||||
fileProtect, /* Read and write */
|
||||
highLen, /* High word of max size */
|
||||
lowLen, /* Low word of max size */
|
||||
NULL); /* No name for object */
|
||||
|
||||
if (mapping == NULL) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
mapAddress = MapViewOfFile(
|
||||
mapping, /* Handle of file mapping object */
|
||||
mapAccess, /* Read and write access */
|
||||
highOffset, /* High word of offset */
|
||||
lowOffset, /* Low word of offset */
|
||||
(SIZE_T)len); /* Number of bytes to map */
|
||||
mapError = GetLastError();
|
||||
|
||||
result = CloseHandle(mapping);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
if (mapAddress == NULL) {
|
||||
if (mapError == ERROR_NOT_ENOUGH_MEMORY)
|
||||
JNU_ThrowOutOfMemoryError(env, "Map failed");
|
||||
else
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
return ptr_to_jlong(mapAddress);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this,
|
||||
jlong address, jlong len)
|
||||
{
|
||||
BOOL result;
|
||||
void *a = (void *) jlong_to_ptr(address);
|
||||
|
||||
result = UnmapViewOfFile(a);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Unmap failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Integer.MAX_VALUE - 1 is the maximum transfer size for TransmitFile()
|
||||
#define MAX_TRANSMIT_SIZE (java_lang_Integer_MAX_VALUE - 1)
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
|
||||
jobject srcFD,
|
||||
jlong position, jlong count,
|
||||
jobject dstFD, jboolean append)
|
||||
{
|
||||
const int PACKET_SIZE = 524288;
|
||||
|
||||
LARGE_INTEGER where;
|
||||
HANDLE src = (HANDLE)(handleval(env, srcFD));
|
||||
SOCKET dst = (SOCKET)(fdval(env, dstFD));
|
||||
DWORD chunkSize = (count > MAX_TRANSMIT_SIZE) ?
|
||||
MAX_TRANSMIT_SIZE : (DWORD)count;
|
||||
BOOL result;
|
||||
|
||||
where.QuadPart = position;
|
||||
result = SetFilePointerEx(src, where, &where, FILE_BEGIN);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
result = TransmitFile(
|
||||
dst,
|
||||
src,
|
||||
chunkSize,
|
||||
PACKET_SIZE,
|
||||
NULL,
|
||||
NULL,
|
||||
TF_USE_KERNEL_APC
|
||||
);
|
||||
if (!result) {
|
||||
int error = WSAGetLastError();
|
||||
if (WSAEINVAL == error && count >= 0) {
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
}
|
||||
if (WSAENOTSOCK == error) {
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
}
|
||||
JNU_ThrowIOExceptionWithLastError(env, "transfer failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
return chunkSize;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_transferFrom0(JNIEnv *env, jobject this,
|
||||
jobject srcFDO, jobject dstFDO,
|
||||
jlong position, jlong count,
|
||||
jboolean append)
|
||||
{
|
||||
return IOS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileChannelImpl_maxDirectTransferSize0(JNIEnv* env, jobject this)
|
||||
{
|
||||
return MAX_TRANSMIT_SIZE;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -28,12 +28,14 @@
|
|||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
#include "sun_nio_ch_FileDispatcherImpl.h"
|
||||
#include <io.h>
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
#include "jlong.h"
|
||||
#include "java_lang_Integer.h"
|
||||
#include "sun_nio_ch_FileDispatcherImpl.h"
|
||||
|
||||
#include <Mswsock.h>
|
||||
#pragma comment(lib, "Mswsock.lib")
|
||||
|
||||
/**************************************************************
|
||||
* FileDispatcherImpl.c
|
||||
|
@ -482,6 +484,165 @@ Java_sun_nio_ch_FileDispatcherImpl_duplicateHandle(JNIEnv *env, jclass this, jlo
|
|||
return ptr_to_jlong(hResult);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
* static method to retrieve the allocation granularity
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_allocationGranularity0(JNIEnv *env, jclass klass)
|
||||
{
|
||||
SYSTEM_INFO si;
|
||||
jint align;
|
||||
GetSystemInfo(&si);
|
||||
align = si.dwAllocationGranularity;
|
||||
return align;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* Channel
|
||||
*/
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_map0(JNIEnv *env, jclass klass, jobject fdo,
|
||||
jint prot, jlong off, jlong len,
|
||||
jboolean map_sync)
|
||||
{
|
||||
void *mapAddress = 0;
|
||||
jint lowOffset = (jint)off;
|
||||
jint highOffset = (jint)(off >> 32);
|
||||
jlong maxSize = off + len;
|
||||
jint lowLen = (jint)(maxSize);
|
||||
jint highLen = (jint)(maxSize >> 32);
|
||||
HANDLE fileHandle = (HANDLE)(handleval(env, fdo));
|
||||
HANDLE mapping;
|
||||
DWORD mapAccess = FILE_MAP_READ;
|
||||
DWORD fileProtect = PAGE_READONLY;
|
||||
DWORD mapError;
|
||||
BOOL result;
|
||||
|
||||
if (prot == sun_nio_ch_FileDispatcherImpl_MAP_RO) {
|
||||
fileProtect = PAGE_READONLY;
|
||||
mapAccess = FILE_MAP_READ;
|
||||
} else if (prot == sun_nio_ch_FileDispatcherImpl_MAP_RW) {
|
||||
fileProtect = PAGE_READWRITE;
|
||||
mapAccess = FILE_MAP_WRITE;
|
||||
} else if (prot == sun_nio_ch_FileDispatcherImpl_MAP_PV) {
|
||||
fileProtect = PAGE_WRITECOPY;
|
||||
mapAccess = FILE_MAP_COPY;
|
||||
}
|
||||
|
||||
if (map_sync) {
|
||||
JNU_ThrowInternalError(env, "should never call map on platform where MAP_SYNC is unimplemented");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
mapping = CreateFileMapping(
|
||||
fileHandle, /* Handle of file */
|
||||
NULL, /* Not inheritable */
|
||||
fileProtect, /* Read and write */
|
||||
highLen, /* High word of max size */
|
||||
lowLen, /* Low word of max size */
|
||||
NULL); /* No name for object */
|
||||
|
||||
if (mapping == NULL) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
mapAddress = MapViewOfFile(
|
||||
mapping, /* Handle of file mapping object */
|
||||
mapAccess, /* Read and write access */
|
||||
highOffset, /* High word of offset */
|
||||
lowOffset, /* Low word of offset */
|
||||
(SIZE_T)len); /* Number of bytes to map */
|
||||
mapError = GetLastError();
|
||||
|
||||
result = CloseHandle(mapping);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
if (mapAddress == NULL) {
|
||||
if (mapError == ERROR_NOT_ENOUGH_MEMORY)
|
||||
JNU_ThrowOutOfMemoryError(env, "Map failed");
|
||||
else
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Map failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
return ptr_to_jlong(mapAddress);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_unmap0(JNIEnv *env, jclass klass,
|
||||
jlong address, jlong len)
|
||||
{
|
||||
BOOL result;
|
||||
void *a = (void *) jlong_to_ptr(address);
|
||||
|
||||
result = UnmapViewOfFile(a);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Unmap failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Integer.MAX_VALUE - 1 is the maximum transfer size for TransmitFile()
|
||||
#define MAX_TRANSMIT_SIZE (java_lang_Integer_MAX_VALUE - 1)
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_maxDirectTransferSize0(JNIEnv* env, jclass klass)
|
||||
{
|
||||
return MAX_TRANSMIT_SIZE;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_transferTo0(JNIEnv *env, jclass klass,
|
||||
jobject srcFD,
|
||||
jlong position, jlong count,
|
||||
jobject dstFD, jboolean append)
|
||||
{
|
||||
const int PACKET_SIZE = 524288;
|
||||
|
||||
LARGE_INTEGER where;
|
||||
HANDLE src = (HANDLE)(handleval(env, srcFD));
|
||||
SOCKET dst = (SOCKET)(fdval(env, dstFD));
|
||||
DWORD chunkSize = (count > MAX_TRANSMIT_SIZE) ?
|
||||
MAX_TRANSMIT_SIZE : (DWORD)count;
|
||||
BOOL result;
|
||||
|
||||
where.QuadPart = position;
|
||||
result = SetFilePointerEx(src, where, &where, FILE_BEGIN);
|
||||
if (result == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
result = TransmitFile(
|
||||
dst,
|
||||
src,
|
||||
chunkSize,
|
||||
PACKET_SIZE,
|
||||
NULL,
|
||||
NULL,
|
||||
TF_USE_KERNEL_APC
|
||||
);
|
||||
if (!result) {
|
||||
int error = WSAGetLastError();
|
||||
if (WSAEINVAL == error && count >= 0) {
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
}
|
||||
if (WSAENOTSOCK == error) {
|
||||
return IOS_UNSUPPORTED_CASE;
|
||||
}
|
||||
JNU_ThrowIOExceptionWithLastError(env, "transfer failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
return chunkSize;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_setDirect0(JNIEnv *env, jclass this,
|
||||
jobject fdObj, jobject buffer)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue