--- old/src/java.base/share/classes/java/io/FileOutputStream.java 2016-08-25 17:51:52.726564686 -0700
+++ new/src/java.base/share/classes/java/io/FileOutputStream.java 2016-08-25 17:51:52.624564685 -0700
@@ -79,6 +79,10 @@
private final AtomicBoolean closed = new AtomicBoolean(false);
+ private boolean direct = false;
+
+ private int pageSize = -1;
+
/**
* Creates a file output stream to write to the file with the
* specified name. A new FileDescriptor
object is
@@ -101,7 +105,7 @@
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
*/
public FileOutputStream(String name) throws FileNotFoundException {
- this(name != null ? new File(name) : null, false);
+ this(name != null ? new File(name) : null, false, false);
}
/**
@@ -133,7 +137,42 @@
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
{
- this(name != null ? new File(name) : null, append);
+ this(name != null ? new File(name) : null, append, false);
+ }
+
+ /**
+ * Creates a file output stream to write to the file with the specified
+ * name. If the second argument is true
, then bytes will
+ * be written to the end of the file rather than the beginning. If the
+ * third parameter is true
, then bytes will be directly
+ * written to storage media. A new FileDescriptor
object
+ * is created to represent this file connection.
+ *
+ * First, if there is a security manager, its checkWrite
+ * method is called with name
as its argument.
+ *
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a FileNotFoundException
is thrown.
+ *
+ * @param name the system-dependent file name
+ * @param append if true
, then bytes will be written
+ * to the end of the file rather than the beginning
+ * @param direct if true
, then bytes will be written
+ * directly to storage media
+ * @exception FileNotFoundException if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason.
+ * @exception SecurityException if a security manager exists and its
+ * checkWrite
method denies write access
+ * to the file.
+ * @see java.lang.SecurityManager#checkWrite(java.lang.String)
+ * @since 1.9
+ */
+ public FileOutputStream(String name, boolean append, boolean direct)
+ throws FileNotFoundException
+ {
+ this(name != null ? new File(name) : null, append, direct);
}
/**
@@ -162,7 +201,7 @@
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
*/
public FileOutputStream(File file) throws FileNotFoundException {
- this(file, false);
+ this(file, false, false);
}
/**
@@ -197,6 +236,49 @@
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{
+ this(file, append, false);
+ }
+
+ /**
+ * Creates a file output stream to write to the file represented by
+ * the specified File
object. If the second argument is
+ * true
, then bytes will be written to the end of the file
+ * rather than the beginning. If the third argument is true
,
+ * then bytes will be directly written to storage media. A new
+ * FileDescriptor
object is created to represent this file
+ * connection.
+ *
+ * First, if there is a security manager, its checkWrite
+ * method is called with the path represented by the file
+ * argument as its argument.
+ *
+ * If the file exists but is a directory rather than a regular file, does
+ * not exist but cannot be created, or cannot be opened for any other
+ * reason then a FileNotFoundException
is thrown.
+ *
+ * @param file the file to be opened for writing.
+ * @param append if true
, then bytes will be written
+ * to the end of the file rather than the beginning
+ * @param direct if true
, then bytes will be written
+ * directly to storage media
+ * @exception FileNotFoundException if the file exists but is a directory
+ * rather than a regular file, does not exist but cannot
+ * be created, or cannot be opened for any other reason
+ * @exception SecurityException if a security manager exists and its
+ * checkWrite
method denies write access
+ * to the file.
+ * @see java.io.File#getPath()
+ * @see java.lang.SecurityException
+ * @see java.lang.SecurityManager#checkWrite(java.lang.String)
+ * @since 1.9
+ */
+ public FileOutputStream(File file, boolean append, boolean direct)
+ throws FileNotFoundException
+ {
+ this.direct = direct;
+ if (direct) {
+ getPageSize();
+ }
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
@@ -256,8 +338,9 @@
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
+ * @param direct whether the file s to be opened in the direct mode
*/
- private native void open0(String name, boolean append)
+ private native void open0(String name, boolean append, boolean direct)
throws FileNotFoundException;
// wrap native call to allow instrumentation
@@ -268,7 +351,16 @@
*/
private void open(String name, boolean append)
throws FileNotFoundException {
- open0(name, append);
+ open0(name, append, direct);
+ }
+
+ private native int getPageSize0();
+
+ private int getPageSize() {
+ if (pageSize == -1) {
+ pageSize = getPageSize0();
+ }
+ return this.pageSize;
}
/**
@@ -304,6 +396,17 @@
throws IOException;
/**
+ * Writes a sub array as a sequence of bytes with DirectIO.
+ * @param b the data to be written
+ * @param off the start offset in the data
+ * @param len the number of bytes that are written
+ * @param append {@code true} to first advance the position to the
+ * end of file
+ * @exception IOException If an I/O error has occurred.*/
+ private native void writeBytesD(byte b[], int off, int len, boolean append)
+ throws IOException;
+
+ /**
* Writes b.length
bytes from the specified byte array
* to this file output stream.
*
@@ -311,7 +414,15 @@
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[]) throws IOException {
- writeBytes(b, 0, b.length, fdAccess.getAppend(fd));
+ if (direct) {
+ if((b.length % pageSize != 0) ||(getCurrentLocation() % pageSize != 0)) {
+ throw new IOException("In DirectIO mode, the IO size must be aligned "
+ + "with kernel page size " + pageSize + " bytes!");
+ }
+ writeBytesD(b, 0, b.length, fdAccess.getAppend(fd));
+ } else {
+ writeBytes(b, 0, b.length, fdAccess.getAppend(fd));
+ }
}
/**
@@ -324,9 +435,23 @@
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
- writeBytes(b, off, len, fdAccess.getAppend(fd));
+ if (direct) {
+ if((len % pageSize != 0) || (getCurrentLocation() % pageSize != 0)) {
+ throw new IOException("In DirectIO mode, the IO size and the start "
+ + "point must be aligned with kernel page size " + pageSize + " bytes!");
+ }
+ writeBytesD(b, off, len, fdAccess.getAppend(fd));
+ } else {
+ writeBytes(b, off, len, fdAccess.getAppend(fd));
+ }
+ }
+
+ private long getCurrentLocation() throws IOException {
+ return getCurrentLocation0();
}
+ private native long getCurrentLocation0() throws IOException;
+
/**
* Closes this file output stream and releases any system resources
* associated with this stream. This file output stream may no longer