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

Print this page
rev 6052 : [mq]: jdk.patch


  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
 248                     p = (append) ? nd.size(fd) : position0(fd, -1);


 648             throw new IllegalArgumentException();
 649         if (position > size())
 650             return 0;
 651         if (src instanceof FileChannelImpl)
 652            return transferFromFileChannel((FileChannelImpl)src,
 653                                           position, count);
 654 
 655         return transferFromArbitraryChannel(src, position, count);
 656     }
 657 
 658     public int read(ByteBuffer dst, long position) throws IOException {
 659         if (dst == null)
 660             throw new NullPointerException();
 661         if (position < 0)
 662             throw new IllegalArgumentException("Negative position");
 663         if (!readable)
 664             throw new NonReadableChannelException();
 665         ensureOpen();
 666         int n = 0;
 667         int ti = -1;

 668         try {
 669             begin();
 670             ti = threads.add();
 671             if (!isOpen())
 672                 return -1;
 673             do {
 674                 n = IOUtil.read(fd, dst, position, nd, positionLock);
 675             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 676             return IOStatus.normalize(n);
 677         } finally {
 678             threads.remove(ti);
 679             end(n > 0);

 680             assert IOStatus.check(n);
 681         }
 682     }
 683 
 684     public int write(ByteBuffer src, long position) throws IOException {
 685         if (src == null)
 686             throw new NullPointerException();
 687         if (position < 0)
 688             throw new IllegalArgumentException("Negative position");
 689         if (!writable)
 690             throw new NonWritableChannelException();
 691         ensureOpen();
 692         int n = 0;
 693         int ti = -1;

 694         try {
 695             begin();
 696             ti = threads.add();
 697             if (!isOpen())
 698                 return -1;
 699             do {
 700                 n = IOUtil.write(fd, src, position, nd, positionLock);
 701             } while ((n == IOStatus.INTERRUPTED) && isOpen());
 702             return IOStatus.normalize(n);
 703         } finally {
 704             threads.remove(ti);
 705             end(n > 0);

 706             assert IOStatus.check(n);
 707         }
 708     }
 709 
 710 
 711     // -- Memory-mapped buffers --
 712 
 713     private static class Unmapper
 714         implements Runnable
 715     {
 716         // may be required to close file
 717         private static final NativeDispatcher nd = new FileDispatcherImpl();
 718 
 719         // keep track of mapped buffer usage
 720         static volatile int count;
 721         static volatile long totalSize;
 722         static volatile long totalCapacity;
 723 
 724         private volatile long address;
 725         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.security.action.GetPropertyAction;
  39 
  40 public class FileChannelImpl
  41     extends FileChannel
  42 {
  43     // Memory allocation size for mapping buffers
  44     private static final long allocationGranularity;
  45 
  46     // Used to make native read and write calls
  47     private final FileDispatcher nd;
  48 
  49     // File descriptor
  50     private final FileDescriptor fd;
  51 
  52     // File access mode (immutable)
  53     private final boolean writable;
  54     private final boolean readable;
  55     private final boolean append;
  56 
  57     // Required to prevent finalization of creating stream (immutable)
  58     private final Object parent;
  59 
  60     // The path of the referenced file (null if there is no file)
  61     private final String path;
  62 
  63     // Thread-safe set of IDs of native threads, for signalling
  64     private final NativeThreadSet threads = new NativeThreadSet(2);
  65 
  66     // Lock for operations involving position and size
  67     private final Object positionLock = new Object();
  68 
  69     private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
  70                             boolean writable, boolean append, Object parent)
  71     {
  72         this.fd = fd;
  73         this.readable = readable;
  74         this.writable = writable;
  75         this.append = append;
  76         this.parent = parent;
  77         this.path = path;
  78         this.nd = new FileDispatcherImpl(append);
  79     }
  80 
  81     // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()
  82     public static FileChannel open(FileDescriptor fd, String path,
  83                                    boolean readable, boolean writable,
  84                                    Object parent)
  85     {
  86         return new FileChannelImpl(fd, path, readable, writable, false, parent);
  87     }
  88 
  89     // Used by FileOutputStream.getChannel
  90     public static FileChannel open(FileDescriptor fd, String path,
  91                                    boolean readable, boolean writable,
  92                                    boolean append, Object parent)
  93     {
  94         return new FileChannelImpl(fd, path, readable, writable, append, parent);
  95     }
  96 
  97     private void ensureOpen() throws IOException {
  98         if (!isOpen())
  99             throw new ClosedChannelException();
 100     }
 101 
 102 
 103     // -- Standard channel operations --
 104 
 105     protected void implCloseChannel() throws IOException {
 106         // Release and invalidate any locks that we still hold
 107         if (fileLockTable != null) {
 108             for (FileLock fl: fileLockTable.removeAll()) {
 109                 synchronized (fl) {
 110                     if (fl.isValid()) {
 111                         nd.release(fd, fl.position(), fl.size());
 112                         ((FileLockImpl)fl).invalidate();
 113                     }
 114                 }


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


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