--- old/make/mapfiles/libnio/mapfile-linux 2016-11-16 10:28:17.515497893 -0800
+++ new/make/mapfiles/libnio/mapfile-linux 2016-11-16 10:28:17.459497893 -0800
@@ -60,6 +60,7 @@
Java_sun_nio_ch_FileChannelImpl_position0;
Java_sun_nio_ch_FileChannelImpl_transferTo0;
Java_sun_nio_ch_FileChannelImpl_unmap0;
+ Java_sun_nio_ch_FileChannelImpl_setDirect0;
Java_sun_nio_ch_FileDispatcherImpl_close0;
Java_sun_nio_ch_FileDispatcherImpl_closeIntFD;
Java_sun_nio_ch_FileDispatcherImpl_force0;
--- old/src/java.base/share/classes/java/nio/channels/FileChannel.java 2016-11-16 10:28:17.792497896 -0800
+++ new/src/java.base/share/classes/java/nio/channels/FileChannel.java 2016-11-16 10:28:17.733497895 -0800
@@ -287,6 +287,7 @@
return provider.newFileChannel(path, options, attrs);
}
+
@SuppressWarnings({"unchecked", "rawtypes"}) // generic array construction
private static final FileAttribute>[] NO_ATTRIBUTES = new FileAttribute[0];
--- old/src/java.base/share/classes/java/nio/file/FileStore.java 2016-11-16 10:28:17.991497898 -0800
+++ new/src/java.base/share/classes/java/nio/file/FileStore.java 2016-11-16 10:28:17.934497897 -0800
@@ -112,6 +112,17 @@
public abstract long getUsableSpace() throws IOException;
/**
+ * Returns block size in Bytes to this Java virtual machine on the file
+ * store.
+ *
+ * @return block size
+ *
+ * @throws IOException
+ * if an I/O error occurs
+ */
+ public abstract int getBlockSize() throws IOException;
+
+ /**
* Returns the number of unallocated bytes in the file store.
*
*
The returned number of unallocated bytes is a hint, but not a
--- old/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java 2016-11-16 10:28:18.210497900 -0800
+++ new/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileStore.java 2016-11-16 10:28:18.154497899 -0800
@@ -82,6 +82,11 @@
}
@Override
+ public int getBlockSize() throws IOException {
+ throw new UnsupportedOperationException("getBlockSize");
+ }
+
+ @Override
public long getUsableSpace() throws IOException {
throw new UnsupportedOperationException("getUsableSpace");
}
--- old/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java 2016-11-16 10:28:18.418497902 -0800
+++ new/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java 2016-11-16 10:28:18.362497901 -0800
@@ -49,6 +49,12 @@
import jdk.internal.ref.Cleaner;
import sun.security.action.GetPropertyAction;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.FileSystemException;
+
public class FileChannelImpl
extends FileChannel
{
@@ -85,24 +91,55 @@
// Positional-read is not interruptible
private volatile boolean uninterruptible;
+ //directIO
+ private volatile boolean direct;
+
+ //IO alignment for DirectIO
+ private volatile int alignment = -1;
+
private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
- boolean writable, Object parent)
+ boolean writable, boolean direct, Object parent)
{
this.fd = fd;
this.readable = readable;
this.writable = writable;
this.parent = parent;
this.path = path;
+ this.direct = direct;
+ if (direct)
+ setDirectIO();
this.nd = new FileDispatcherImpl();
}
+ private void setDirectIO()
+ {
+ if (alignment == -1) {
+ Path fp = Paths.get(path);
+ try {
+ setDirect0(fd);
+ FileStore fs = Files.getFileStore(fp);
+ this.alignment = fs.getBlockSize();
+ } catch (IOException e) {
+ this.alignment = -1;
+ throw new UnsupportedOperationException("Error setting up DirectIO");
+ }
+ }
+ }
+
// Used by FileInputStream.getChannel(), FileOutputStream.getChannel
// and RandomAccessFile.getChannel()
public static FileChannel open(FileDescriptor fd, String path,
boolean readable, boolean writable,
Object parent)
{
- return new FileChannelImpl(fd, path, readable, writable, parent);
+ return new FileChannelImpl(fd, path, readable, writable, false, parent);
+ }
+
+ public static FileChannel open(FileDescriptor fd, String path,
+ boolean readable, boolean writable,
+ boolean direct, Object parent)
+ {
+ return new FileChannelImpl(fd, path, readable, writable, direct, parent);
}
private void ensureOpen() throws IOException {
@@ -150,6 +187,9 @@
}
public int read(ByteBuffer dst) throws IOException {
+ if (direct && ((dst.remaining() % alignment != 0) ||
+ (position() % alignment != 0)))
+ throw new IllegalArgumentException("IO size or position is not aligned");
ensureOpen();
if (!readable)
throw new NonReadableChannelException();
@@ -162,7 +202,7 @@
if (!isOpen())
return 0;
do {
- n = IOUtil.read(fd, dst, -1, nd);
+ n = IOUtil.read(fd, dst, -1, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -178,6 +218,10 @@
{
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
+
+ if (direct && (position() % alignment != 0))
+ throw new IllegalArgumentException("Position is not aligned");
+
ensureOpen();
if (!readable)
throw new NonReadableChannelException();
@@ -190,7 +234,7 @@
if (!isOpen())
return 0;
do {
- n = IOUtil.read(fd, dsts, offset, length, nd);
+ n = IOUtil.read(fd, dsts, offset, length, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -202,9 +246,13 @@
}
public int write(ByteBuffer src) throws IOException {
+
ensureOpen();
if (!writable)
throw new NonWritableChannelException();
+ if (direct && ((src.remaining() % alignment != 0) ||
+ (position() % alignment != 0)))
+ throw new IllegalArgumentException("IO size or position is not aligned");
synchronized (positionLock) {
int n = 0;
int ti = -1;
@@ -214,7 +262,7 @@
if (!isOpen())
return 0;
do {
- n = IOUtil.write(fd, src, -1, nd);
+ n = IOUtil.write(fd, src, -1, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -233,6 +281,10 @@
ensureOpen();
if (!writable)
throw new NonWritableChannelException();
+
+ if (direct && (position() % alignment != 0))
+ throw new IllegalArgumentException("Position is not aligned");
+
synchronized (positionLock) {
long n = 0;
int ti = -1;
@@ -242,7 +294,7 @@
if (!isOpen())
return 0;
do {
- n = IOUtil.write(fd, srcs, offset, length, nd);
+ n = IOUtil.write(fd, srcs, offset, length, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -725,6 +777,10 @@
throw new IllegalArgumentException("Negative position");
if (!readable)
throw new NonReadableChannelException();
+ if (direct && ((dst.remaining() % alignment != 0) ||
+ (position % alignment != 0)))
+ throw new IllegalArgumentException("IO size or position is not aligned");
+
ensureOpen();
if (nd.needsPositionLock()) {
synchronized (positionLock) {
@@ -747,7 +803,7 @@
if (!isOpen())
return -1;
do {
- n = IOUtil.read(fd, dst, position, nd);
+ n = IOUtil.read(fd, dst, position, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -764,6 +820,10 @@
throw new IllegalArgumentException("Negative position");
if (!writable)
throw new NonWritableChannelException();
+ if (direct && ((src.remaining() % alignment != 0) ||
+ (position % alignment != 0)))
+ throw new IllegalArgumentException("IO size or position is not aligned");
+
ensureOpen();
if (nd.needsPositionLock()) {
synchronized (positionLock) {
@@ -784,7 +844,7 @@
if (!isOpen())
return -1;
do {
- n = IOUtil.write(fd, src, position, nd);
+ n = IOUtil.write(fd, src, position, direct, alignment, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -1228,6 +1288,8 @@
// Caches fieldIDs
private static native long initIDs();
+ private native int setDirect0(FileDescriptor fd) throws IOException;
+
static {
IOUtil.load();
allocationGranularity = initIDs();
--- old/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2016-11-16 10:28:18.626497904 -0800
+++ new/src/java.base/share/classes/sun/nio/ch/IOUtil.java 2016-11-16 10:28:18.569497903 -0800
@@ -47,22 +47,37 @@
NativeDispatcher nd)
throws IOException
{
- if (src instanceof DirectBuffer)
- return writeFromNativeBuffer(fd, src, position, nd);
+ return write(fd, src, position, false, -1, nd);
+ }
+
+ static int write(FileDescriptor fd, ByteBuffer src, long position,
+ boolean directIO, int alignment, NativeDispatcher nd)
+ throws IOException
+ {
+ if (src instanceof DirectBuffer) {
+ return writeFromNativeBuffer(fd, src, position, directIO, alignment, nd);
+ }
// Substitute a native buffer
int pos = src.position();
int lim = src.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
- ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
+ ByteBuffer bb;
+ if (directIO) {
+ if (rem % alignment != 0)
+ throw new IllegalArgumentException("DirectByteBuffer is not properly aligned");
+ bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
+ } else {
+ bb = Util.getTemporaryDirectBuffer(rem);
+ }
try {
bb.put(src);
bb.flip();
// Do not update src until we see how many bytes were written
src.position(pos);
- int n = writeFromNativeBuffer(fd, bb, position, nd);
+ int n = writeFromNativeBuffer(fd, bb, position, directIO, alignment, nd);
if (n > 0) {
// now update src
src.position(pos + n);
@@ -73,8 +88,8 @@
}
}
- private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
- long position, NativeDispatcher nd)
+ private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, long position,
+ boolean directIO, int alignment, NativeDispatcher nd)
throws IOException
{
int pos = bb.position();
@@ -82,6 +97,10 @@
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
+ if (directIO && (bb.alignmentOffset(pos, alignment) != 0) && (rem % alignment != 0)) {
+ throw new IllegalArgumentException("DirectByteBuffer is not properly aligned");
+ }
+
int written = 0;
if (rem == 0)
return 0;
@@ -100,13 +119,20 @@
static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
throws IOException
{
- return write(fd, bufs, 0, bufs.length, nd);
+ return write(fd, bufs, 0, bufs.length, false, -1, nd);
}
static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
NativeDispatcher nd)
throws IOException
{
+ return write(fd, bufs, offset, length, false, -1, nd);
+ }
+
+ static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
+ boolean directIO, int alignment, NativeDispatcher nd)
+ throws IOException
+ {
IOVecWrapper vec = IOVecWrapper.get(length);
boolean completed = false;
@@ -122,12 +148,19 @@
int lim = buf.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
+ if (directIO && (rem % alignment != 0))
+ throw new IllegalArgumentException("IO size or position is not aligned");
+
if (rem > 0) {
vec.setBuffer(iov_len, buf, pos, rem);
// allocate shadow buffer to ensure I/O is done with direct buffer
if (!(buf instanceof DirectBuffer)) {
- ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
+ ByteBuffer shadow;
+ if (directIO)
+ shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
+ else
+ shadow = Util.getTemporaryDirectBuffer(rem);
shadow.put(buf);
shadow.flip();
vec.setShadow(iov_len, shadow);
@@ -186,15 +219,29 @@
NativeDispatcher nd)
throws IOException
{
+ return read(fd, dst, position, false, -1, nd);
+ }
+
+ static int read(FileDescriptor fd, ByteBuffer dst, long position,
+ boolean directIO, int alignment, NativeDispatcher nd)
+ throws IOException
+ {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (dst instanceof DirectBuffer)
- return readIntoNativeBuffer(fd, dst, position, nd);
+ return readIntoNativeBuffer(fd, dst, position, directIO, alignment, nd);
// Substitute a native buffer
- ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
+ ByteBuffer bb;
+ if (directIO) {
+ if (dst.remaining() % alignment != 0)
+ throw new IllegalArgumentException("DirectByteBuffer is not properly aligned");
+ bb = Util.getTemporaryAlignedDirectBuffer(dst.remaining(), alignment);
+ } else {
+ bb = Util.getTemporaryDirectBuffer(dst.remaining());
+ }
try {
- int n = readIntoNativeBuffer(fd, bb, position, nd);
+ int n = readIntoNativeBuffer(fd, bb, position, directIO, alignment,nd);
bb.flip();
if (n > 0)
dst.put(bb);
@@ -204,14 +251,17 @@
}
}
- private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
- long position, NativeDispatcher nd)
+ private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, long position,
+ boolean directIO, int alignment, NativeDispatcher nd)
throws IOException
{
int pos = bb.position();
int lim = bb.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
+
+ if(directIO && !(bb.alignmentOffset(pos, alignment) != 0) && (rem % alignment != 0))
+ throw new IllegalArgumentException("DirectByteBuffer is not properly aligned");
if (rem == 0)
return 0;
@@ -230,13 +280,20 @@
static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
throws IOException
{
- return read(fd, bufs, 0, bufs.length, nd);
+ return read(fd, bufs, 0, bufs.length, false, -1, nd);
}
static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
NativeDispatcher nd)
throws IOException
{
+ return read(fd, bufs, offset, bufs.length, false, -1, nd);
+ }
+
+ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
+ boolean directIO, int alignment, NativeDispatcher nd)
+ throws IOException
+ {
IOVecWrapper vec = IOVecWrapper.get(length);
boolean completed = false;
@@ -255,12 +312,20 @@
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
+ if (directIO && (rem % alignment != 0))
+ throw new IllegalArgumentException("IO size or position is not aligned");
+
if (rem > 0) {
vec.setBuffer(iov_len, buf, pos, rem);
// allocate shadow buffer to ensure I/O is done with direct buffer
if (!(buf instanceof DirectBuffer)) {
- ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
+ ByteBuffer shadow;
+ if (directIO) {
+ shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
+ } else {
+ shadow = Util.getTemporaryDirectBuffer(rem);
+ }
vec.setShadow(iov_len, shadow);
buf = shadow;
pos = shadow.position();
--- old/src/java.base/share/classes/sun/nio/ch/Util.java 2016-11-16 10:28:18.829497906 -0800
+++ new/src/java.base/share/classes/sun/nio/ch/Util.java 2016-11-16 10:28:18.772497905 -0800
@@ -234,6 +234,32 @@
}
/**
+ * Returns a temporary buffer of at least the given size and
+ * aligned to the alignment
+ */
+ public static ByteBuffer getTemporaryAlignedDirectBuffer(int size, int alignment) {
+ if (isBufferTooLarge(size)) {
+ return ByteBuffer.allocateDirect(size + alignment - 1).alignedSlice(alignment);
+ }
+
+ BufferCache cache = bufferCache.get();
+ ByteBuffer buf = cache.get(size);
+ if (buf != null) {
+ if (buf instanceof DirectBuffer) {
+ if (buf.alignmentOffset(0, alignment) == 0) {
+ return buf;
+ }
+ }
+ } else {
+ if (!cache.isEmpty()) {
+ buf = cache.removeFirst();
+ free(buf);
+ }
+ }
+ return ByteBuffer.allocateDirect(size + alignment - 1).alignedSlice(alignment);
+ }
+
+ /**
* Releases a temporary buffer by returning to the cache or freeing it.
*/
public static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
--- old/src/java.base/share/classes/sun/nio/fs/ExtendedOptions.java 2016-11-16 10:28:19.032497908 -0800
+++ new/src/java.base/share/classes/sun/nio/fs/ExtendedOptions.java 2016-11-16 10:28:18.976497907 -0800
@@ -137,6 +137,8 @@
public static final InternalOption FILE_TREE = new InternalOption<>();
+ public static final InternalOption DIRECT = new InternalOption<>();
+
public static final InternalOption SENSITIVITY_HIGH = new InternalOption<>();
public static final InternalOption SENSITIVITY_MEDIUM = new InternalOption<>();
public static final InternalOption SENSITIVITY_LOW = new InternalOption<>();
--- old/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java 2016-11-16 10:28:19.248497910 -0800
+++ new/src/java.base/unix/classes/sun/nio/fs/UnixChannelFactory.java 2016-11-16 10:28:19.191497909 -0800
@@ -64,6 +64,7 @@
boolean deleteOnClose;
boolean sync;
boolean dsync;
+ boolean direct;
static Flags toFlags(Set extends OpenOption> options) {
Flags flags = new Flags();
@@ -88,6 +89,12 @@
flags.noFollowLinks = true;
continue;
}
+
+ if (ExtendedOptions.DIRECT.matches(option)) {
+ flags.direct = true;
+ continue;
+ }
+
if (option == null)
throw new NullPointerException();
throw new UnsupportedOperationException(option + " not supported");
@@ -134,7 +141,7 @@
throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
FileDescriptor fdObj = open(dfd, path, pathForPermissionCheck, flags, mode);
- return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, null);
+ return FileChannelImpl.open(fdObj, path.toString(), flags.read, flags.write, flags.direct, null);
}
/**
--- old/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2016-11-16 10:28:19.447497912 -0800
+++ new/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template 2016-11-16 10:28:19.390497911 -0800
@@ -27,6 +27,10 @@
@@END_COPYRIGHT@@
+#ifdef __linux__
+#define _GNU_SOURCE
+#endif
+
#include
#include
#include
@@ -70,6 +74,15 @@
static final int PREFIX_O_NOFOLLOW = 00;
#endif
+#ifdef O_DIRECT
+ static final int PREFIX_DIRECT = O_DIRECT;
+#elif F_NOCACHE
+ static final int PREFIX_DIRECT = F_NOCACHE;
+//#elif DIRECTIO_ON
+// static final int PREFIX_DIRECT = DIRECTIO_ON;
+#else
+ static final int PREFIX_DIRECT = 00;
+#endif
static final int PREFIX_S_IAMB =
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
--- old/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java 2016-11-16 10:28:19.648497913 -0800
+++ new/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java 2016-11-16 10:28:19.591497913 -0800
@@ -126,6 +126,12 @@
}
@Override
+ public int getBlockSize() throws IOException {
+ UnixFileStoreAttributes attrs = readAttributes();
+ return (int)attrs.blockSize();
+ }
+
+ @Override
public long getUnallocatedSpace() throws IOException {
UnixFileStoreAttributes attrs = readAttributes();
return attrs.blockSize() * attrs.freeBlocks();
--- old/src/java.base/unix/native/libnio/ch/FileChannelImpl.c 2016-11-16 10:28:19.868497916 -0800
+++ new/src/java.base/unix/native/libnio/ch/FileChannelImpl.c 2016-11-16 10:28:19.810497915 -0800
@@ -276,3 +276,31 @@
#endif
}
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileChannelImpl_setDirect0(JNIEnv *env, jobject this, jobject fObj)
+{
+ jint fd = fdval(env, fObj);
+ jint result;
+
+#ifdef O_DIRECT
+ result = fcntl(fd, F_SETFL, O_DIRECT);
+ if (result == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "DirectIO setup failed");
+ }
+ return result;
+#elif F_NOCACHE
+ result = fcntl(fd, F_NOCACHE, 1);
+ if (result == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "DirectIO setup failed");
+ }
+ return result;
+//#elif DIRECTIO_ON
+// result = directio(fd, DIRECTIO_ON);
+// if (result == -1) {
+// JNU_ThrowIOExceptionWithLastError(env, "DirectIO setup failed");
+// }
+ return result;
+#else
+ return -1;
+#endif
+}
--- old/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2016-11-16 10:28:20.090497918 -0800
+++ new/src/java.base/windows/classes/sun/nio/fs/WindowsChannelFactory.java 2016-11-16 10:28:20.033497917 -0800
@@ -74,6 +74,7 @@
boolean overlapped;
boolean sync;
boolean dsync;
+ boolean direct;
// non-standard
boolean shareRead = true;
@@ -121,6 +122,10 @@
flags.shareDelete = false;
continue;
}
+ if (ExtendedOptions.DIRECT.matches(option)) {
+ flags.direct = true;
+ continue;
+ }
if (option == null)
throw new NullPointerException();
throw new UnsupportedOperationException();
@@ -161,7 +166,7 @@
throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed");
FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor);
- return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, null);
+ return FileChannelImpl.open(fdObj, pathForWindows, flags.read, flags.write, flags.direct, null);
}
/**
@@ -273,6 +278,8 @@
dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
if (flags.deleteOnClose)
dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+ if (flags.direct)
+ dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
// NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point
boolean okayToFollowLinks = true;
--- old/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java 2016-11-16 10:28:20.290497920 -0800
+++ new/src/java.base/windows/classes/sun/nio/fs/WindowsFileStore.java 2016-11-16 10:28:20.233497919 -0800
@@ -125,7 +125,7 @@
}
// read the free space info
- private DiskFreeSpace readDiskFreeSpace() throws IOException {
+ private DiskFreeSpace readDiskFreeSpaceEx() throws IOException {
try {
return GetDiskFreeSpaceEx(root);
} catch (WindowsException x) {
@@ -134,19 +134,33 @@
}
}
+ private DiskFreeSpace readDiskFreeSpace() throws IOException {
+ try {
+ return GetDiskFreeSpace(root);
+ } catch (WindowsException x) {
+ x.rethrowAsIOException(root);
+ return null;
+ }
+ }
+
@Override
public long getTotalSpace() throws IOException {
- return readDiskFreeSpace().totalNumberOfBytes();
+ return readDiskFreeSpaceEx().totalNumberOfBytes();
}
@Override
public long getUsableSpace() throws IOException {
- return readDiskFreeSpace().freeBytesAvailable();
+ return readDiskFreeSpaceEx().freeBytesAvailable();
+ }
+
+ @Override
+ public int getBlockSize() throws IOException {
+ return (int)readDiskFreeSpace().bytesPerSector();
}
@Override
public long getUnallocatedSpace() throws IOException {
- return readDiskFreeSpace().freeBytesAvailable();
+ return readDiskFreeSpaceEx().freeBytesAvailable();
}
@Override
@@ -165,6 +179,8 @@
return getUsableSpace();
if (attribute.equals("unallocatedSpace"))
return getUnallocatedSpace();
+ if (attribute.equals("bytesPerSector"))
+ return getBlockSize();
// windows specific for testing purposes
if (attribute.equals("volume:vsn"))
return volInfo.volumeSerialNumber();
--- old/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java 2016-11-16 10:28:20.489497921 -0800
+++ new/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java 2016-11-16 10:28:20.432497921 -0800
@@ -485,21 +485,50 @@
buffer.release();
}
}
+
+ /**
+ * GetDiskFreeSpace(
+ * LPCTSTR lpRootPathName,
+ * LPDWORD lpSectorsPerCluster,
+ * LPDWORD lpBytesPerSector,
+ * LPDWORD lpNumberOfFreeClusters,
+ * LPDWORD lpTotalNumberOfClusters
+ * )
+ */
+ static DiskFreeSpace GetDiskFreeSpace(String path)
+ throws WindowsException
+ {
+ NativeBuffer buffer = asNativeBuffer(path);
+ try {
+ DiskFreeSpace space = new DiskFreeSpace();
+ GetDiskFreeSpace0(buffer.address(), space);
+ return space;
+ } finally {
+ buffer.release();
+ }
+ }
+
static class DiskFreeSpace {
private long freeBytesAvailable;
private long totalNumberOfBytes;
private long totalNumberOfFreeBytes;
+ private long bytesPerSector;
private DiskFreeSpace() { }
public long freeBytesAvailable() { return freeBytesAvailable; }
public long totalNumberOfBytes() { return totalNumberOfBytes; }
public long totalNumberOfFreeBytes() { return totalNumberOfFreeBytes; }
+ public long bytesPerSector() { return bytesPerSector; }
}
private static native void GetDiskFreeSpaceEx0(long lpDirectoryName,
DiskFreeSpace obj)
throws WindowsException;
+ private static native void GetDiskFreeSpace0(long lpRootPathName,
+ DiskFreeSpace obj)
+ throws WindowsException;
+
/**
* GetVolumePathName(
* LPCTSTR lpszFileName,
--- old/src/java.base/windows/native/libnio/ch/FileChannelImpl.c 2016-11-16 10:28:20.703497923 -0800
+++ new/src/java.base/windows/native/libnio/ch/FileChannelImpl.c 2016-11-16 10:28:20.646497923 -0800
@@ -218,3 +218,9 @@
}
return chunkSize;
}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileChannelImpl_setDirect0(JNIEnv *env, jobject this, jobject fObj)
+{
+ return 0;
+}
--- old/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c 2016-11-16 10:28:20.918497925 -0800
+++ new/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c 2016-11-16 10:28:20.860497925 -0800
@@ -59,6 +59,8 @@
static jfieldID diskSpace_totalBytes;
static jfieldID diskSpace_totalFree;
+static jfieldID diskSpace_bytesPerSector;
+
static jfieldID account_domain;
static jfieldID account_name;
static jfieldID account_use;
@@ -121,6 +123,8 @@
CHECK_NULL(diskSpace_totalBytes);
diskSpace_totalFree = (*env)->GetFieldID(env, clazz, "totalNumberOfFreeBytes", "J");
CHECK_NULL(diskSpace_totalFree);
+ diskSpace_bytesPerSector = (*env)->GetFieldID(env, clazz, "bytesPerSector", "J");
+ CHECK_NULL(diskSpace_bytesPerSector);
clazz = (*env)->FindClass(env, "sun/nio/fs/WindowsNativeDispatcher$Account");
CHECK_NULL(clazz);
@@ -582,6 +586,30 @@
long_to_jlong(totalNumberOfFreeBytes.QuadPart));
}
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_WindowsNativeDispatcher_GetDiskFreeSpace0(JNIEnv* env, jclass this,
+ jlong address, jobject obj)
+{
+ DWORD sectorsPerCluster;
+ DWORD bytesPerSector;
+ DWORD numberOfFreeClusters;
+ DWORD totalNumberOfClusters;
+ LPCWSTR lpRootPathName = jlong_to_ptr(address);
+
+
+ BOOL res = GetDiskFreeSpaceW(lpRootPathName,
+ §orsPerCluster,
+ &bytesPerSector,
+ &numberOfFreeClusters,
+ &totalNumberOfClusters);
+ if (res == 0) {
+ throwWindowsException(env, GetLastError());
+ return;
+ }
+
+ (*env)->SetLongField(env, obj, diskSpace_bytesPerSector,
+ long_to_jlong(bytesPerSector));
+}
JNIEXPORT jstring JNICALL
Java_sun_nio_fs_WindowsNativeDispatcher_GetVolumePathName0(JNIEnv* env, jclass this,
--- old/src/jdk.unsupported/share/classes/com/sun/nio/file/ExtendedOpenOption.java 2016-11-16 10:28:21.141497928 -0800
+++ new/src/jdk.unsupported/share/classes/com/sun/nio/file/ExtendedOpenOption.java 2016-11-16 10:28:21.084497927 -0800
@@ -47,7 +47,12 @@
/**
* Prevent operations on the file that request delete access.
*/
- NOSHARE_DELETE(ExtendedOptions.NOSHARE_DELETE);
+ NOSHARE_DELETE(ExtendedOptions.NOSHARE_DELETE),
+
+ /**
+ * DirectIO.
+ */
+ DIRECT(ExtendedOptions.DIRECT);
ExtendedOpenOption(ExtendedOptions.InternalOption option) {
option.register(this);
--- old/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileStore.java 2016-11-16 10:28:21.375497930 -0800
+++ new/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileStore.java 2016-11-16 10:28:21.318497929 -0800
@@ -89,6 +89,11 @@
}
@Override
+ public int getBlockSize() throws IOException {
+ throw new UnsupportedOperationException("getBlockSize");
+ }
+
+ @Override
public long getUsableSpace() throws IOException {
return new ZipFileStoreAttributes(this).usableSpace();
}
--- /dev/null 2016-11-14 12:26:28.251338568 -0800
+++ new/test/java/nio/channels/FileChannel/PreadDirect.java 2016-11-16 10:28:21.533497931 -0800
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2000, 2010, 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 4862382
+ * @summary Test positional read method of FileChannel with DirectIO
+ * @key randomness
+ */
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.*;
+import java.nio.channels.FileChannel;
+import java.util.Random;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import com.sun.nio.file.ExtendedOpenOption;
+
+/**
+ * Testing FileChannel's positional read method.
+ */
+
+public class PreadDirect {
+
+ private static PrintStream err = System.err;
+
+ private static Random generator = new Random();
+
+ private static int CHARS_PER_GROUP = 4096;
+
+ public static void main(String[] args) throws Exception {
+ genericTest1();
+ genericTest2();
+ testNegativePosition(); // This test for bug 4862382
+ }
+
+ // This test for bug 4862382
+ private static void testNegativePosition() throws Exception {
+ File blah = File.createTempFile("blah1", null);
+ blah.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(blah);
+ fos.write(new byte[4096]);
+ fos.close();
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+
+ try {
+ fc.read(ByteBuffer.allocate(4096), -1L);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch(IllegalArgumentException e) {
+ // Correct result
+ } finally {
+ fc.close();
+ blah.delete();
+ }
+ }
+
+ private static void genericTest2() throws Exception {
+ File blah = File.createTempFile("blah2", null);
+ blah.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(blah);
+ fos.write(new byte[4096]);
+ fos.close();
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+ try {
+ fc.read(ByteBuffer.allocate(4096), 4000);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch(IllegalArgumentException e) {
+ if (!e.getMessage().contains("IO size or position is not aligned"))
+ throw new RuntimeException("Read test failed");
+ } finally {
+ fc.close();
+ blah.delete();
+ }
+ }
+
+ private static void genericTest1() throws Exception {
+ StringBuffer sb = new StringBuffer();
+ sb.setLength(2);
+
+ File blah = File.createTempFile("blah3", null);
+ blah.deleteOnExit();
+ initTestFile(blah);
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel c = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+
+ for (int x=0; x<100; x++) {
+ long offset = generator.nextInt(100) * 4096;
+ long expectedResult = offset / CHARS_PER_GROUP;
+ offset = expectedResult * CHARS_PER_GROUP;
+ ByteBuffer block = ByteBuffer.allocateDirect(4096 + alignment - 1).alignedSlice(alignment);
+
+ long originalPosition = c.position();
+
+ int totalRead = 0;
+ while (totalRead < 4096) {
+ int read = c.read(block, offset);
+ if (read < 0)
+ throw new Exception("Read failed");
+ totalRead += read;
+ }
+
+ long newPosition = c.position();
+
+ for (int i=0; i<2; i++) {
+ byte aByte = block.get(i);
+ sb.setCharAt(i, (char)aByte);
+ }
+ int result = Integer.parseInt(sb.toString());
+ if (result != expectedResult) {
+ err.println("I expected "+ expectedResult);
+ err.println("I got "+ result);
+ throw new Exception("Read test failed");
+ }
+
+ // Ensure that file pointer position has not changed
+ if (originalPosition != newPosition)
+ throw new Exception("File position modified");
+ }
+
+ c.close();
+ blah.delete();
+ }
+
+ /**
+ * Creates file blah:
+ */
+ private static void initTestFile(File blah) throws Exception {
+ FileOutputStream fos = new FileOutputStream(blah);
+ BufferedWriter awriter
+ = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
+
+ for(int i=0; i<100; i++) {
+ String number = new Integer(i).toString();
+ for (int h=0; h<2-number.length(); h++)
+ awriter.write("0");
+ awriter.write(""+i);
+ for (int j=0; j < 4094; j++)
+ awriter.write("0");
+ }
+ awriter.flush();
+ awriter.close();
+ }
+}
--- /dev/null 2016-11-14 12:26:28.251338568 -0800
+++ new/test/java/nio/channels/FileChannel/PwriteDirect.java 2016-11-16 10:28:21.729497933 -0800
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2000, 2010, 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 4862411
+ * @summary Test positional write method of FileChannel with DirectIO
+ * @key randomness
+ */
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.*;
+import java.nio.channels.FileChannel;
+import java.util.Random;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.StandardOpenOption;
+import com.sun.nio.file.ExtendedOpenOption;
+
+/**
+ * Testing FileChannel's positional write method.
+ */
+public class PwriteDirect {
+
+ private static Random generator = new Random();
+
+ private static File blah;
+
+ public static void main(String[] args) throws Exception {
+ genericTest();
+ testUnwritableChannel();
+ }
+
+ // This test for bug 4862411
+ private static void testUnwritableChannel() throws Exception {
+ File blah = File.createTempFile("blah2", null);
+ blah.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(blah);
+ fos.write(new byte[4096]);
+ fos.close();
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel fc = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+
+ try {
+ fc.write(ByteBuffer.allocate(4096),0);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch(NonWritableChannelException e) {
+ // Correct result
+ } finally {
+ fc.close();
+ blah.delete();
+ }
+ }
+
+ private static void genericTest() throws Exception {
+ blah = File.createTempFile("blah", null);
+ blah.deleteOnExit();
+ initTestFile(blah);
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel c = FileChannel.open(p, StandardOpenOption.WRITE, StandardOpenOption.READ, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+
+ for (int x=0; x<100; x++) {
+ long offset = generator.nextInt(100) * 4096;
+ ByteBuffer block = ByteBuffer.allocateDirect(4096 + alignment - 1).alignedSlice(alignment);
+
+ // Write known sequence out
+ for (byte i=0; i<4; i++) {
+ block.put(i);
+ }
+ block.position(0);
+ long originalPosition = c.position();
+ int totalWritten = 0;
+ while (totalWritten < 4096) {
+ int written = c.write(block, offset);
+ if (written < 0)
+ throw new Exception("Write failed");
+ totalWritten += written;
+ }
+
+ long newPosition = c.position();
+
+ // Ensure that file pointer position has not changed
+ if (originalPosition != newPosition)
+ throw new Exception("File position modified");
+
+ // Attempt to read sequence back in
+ block = ByteBuffer.allocateDirect(4096 + alignment - 1).alignedSlice(alignment);
+ originalPosition = c.position();
+ int totalRead = 0;
+ while (totalRead < 4096) {
+ int read = c.read(block, offset);
+ if (read < 0)
+ throw new Exception("Read failed");
+ totalRead += read;
+ }
+ newPosition = c.position();
+
+ // Ensure that file pointer position has not changed
+ if (originalPosition != newPosition)
+ throw new Exception("File position modified");
+
+ for (byte i=0; i<4; i++) {
+ if (block.get(i) != i)
+ throw new Exception("Write test failed");
+ }
+ }
+ c.close();
+ blah.delete();
+ }
+
+ /**
+ * Creates file blah:
+ */
+ private static void initTestFile(File blah) throws Exception {
+ FileOutputStream fos = new FileOutputStream(blah);
+ BufferedWriter awriter
+ = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
+
+ for(int i=0; i<100; i++) {
+ String number = new Integer(i).toString();
+ for (int h=0; h<4-number.length(); h++)
+ awriter.write("0");
+ awriter.write(""+i);
+ for (int j=0; j < 4092; j++)
+ awriter.write("0");
+ }
+ awriter.flush();
+ awriter.close();
+ }
+}
--- /dev/null 2016-11-14 12:26:28.251338568 -0800
+++ new/test/java/nio/channels/FileChannel/ReadDirect.java 2016-11-16 10:28:21.926497935 -0800
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2000, 2010, 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @summary Test read method of FileChannel with DirectIO
+ */
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.*;
+import java.nio.channels.FileChannel;
+import java.util.Random;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import com.sun.nio.file.ExtendedOpenOption;
+
+/**
+ * Testing FileChannel's mapping capabilities.
+ */
+
+public class ReadDirect {
+
+ private static PrintStream err = System.err;
+
+ private static Random generator = new Random();
+
+ private static File blah;
+
+ private static void testRead1() throws Exception {
+ StringBuffer sb = new StringBuffer();
+ sb.setLength(2);
+
+ int charsPerGroup = 4096;
+ blah = File.createTempFile("blah1", null);
+ blah.deleteOnExit();
+ initTestFile(blah, charsPerGroup);
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel c = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+
+ for (int x=0; x<100; x++) {
+ long offset = x * charsPerGroup;
+ long expectedResult = offset / charsPerGroup;
+ ByteBuffer block = ByteBuffer.allocateDirect(charsPerGroup + alignment - 1).alignedSlice(alignment);
+ c.read(block);
+
+ for (int i=0; i<2; i++) {
+ byte aByte = block.get(i);
+ sb.setCharAt(i, (char)aByte);
+ }
+ int result = Integer.parseInt(sb.toString());
+ if (result != expectedResult) {
+ err.println("I expected "+expectedResult);
+ err.println("I got "+ result);
+ throw new Exception("Read test failed");
+ }
+ }
+ c.close();
+ blah.delete();
+ }
+
+ private static void testRead2() throws Exception {
+ int charsPerGroup = 4000;
+ blah = File.createTempFile("blah2", null);
+ blah.deleteOnExit();
+
+ FileOutputStream fos = new FileOutputStream(blah);
+ fos.write(new byte[charsPerGroup]);
+ fos.close();
+
+ String path = blah.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel c = FileChannel.open(p, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+
+ ByteBuffer block = ByteBuffer.allocate(charsPerGroup);
+ try {
+ c.read(block);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch (IllegalArgumentException e) {
+ if (!e.getMessage().contains("IO size or position is not aligned"))
+ throw new Exception("Read test failed");
+ } finally {
+ c.close();
+ blah.delete();
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+ testRead1();
+ testRead2();
+ }
+
+ /**
+ * Creates file blah:
+ */
+ private static void initTestFile(File blah, int charsPerGroup) throws Exception {
+ FileOutputStream fos = new FileOutputStream(blah);
+ BufferedWriter awriter
+ = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
+
+ for(int i=0; i<100; i++) {
+ String number = new Integer(i).toString();
+ for (int h=0; h<2-number.length(); h++)
+ awriter.write("0");
+ awriter.write(""+i);
+ for (int j=0; j < (charsPerGroup - 2); j++)
+ awriter.write("0");
+ }
+ awriter.flush();
+ awriter.close();
+ }
+}
--- /dev/null 2016-11-14 12:26:28.251338568 -0800
+++ new/test/java/nio/channels/FileChannel/WriteDirect.java 2016-11-16 10:28:22.127497937 -0800
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2001, 2010, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary Test FileChannel write with DirectIO
+ * @run main/othervm Write
+ */
+
+import java.nio.channels.*;
+import java.nio.*;
+import java.io.*;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.StandardOpenOption;
+import com.sun.nio.file.ExtendedOpenOption;
+
+public class WriteDirect {
+
+ public static void main(String[] args) throws Exception {
+ test1();
+ test2();
+ }
+
+ static void test1() throws Exception {
+ File testFile = File.createTempFile("test1", null);
+ testFile.deleteOnExit();
+
+ String path = testFile.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+ ByteBuffer src = ByteBuffer.allocate(4000);
+ try {
+ fc.write(src);
+ throw new RuntimeException("Expected exception not thrown");
+ } catch (IllegalArgumentException e) {
+ if (!e.getMessage().contains("IO size or position is not aligned"))
+ throw new Exception("Write failure");
+ } finally {
+ fc.close();
+ }
+
+ testFile.delete();
+ }
+
+ // Test to see that the appropriate buffers are updated
+ static void test2() throws Exception {
+ File testFile = File.createTempFile("test2", null);
+ testFile.deleteOnExit();
+ ByteBuffer[] srcs = new ByteBuffer[4];
+ String path = testFile.getAbsolutePath();
+ Path p = Paths.get(path);
+ FileChannel fc = FileChannel.open(p, StandardOpenOption.WRITE, ExtendedOpenOption.DIRECT);
+ FileStore fs = Files.getFileStore(p);
+ int alignment = fs.getBlockSize();
+
+ for (int i=0; i<4; i++) {
+ srcs[i] = ByteBuffer.allocateDirect(4096 + alignment -1).alignedSlice(alignment);
+ for (int j=0; j<4096; j++) {
+ srcs[i].put((byte)i);
+ }
+ srcs[i].flip();
+ }
+
+ try {
+ fc.write(srcs, 1, 2);
+ } finally {
+ fc.close();
+ }
+
+ FileInputStream fis = new FileInputStream(testFile);
+ fc = fis.getChannel();
+ try {
+ ByteBuffer bb = ByteBuffer.allocateDirect(8192);
+ fc.read(bb);
+ bb.flip();
+ for (int k=0; k<4096; k++) {
+ if (bb.get() != 1)
+ throw new RuntimeException("Write failure");
+ }
+ for (int m=0; m<4096; m++) {
+ if (bb.get() != 2)
+ throw new RuntimeException("Write failure");
+ }
+ try {
+ bb.get();
+ throw new RuntimeException("Write failure");
+ } catch (BufferUnderflowException bufe) {
+ // correct result
+ }
+ } finally {
+ fc.close();
+ }
+
+ // eagerly clean-up
+ testFile.delete();
+ }
+}