< prev index next >

src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

Print this page

        

@@ -47,10 +47,16 @@
 import jdk.internal.misc.JavaNioAccess;
 import jdk.internal.misc.SharedSecrets;
 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
 {
     // Memory allocation size for mapping buffers
     private static final long allocationGranularity;

@@ -83,28 +89,59 @@
     private final Object positionLock = new Object();
 
     // 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 {
         if (!isOpen())
             throw new ClosedChannelException();

@@ -148,10 +185,13 @@
         }
 
     }
 
     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();
         synchronized (positionLock) {
             int n = 0;

@@ -160,11 +200,11 @@
                 begin();
                 ti = threads.add();
                 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 {
                 threads.remove(ti);
                 end(n > 0);

@@ -176,10 +216,14 @@
     public long read(ByteBuffer[] dsts, int offset, int length)
         throws IOException
     {
         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();
         synchronized (positionLock) {
             long n = 0;

@@ -188,11 +232,11 @@
                 begin();
                 ti = threads.add();
                 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 {
                 threads.remove(ti);
                 end(n > 0);

@@ -200,23 +244,27 @@
             }
         }
     }
 
     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;
             try {
                 begin();
                 ti = threads.add();
                 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 {
                 threads.remove(ti);
                 end(n > 0);

@@ -231,20 +279,24 @@
         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
             throw new IndexOutOfBoundsException();
         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;
             try {
                 begin();
                 ti = threads.add();
                 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 {
                 threads.remove(ti);
                 end(n > 0);

@@ -723,10 +775,14 @@
             throw new NullPointerException();
         if (position < 0)
             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) {
                 return readInternal(dst, position);
             }

@@ -745,11 +801,11 @@
             if (interruptible) begin();
             ti = threads.add();
             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 {
             threads.remove(ti);
             if (interruptible) end(n > 0);

@@ -762,10 +818,14 @@
             throw new NullPointerException();
         if (position < 0)
             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) {
                 return writeInternal(src, position);
             }

@@ -782,11 +842,11 @@
             begin();
             ti = threads.add();
             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 {
             threads.remove(ti);
             end(n > 0);

@@ -1226,10 +1286,12 @@
     private native long position0(FileDescriptor fd, long offset);
 
     // Caches fieldIDs
     private static native long initIDs();
 
+    private native int setDirect0(FileDescriptor fd) throws IOException;
+
     static {
         IOUtil.load();
         allocationGranularity = initIDs();
     }
 
< prev index next >