提交 98588034 编写于 作者: A alanb

8064407: (fc) FileChannel transferTo should use TransmitFile on Windows

Reviewed-by: alanb
Contributed-by: kirk.shoop@microsoft.com, v-valkop@microsoft.com
上级 4ad2063f
...@@ -38,6 +38,7 @@ import java.nio.channels.NonReadableChannelException; ...@@ -38,6 +38,7 @@ import java.nio.channels.NonReadableChannelException;
import java.nio.channels.NonWritableChannelException; import java.nio.channels.NonWritableChannelException;
import java.nio.channels.OverlappingFileLockException; import java.nio.channels.OverlappingFileLockException;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel; import java.nio.channels.WritableByteChannel;
import java.security.AccessController; import java.security.AccessController;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -407,30 +408,13 @@ public class FileChannelImpl ...@@ -407,30 +408,13 @@ public class FileChannelImpl
// //
private static volatile boolean fileSupported = true; private static volatile boolean fileSupported = true;
private long transferToDirectly(long position, int icount, private long transferToDirectlyInternal(long position, int icount,
WritableByteChannel target) WritableByteChannel target,
FileDescriptor targetFD)
throws IOException throws IOException
{ {
if (!transferSupported) assert !nd.transferToDirectlyNeedsPositionLock() ||
return IOStatus.UNSUPPORTED; Thread.holdsLock(positionLock);
FileDescriptor targetFD = null;
if (target instanceof FileChannelImpl) {
if (!fileSupported)
return IOStatus.UNSUPPORTED_CASE;
targetFD = ((FileChannelImpl)target).fd;
} else if (target instanceof SelChImpl) {
// Direct transfer to pipe causes EINVAL on some configurations
if ((target instanceof SinkChannelImpl) && !pipeSupported)
return IOStatus.UNSUPPORTED_CASE;
targetFD = ((SelChImpl)target).getFD();
}
if (targetFD == null)
return IOStatus.UNSUPPORTED;
int thisFDVal = IOUtil.fdVal(fd);
int targetFDVal = IOUtil.fdVal(targetFD);
if (thisFDVal == targetFDVal) // Not supported on some configurations
return IOStatus.UNSUPPORTED;
long n = -1; long n = -1;
int ti = -1; int ti = -1;
...@@ -440,7 +424,7 @@ public class FileChannelImpl ...@@ -440,7 +424,7 @@ public class FileChannelImpl
if (!isOpen()) if (!isOpen())
return -1; return -1;
do { do {
n = transferTo0(thisFDVal, position, icount, targetFDVal); n = transferTo0(fd, position, icount, targetFD);
} while ((n == IOStatus.INTERRUPTED) && isOpen()); } while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n == IOStatus.UNSUPPORTED_CASE) { if (n == IOStatus.UNSUPPORTED_CASE) {
if (target instanceof SinkChannelImpl) if (target instanceof SinkChannelImpl)
...@@ -461,6 +445,54 @@ public class FileChannelImpl ...@@ -461,6 +445,54 @@ public class FileChannelImpl
} }
} }
private long transferToDirectly(long position, int icount,
WritableByteChannel target)
throws IOException
{
if (!transferSupported)
return IOStatus.UNSUPPORTED;
FileDescriptor targetFD = null;
if (target instanceof FileChannelImpl) {
if (!fileSupported)
return IOStatus.UNSUPPORTED_CASE;
targetFD = ((FileChannelImpl)target).fd;
} else if (target instanceof SelChImpl) {
// Direct transfer to pipe causes EINVAL on some configurations
if ((target instanceof SinkChannelImpl) && !pipeSupported)
return IOStatus.UNSUPPORTED_CASE;
// Platform-specific restrictions. Now there is only one:
// Direct transfer to non-blocking channel could be forbidden
SelectableChannel sc = (SelectableChannel)target;
if (!nd.canTransferToDirectly(sc))
return IOStatus.UNSUPPORTED_CASE;
targetFD = ((SelChImpl)target).getFD();
}
if (targetFD == null)
return IOStatus.UNSUPPORTED;
int thisFDVal = IOUtil.fdVal(fd);
int targetFDVal = IOUtil.fdVal(targetFD);
if (thisFDVal == targetFDVal) // Not supported on some configurations
return IOStatus.UNSUPPORTED;
if (nd.transferToDirectlyNeedsPositionLock()) {
synchronized (positionLock) {
long pos = position();
try {
return transferToDirectlyInternal(position, icount,
target, targetFD);
} finally {
position(pos);
}
}
} else {
return transferToDirectlyInternal(position, icount, target, targetFD);
}
}
// Maximum size to map when using a mapped buffer // Maximum size to map when using a mapped buffer
private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L; private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;
...@@ -1176,7 +1208,8 @@ public class FileChannelImpl ...@@ -1176,7 +1208,8 @@ public class FileChannelImpl
private static native int unmap0(long address, long length); private static native int unmap0(long address, long length);
// Transfers from src to dst, or returns -2 if kernel can't do that // Transfers from src to dst, or returns -2 if kernel can't do that
private native long transferTo0(int src, long position, long count, int dst); private native long transferTo0(FileDescriptor src, long position,
long count, FileDescriptor dst);
// Sets or reports this file's position // Sets or reports this file's position
// If offset is -1, the current position is returned // If offset is -1, the current position is returned
......
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.channels.SelectableChannel;
abstract class FileDispatcher extends NativeDispatcher { abstract class FileDispatcher extends NativeDispatcher {
...@@ -53,4 +55,8 @@ abstract class FileDispatcher extends NativeDispatcher { ...@@ -53,4 +55,8 @@ abstract class FileDispatcher extends NativeDispatcher {
*/ */
abstract FileDescriptor duplicateForMapping(FileDescriptor fd) abstract FileDescriptor duplicateForMapping(FileDescriptor fd)
throws IOException; throws IOException;
abstract boolean canTransferToDirectly(SelectableChannel sc);
abstract boolean transferToDirectlyNeedsPositionLock();
} }
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.FileDescriptor;
import java.io.IOException;
class FileDispatcherImpl extends FileDispatcher class FileDispatcherImpl extends FileDispatcher {
{
static { static {
IOUtil.load(); IOUtil.load();
...@@ -108,6 +108,14 @@ class FileDispatcherImpl extends FileDispatcher ...@@ -108,6 +108,14 @@ class FileDispatcherImpl extends FileDispatcher
return new FileDescriptor(); return new FileDescriptor();
} }
boolean canTransferToDirectly(java.nio.channels.SelectableChannel sc) {
return true;
}
boolean transferToDirectlyNeedsPositionLock() {
return false;
}
// -- Native methods -- // -- Native methods --
static native int read0(FileDescriptor fd, long address, int len) static native int read0(FileDescriptor fd, long address, int len)
......
...@@ -154,10 +154,13 @@ Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) ...@@ -154,10 +154,13 @@ Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
jint srcFD, jobject srcFDO,
jlong position, jlong count, jlong position, jlong count,
jint dstFD) jobject dstFDO)
{ {
jint srcFD = fdval(env, srcFDO);
jint dstFD = fdval(env, dstFDO);
#if defined(__linux__) #if defined(__linux__)
off64_t offset = (off64_t)position; off64_t offset = (off64_t)position;
jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count); jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count);
......
...@@ -25,15 +25,16 @@ ...@@ -25,15 +25,16 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.FileDescriptor;
import java.io.IOException;
import java.security.PrivilegedAction;
import sun.misc.SharedSecrets; import sun.misc.SharedSecrets;
import sun.misc.JavaIOFileDescriptorAccess; import sun.misc.JavaIOFileDescriptorAccess;
class FileDispatcherImpl extends FileDispatcher class FileDispatcherImpl extends FileDispatcher {
{
static { // set to true if fast file transmission (TransmitFile) is enabled
IOUtil.load(); private static final boolean fastFileTransfer;
}
/** /**
* Indicates if the dispatcher should first advance the file position * Indicates if the dispatcher should first advance the file position
...@@ -120,6 +121,36 @@ class FileDispatcherImpl extends FileDispatcher ...@@ -120,6 +121,36 @@ class FileDispatcherImpl extends FileDispatcher
return result; return result;
} }
boolean canTransferToDirectly(java.nio.channels.SelectableChannel sc) {
return fastFileTransfer && sc.isBlocking();
}
boolean transferToDirectlyNeedsPositionLock() {
return true;
}
static boolean isFastFileTransferRequested() {
String fileTransferProp = java.security.AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("jdk.net.enableFastFileTransfer");
}
});
boolean enable;
if ("".equals(fileTransferProp)) {
enable = true;
} else {
enable = Boolean.parseBoolean(fileTransferProp);
}
return enable;
}
static {
IOUtil.load();
fastFileTransfer = isFastFileTransferRequested();
}
//-- Native methods //-- Native methods
static native int read0(FileDescriptor fd, long address, int len) static native int read0(FileDescriptor fd, long address, int len)
......
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include "nio.h" #include "nio.h"
#include "nio_util.h" #include "nio_util.h"
#include "sun_nio_ch_FileChannelImpl.h" #include "sun_nio_ch_FileChannelImpl.h"
#include "java_lang_Integer.h"
#include <Mswsock.h>
#pragma comment(lib, "Mswsock.lib")
static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */ static jfieldID chan_fd; /* id for jobject 'fd' in java.io.FileChannel */
...@@ -174,9 +178,42 @@ Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo) ...@@ -174,9 +178,42 @@ Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
jint srcFD, jobject srcFD,
jlong position, jlong count, jlong position, jlong count,
jint dstFD) jobject dstFD)
{ {
return IOS_UNSUPPORTED; const int PACKET_SIZE = 524288;
HANDLE src = (HANDLE)(handleval(env, srcFD));
SOCKET dst = (SOCKET)(fdval(env, dstFD));
DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ?
java_lang_Integer_MAX_VALUE : (DWORD)count;
BOOL result = 0;
jlong pos = Java_sun_nio_ch_FileChannelImpl_position0(env, this, srcFD, position);
if (pos == IOS_THROWN) {
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;
} }
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
/* @test /* @test
* @bug 4652496 * @bug 4652496
* @summary Test transferTo with different target channels * @summary Test transferTo with different target channels
* @run main TransferToChannel
* @run main/othervm -Djdk.net.enableFastFileTransfer TransferToChannel
*/ */
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册