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;
|