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

Print this page
rev 6099 : [mq]: io-trace


  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.nio.ByteBuffer;
  31 import java.nio.MappedByteBuffer;
  32 import java.nio.channels.*;
  33 import java.util.ArrayList;
  34 import java.util.List;
  35 import java.security.AccessController;
  36 import sun.misc.Cleaner;


  37 import sun.security.action.GetPropertyAction;
  38 
  39 public class FileChannelImpl
  40     extends FileChannel
  41 {
  42     // Memory allocation size for mapping buffers
  43     private static final long allocationGranularity;
  44 
  45     // Used to make native read and write calls
  46     private final FileDispatcher nd;
  47 
  48     // File descriptor
  49     private final FileDescriptor fd;
  50 
  51     // File access mode (immutable)
  52     private final boolean writable;
  53     private final boolean readable;
  54     private final boolean append;
  55 
  56     // Required to prevent finalization of creating stream (immutable)
  57     private final Object parent;
  58 



  59     // Thread-safe set of IDs of native threads, for signalling
  60     private final NativeThreadSet threads = new NativeThreadSet(2);
  61 
  62     // Lock for operations involving position and size
  63     private final Object positionLock = new Object();
  64 
  65     private FileChannelImpl(FileDescriptor fd, boolean readable,
  66                             boolean writable, boolean append, Object parent)
  67     {
  68         this.fd = fd;
  69         this.readable = readable;
  70         this.writable = writable;
  71         this.append = append;
  72         this.parent = parent;

  73         this.nd = new FileDispatcherImpl(append);
  74     }
  75 
  76     // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
  77     public static FileChannel open(FileDescriptor fd,
  78                                    boolean readable, boolean writable,
  79                                    Object parent)
  80     {
  81         return new FileChannelImpl(fd, readable, writable, false, parent);
  82     }
  83 
  84     // Used by FileOutputStream.getChannel
  85     public static FileChannel open(FileDescriptor fd,
  86                                    boolean readable, boolean writable,
  87                                    boolean append, Object parent)
  88     {
  89         return new FileChannelImpl(fd, readable, writable, append, parent);
  90     }
  91 
  92     private void ensureOpen() throws IOException {
  93         if (!isOpen())
  94             throw new ClosedChannelException();
  95     }
  96 
  97 
  98     // -- Standard channel operations --
  99 
 100     protected void implCloseChannel() throws IOException {
 101         // Release and invalidate any locks that we still hold
 102         if (fileLockTable != null) {
 103             for (FileLock fl: fileLockTable.removeAll()) {
 104                 synchronized (fl) {
 105                     if (fl.isValid()) {
 106                         nd.release(fd, fl.position(), fl.size());
 107                         ((FileLockImpl)fl).invalidate();
 108                     }
 109                 }


 117 
 118             // Close the fd via the parent stream's close method.  The parent
 119             // will reinvoke our close method, which is defined in the
 120             // superclass AbstractInterruptibleChannel, but the isOpen logic in
 121             // that method will prevent this method from being reinvoked.
 122             //
 123             ((java.io.Closeable)parent).close();
 124         } else {
 125             nd.close(fd);
 126         }
 127 
 128     }
 129 
 130     public int read(ByteBuffer dst) throws IOException {
 131         ensureOpen();
 132         if (!readable)
 133             throw new NonReadableChannelException();
 134         synchronized (positionLock) {
 135             int n = 0;
 136             int ti = -1;

 137             try {
 138                 begin();
 139                 ti = threads.add();
 140                 if (!isOpen())
 141                     return 0;
 142                 do {
 143                     n = IOUtil.read(fd, dst, -1, nd, positionLock);
 144                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 145                 return IOStatus.normalize(n);
 146             } finally {
 147                 threads.remove(ti);

 148                 end(n > 0);
 149                 assert IOStatus.check(n);
 150             }
 151         }
 152     }
 153 
 154     public long read(ByteBuffer[] dsts, int offset, int length)
 155         throws IOException
 156     {
 157         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
 158             throw new IndexOutOfBoundsException();
 159         ensureOpen();
 160         if (!readable)
 161             throw new NonReadableChannelException();
 162         synchronized (positionLock) {
 163             long n = 0;
 164             int ti = -1;

 165             try {
 166                 begin();
 167                 ti = threads.add();
 168                 if (!isOpen())
 169                     return 0;
 170                 do {
 171                     n = IOUtil.read(fd, dsts, offset, length, nd);
 172                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 173                 return IOStatus.normalize(n);
 174             } finally {
 175                 threads.remove(ti);

 176                 end(n > 0);
 177                 assert IOStatus.check(n);
 178             }
 179         }
 180     }
 181 
 182     public int write(ByteBuffer src) throws IOException {
 183         ensureOpen();
 184         if (!writable)
 185             throw new NonWritableChannelException();
 186         synchronized (positionLock) {
 187             int n = 0;
 188             int ti = -1;

 189             try {
 190                 begin();
 191                 ti = threads.add();
 192                 if (!isOpen())
 193                     return 0;
 194                 do {
 195                     n = IOUtil.write(fd, src, -1, nd, positionLock);
 196                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 197                 return IOStatus.normalize(n);
 198             } finally {
 199                 threads.remove(ti);
 200                 end(n > 0);

 201                 assert IOStatus.check(n);
 202             }
 203         }
 204     }
 205 
 206     public long write(ByteBuffer[] srcs, int offset, int length)
 207         throws IOException
 208     {
 209         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
 210             throw new IndexOutOfBoundsException();
 211         ensureOpen();
 212         if (!writable)
 213             throw new NonWritableChannelException();
 214         synchronized (positionLock) {
 215             long n = 0;
 216             int ti = -1;

 217             try {
 218                 begin();
 219                 ti = threads.add();
 220                 if (!isOpen())
 221                     return 0;
 222                 do {
 223                     n = IOUtil.write(fd, srcs, offset, length, nd);
 224                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 225                 return IOStatus.normalize(n);
 226             } finally {
 227                 threads.remove(ti);

 228                 end(n > 0);
 229                 assert IOStatus.check(n);
 230             }
 231         }
 232     }
 233 
 234     // -- Other operations --
 235 
 236     public long position() throws IOException {
 237         ensureOpen();
 238         synchronized (positionLock) {
 239             long p = -1;
 240             int ti = -1;
 241             try {
 242                 begin();
 243                 ti = threads.add();
 244                 if (!isOpen())
 245                     return 0;
 246                 do {
 247                     // in append-mode then position is advanced to end before writing


 656             throw new IllegalArgumentException();
 657         if (position > size())
 658             return 0;
 659         if (src instanceof FileChannelImpl)
 660            return transferFromFileChannel((FileChannelImpl)src,
 661                                           position, count);
 662 
 663         return transferFromArbitraryChannel(src, position, count);
 664     }
 665 
 666     public int read(ByteBuffer dst, long position) throws IOException {
 667         if (dst == null)
 668             throw new NullPointerException();
 669         if (position < 0)
 670             throw new IllegalArgumentException("Negative position");
 671         if (!readable)
 672             throw new NonReadableChannelException();
 673         ensureOpen();
 674         int n = 0;
 675         int ti = -1;

 676         try {
 677             begin();
 678             ti = threads.add();
 679             if (!isOpen())
 680                 return -1;
 681             do {
 682                 n = IOUtil.read(fd, dst, position, nd, positionLock);
 683             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 684             return IOStatus.normalize(n);
 685         } finally {
 686             threads.remove(ti);

 687             end(n > 0);
 688             assert IOStatus.check(n);
 689         }
 690     }
 691 
 692     public int write(ByteBuffer src, long position) throws IOException {
 693         if (src == null)
 694             throw new NullPointerException();
 695         if (position < 0)
 696             throw new IllegalArgumentException("Negative position");
 697         if (!writable)
 698             throw new NonWritableChannelException();
 699         ensureOpen();
 700         int n = 0;
 701         int ti = -1;

 702         try {
 703             begin();
 704             ti = threads.add();
 705             if (!isOpen())
 706                 return -1;
 707             do {
 708                 n = IOUtil.write(fd, src, position, nd, positionLock);
 709             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 710             return IOStatus.normalize(n);
 711         } finally {
 712             threads.remove(ti);
 713             end(n > 0);

 714             assert IOStatus.check(n);
 715         }
 716     }
 717 
 718 
 719     // -- Memory-mapped buffers --
 720 
 721     private static class Unmapper
 722         implements Runnable
 723     {
 724         // may be required to close file
 725         private static final NativeDispatcher nd = new FileDispatcherImpl();
 726 
 727         // keep track of mapped buffer usage
 728         static volatile int count;
 729         static volatile long totalSize;
 730         static volatile long totalCapacity;
 731 
 732         private volatile long address;
 733         private final long size;




  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.nio.ByteBuffer;
  31 import java.nio.MappedByteBuffer;
  32 import java.nio.channels.*;
  33 import java.util.ArrayList;
  34 import java.util.List;
  35 import java.security.AccessController;
  36 import sun.misc.Cleaner;
  37 import sun.misc.IoTrace;
  38 import sun.misc.IoTraceContext;
  39 import sun.security.action.GetPropertyAction;
  40 
  41 public class FileChannelImpl
  42     extends FileChannel
  43 {
  44     // Memory allocation size for mapping buffers
  45     private static final long allocationGranularity;
  46 
  47     // Used to make native read and write calls
  48     private final FileDispatcher nd;
  49 
  50     // File descriptor
  51     private final FileDescriptor fd;
  52 
  53     // File access mode (immutable)
  54     private final boolean writable;
  55     private final boolean readable;
  56     private final boolean append;
  57 
  58     // Required to prevent finalization of creating stream (immutable)
  59     private final Object parent;
  60 
  61     // The path of the referenced file (null if the parent stream is created with a file descriptor)
  62     private final String path;
  63 
  64     // Thread-safe set of IDs of native threads, for signalling
  65     private final NativeThreadSet threads = new NativeThreadSet(2);
  66 
  67     // Lock for operations involving position and size
  68     private final Object positionLock = new Object();
  69 
  70     private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
  71                             boolean writable, boolean append, Object parent)
  72     {
  73         this.fd = fd;
  74         this.readable = readable;
  75         this.writable = writable;
  76         this.append = append;
  77         this.parent = parent;
  78         this.path = path;
  79         this.nd = new FileDispatcherImpl(append);
  80     }
  81 
  82     // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
  83     public static FileChannel open(FileDescriptor fd, String path,
  84                                    boolean readable, boolean writable,
  85                                    Object parent)
  86     {
  87         return new FileChannelImpl(fd, path, readable, writable, false, parent);
  88     }
  89 
  90     // Used by FileOutputStream.getChannel
  91     public static FileChannel open(FileDescriptor fd, String path,
  92                                    boolean readable, boolean writable,
  93                                    boolean append, Object parent)
  94     {
  95         return new FileChannelImpl(fd, path, readable, writable, append, parent);
  96     }
  97 
  98     private void ensureOpen() throws IOException {
  99         if (!isOpen())
 100             throw new ClosedChannelException();
 101     }
 102 
 103 
 104     // -- Standard channel operations --
 105 
 106     protected void implCloseChannel() throws IOException {
 107         // Release and invalidate any locks that we still hold
 108         if (fileLockTable != null) {
 109             for (FileLock fl: fileLockTable.removeAll()) {
 110                 synchronized (fl) {
 111                     if (fl.isValid()) {
 112                         nd.release(fd, fl.position(), fl.size());
 113                         ((FileLockImpl)fl).invalidate();
 114                     }
 115                 }


 123 
 124             // Close the fd via the parent stream's close method.  The parent
 125             // will reinvoke our close method, which is defined in the
 126             // superclass AbstractInterruptibleChannel, but the isOpen logic in
 127             // that method will prevent this method from being reinvoked.
 128             //
 129             ((java.io.Closeable)parent).close();
 130         } else {
 131             nd.close(fd);
 132         }
 133 
 134     }
 135 
 136     public int read(ByteBuffer dst) throws IOException {
 137         ensureOpen();
 138         if (!readable)
 139             throw new NonReadableChannelException();
 140         synchronized (positionLock) {
 141             int n = 0;
 142             int ti = -1;
 143             IoTraceContext traceContext = IoTrace.fileReadBegin(path);
 144             try {
 145                 begin();
 146                 ti = threads.add();
 147                 if (!isOpen())
 148                     return 0;
 149                 do {
 150                     n = IOUtil.read(fd, dst, -1, nd, positionLock);
 151                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 152                 return IOStatus.normalize(n);
 153             } finally {
 154                 threads.remove(ti);
 155                 IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
 156                 end(n > 0);
 157                 assert IOStatus.check(n);
 158             }
 159         }
 160     }
 161 
 162     public long read(ByteBuffer[] dsts, int offset, int length)
 163         throws IOException
 164     {
 165         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
 166             throw new IndexOutOfBoundsException();
 167         ensureOpen();
 168         if (!readable)
 169             throw new NonReadableChannelException();
 170         synchronized (positionLock) {
 171             long n = 0;
 172             int ti = -1;
 173             IoTraceContext traceContext = IoTrace.fileReadBegin(path);
 174             try {
 175                 begin();
 176                 ti = threads.add();
 177                 if (!isOpen())
 178                     return 0;
 179                 do {
 180                     n = IOUtil.read(fd, dsts, offset, length, nd);
 181                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 182                 return IOStatus.normalize(n);
 183             } finally {
 184                 threads.remove(ti);
 185                 IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
 186                 end(n > 0);
 187                 assert IOStatus.check(n);
 188             }
 189         }
 190     }
 191 
 192     public int write(ByteBuffer src) throws IOException {
 193         ensureOpen();
 194         if (!writable)
 195             throw new NonWritableChannelException();
 196         synchronized (positionLock) {
 197             int n = 0;
 198             int ti = -1;
 199             IoTraceContext traceContext = IoTrace.fileWriteBegin(path);
 200             try {
 201                 begin();
 202                 ti = threads.add();
 203                 if (!isOpen())
 204                     return 0;
 205                 do {
 206                     n = IOUtil.write(fd, src, -1, nd, positionLock);
 207                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 208                 return IOStatus.normalize(n);
 209             } finally {
 210                 threads.remove(ti);
 211                 end(n > 0);
 212                 IoTrace.fileWriteEnd(traceContext, IOStatus.normalize(n));
 213                 assert IOStatus.check(n);
 214             }
 215         }
 216     }
 217 
 218     public long write(ByteBuffer[] srcs, int offset, int length)
 219         throws IOException
 220     {
 221         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
 222             throw new IndexOutOfBoundsException();
 223         ensureOpen();
 224         if (!writable)
 225             throw new NonWritableChannelException();
 226         synchronized (positionLock) {
 227             long n = 0;
 228             int ti = -1;
 229             IoTraceContext traceContext = IoTrace.fileWriteBegin(path);
 230             try {
 231                 begin();
 232                 ti = threads.add();
 233                 if (!isOpen())
 234                     return 0;
 235                 do {
 236                     n = IOUtil.write(fd, srcs, offset, length, nd);
 237                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
 238                 return IOStatus.normalize(n);
 239             } finally {
 240                 threads.remove(ti);
 241                 IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
 242                 end(n > 0);
 243                 assert IOStatus.check(n);
 244             }
 245         }
 246     }
 247 
 248     // -- Other operations --
 249 
 250     public long position() throws IOException {
 251         ensureOpen();
 252         synchronized (positionLock) {
 253             long p = -1;
 254             int ti = -1;
 255             try {
 256                 begin();
 257                 ti = threads.add();
 258                 if (!isOpen())
 259                     return 0;
 260                 do {
 261                     // in append-mode then position is advanced to end before writing


 670             throw new IllegalArgumentException();
 671         if (position > size())
 672             return 0;
 673         if (src instanceof FileChannelImpl)
 674            return transferFromFileChannel((FileChannelImpl)src,
 675                                           position, count);
 676 
 677         return transferFromArbitraryChannel(src, position, count);
 678     }
 679 
 680     public int read(ByteBuffer dst, long position) throws IOException {
 681         if (dst == null)
 682             throw new NullPointerException();
 683         if (position < 0)
 684             throw new IllegalArgumentException("Negative position");
 685         if (!readable)
 686             throw new NonReadableChannelException();
 687         ensureOpen();
 688         int n = 0;
 689         int ti = -1;
 690         IoTraceContext traceContext = IoTrace.fileReadBegin(path);
 691         try {
 692             begin();
 693             ti = threads.add();
 694             if (!isOpen())
 695                 return -1;
 696             do {
 697                 n = IOUtil.read(fd, dst, position, nd, positionLock);
 698             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 699             return IOStatus.normalize(n);
 700         } finally {
 701             threads.remove(ti);
 702             IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
 703             end(n > 0);
 704             assert IOStatus.check(n);
 705         }
 706     }
 707 
 708     public int write(ByteBuffer src, long position) throws IOException {
 709         if (src == null)
 710             throw new NullPointerException();
 711         if (position < 0)
 712             throw new IllegalArgumentException("Negative position");
 713         if (!writable)
 714             throw new NonWritableChannelException();
 715         ensureOpen();
 716         int n = 0;
 717         int ti = -1;
 718         IoTraceContext traceContext = IoTrace.fileWriteBegin(path);
 719         try {
 720             begin();
 721             ti = threads.add();
 722             if (!isOpen())
 723                 return -1;
 724             do {
 725                 n = IOUtil.write(fd, src, position, nd, positionLock);
 726             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 727             return IOStatus.normalize(n);
 728         } finally {
 729             threads.remove(ti);
 730             end(n > 0);
 731             IoTrace.fileWriteEnd(traceContext, IOStatus.normalize(n));
 732             assert IOStatus.check(n);
 733         }
 734     }
 735 
 736 
 737     // -- Memory-mapped buffers --
 738 
 739     private static class Unmapper
 740         implements Runnable
 741     {
 742         // may be required to close file
 743         private static final NativeDispatcher nd = new FileDispatcherImpl();
 744 
 745         // keep track of mapped buffer usage
 746         static volatile int count;
 747         static volatile long totalSize;
 748         static volatile long totalCapacity;
 749 
 750         private volatile long address;
 751         private final long size;