39 import java.nio.channels.NonWritableChannelException; |
39 import java.nio.channels.NonWritableChannelException; |
40 import java.nio.channels.OverlappingFileLockException; |
40 import java.nio.channels.OverlappingFileLockException; |
41 import java.nio.channels.ReadableByteChannel; |
41 import java.nio.channels.ReadableByteChannel; |
42 import java.nio.channels.SelectableChannel; |
42 import java.nio.channels.SelectableChannel; |
43 import java.nio.channels.WritableByteChannel; |
43 import java.nio.channels.WritableByteChannel; |
|
44 import java.nio.file.Files; |
|
45 import java.nio.file.FileStore; |
|
46 import java.nio.file.FileSystemException; |
|
47 import java.nio.file.Path; |
|
48 import java.nio.file.Paths; |
44 import java.util.ArrayList; |
49 import java.util.ArrayList; |
45 import java.util.List; |
50 import java.util.List; |
46 |
51 |
47 import jdk.internal.misc.JavaIOFileDescriptorAccess; |
52 import jdk.internal.misc.JavaIOFileDescriptorAccess; |
48 import jdk.internal.misc.JavaNioAccess; |
53 import jdk.internal.misc.JavaNioAccess; |
85 private final Object positionLock = new Object(); |
90 private final Object positionLock = new Object(); |
86 |
91 |
87 // Positional-read is not interruptible |
92 // Positional-read is not interruptible |
88 private volatile boolean uninterruptible; |
93 private volatile boolean uninterruptible; |
89 |
94 |
|
95 // DirectIO flag |
|
96 private final boolean direct; |
|
97 |
|
98 // IO alignment value for DirectIO |
|
99 private final int alignment; |
|
100 |
90 // Cleanable with an action which closes this channel's file descriptor |
101 // Cleanable with an action which closes this channel's file descriptor |
91 private final Cleanable closer; |
102 private final Cleanable closer; |
92 |
103 |
93 private static class Closer implements Runnable { |
104 private static class Closer implements Runnable { |
94 private final FileDescriptor fd; |
105 private final FileDescriptor fd; |
101 fdAccess.close(fd); |
112 fdAccess.close(fd); |
102 } |
113 } |
103 } |
114 } |
104 |
115 |
105 private FileChannelImpl(FileDescriptor fd, String path, boolean readable, |
116 private FileChannelImpl(FileDescriptor fd, String path, boolean readable, |
106 boolean writable, Object parent) |
117 boolean writable, boolean direct, Object parent) |
107 { |
118 { |
108 this.fd = fd; |
119 this.fd = fd; |
109 this.readable = readable; |
120 this.readable = readable; |
110 this.writable = writable; |
121 this.writable = writable; |
111 this.parent = parent; |
122 this.parent = parent; |
112 this.path = path; |
123 this.path = path; |
|
124 this.direct = direct; |
113 this.nd = new FileDispatcherImpl(); |
125 this.nd = new FileDispatcherImpl(); |
|
126 if (direct) { |
|
127 assert path != null; |
|
128 this.alignment = nd.setDirectIO(fd, path); |
|
129 } else { |
|
130 this.alignment = -1; |
|
131 } |
|
132 |
114 // Register a cleaning action if and only if there is no parent |
133 // Register a cleaning action if and only if there is no parent |
115 // as the parent will take care of closing the file descriptor. |
134 // as the parent will take care of closing the file descriptor. |
116 // FileChannel is used by the LambdaMetaFactory so a lambda cannot |
135 // FileChannel is used by the LambdaMetaFactory so a lambda cannot |
117 // be used here hence we use a nested class instead. |
136 // be used here hence we use a nested class instead. |
118 this.closer = parent != null ? null : |
137 this.closer = parent != null ? null : |
123 // and RandomAccessFile.getChannel() |
142 // and RandomAccessFile.getChannel() |
124 public static FileChannel open(FileDescriptor fd, String path, |
143 public static FileChannel open(FileDescriptor fd, String path, |
125 boolean readable, boolean writable, |
144 boolean readable, boolean writable, |
126 Object parent) |
145 Object parent) |
127 { |
146 { |
128 return new FileChannelImpl(fd, path, readable, writable, parent); |
147 return new FileChannelImpl(fd, path, readable, writable, false, parent); |
|
148 } |
|
149 |
|
150 public static FileChannel open(FileDescriptor fd, String path, |
|
151 boolean readable, boolean writable, |
|
152 boolean direct, Object parent) |
|
153 { |
|
154 return new FileChannelImpl(fd, path, readable, writable, direct, parent); |
129 } |
155 } |
130 |
156 |
131 private void ensureOpen() throws IOException { |
157 private void ensureOpen() throws IOException { |
132 if (!isOpen()) |
158 if (!isOpen()) |
133 throw new ClosedChannelException(); |
159 throw new ClosedChannelException(); |
179 public int read(ByteBuffer dst) throws IOException { |
205 public int read(ByteBuffer dst) throws IOException { |
180 ensureOpen(); |
206 ensureOpen(); |
181 if (!readable) |
207 if (!readable) |
182 throw new NonReadableChannelException(); |
208 throw new NonReadableChannelException(); |
183 synchronized (positionLock) { |
209 synchronized (positionLock) { |
|
210 if (direct) |
|
211 Util.checkChannelPositionAligned(position(), alignment); |
184 int n = 0; |
212 int n = 0; |
185 int ti = -1; |
213 int ti = -1; |
186 try { |
214 try { |
187 begin(); |
215 begin(); |
188 ti = threads.add(); |
216 ti = threads.add(); |
189 if (!isOpen()) |
217 if (!isOpen()) |
190 return 0; |
218 return 0; |
191 do { |
219 do { |
192 n = IOUtil.read(fd, dst, -1, nd); |
220 n = IOUtil.read(fd, dst, -1, direct, alignment, nd); |
193 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
221 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
194 return IOStatus.normalize(n); |
222 return IOStatus.normalize(n); |
195 } finally { |
223 } finally { |
196 threads.remove(ti); |
224 threads.remove(ti); |
197 end(n > 0); |
225 end(n > 0); |
207 throw new IndexOutOfBoundsException(); |
235 throw new IndexOutOfBoundsException(); |
208 ensureOpen(); |
236 ensureOpen(); |
209 if (!readable) |
237 if (!readable) |
210 throw new NonReadableChannelException(); |
238 throw new NonReadableChannelException(); |
211 synchronized (positionLock) { |
239 synchronized (positionLock) { |
|
240 if (direct) |
|
241 Util.checkChannelPositionAligned(position(), alignment); |
212 long n = 0; |
242 long n = 0; |
213 int ti = -1; |
243 int ti = -1; |
214 try { |
244 try { |
215 begin(); |
245 begin(); |
216 ti = threads.add(); |
246 ti = threads.add(); |
217 if (!isOpen()) |
247 if (!isOpen()) |
218 return 0; |
248 return 0; |
219 do { |
249 do { |
220 n = IOUtil.read(fd, dsts, offset, length, nd); |
250 n = IOUtil.read(fd, dsts, offset, length, |
|
251 direct, alignment, nd); |
221 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
252 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
222 return IOStatus.normalize(n); |
253 return IOStatus.normalize(n); |
223 } finally { |
254 } finally { |
224 threads.remove(ti); |
255 threads.remove(ti); |
225 end(n > 0); |
256 end(n > 0); |
231 public int write(ByteBuffer src) throws IOException { |
262 public int write(ByteBuffer src) throws IOException { |
232 ensureOpen(); |
263 ensureOpen(); |
233 if (!writable) |
264 if (!writable) |
234 throw new NonWritableChannelException(); |
265 throw new NonWritableChannelException(); |
235 synchronized (positionLock) { |
266 synchronized (positionLock) { |
|
267 if (direct) |
|
268 Util.checkChannelPositionAligned(position(), alignment); |
236 int n = 0; |
269 int n = 0; |
237 int ti = -1; |
270 int ti = -1; |
238 try { |
271 try { |
239 begin(); |
272 begin(); |
240 ti = threads.add(); |
273 ti = threads.add(); |
241 if (!isOpen()) |
274 if (!isOpen()) |
242 return 0; |
275 return 0; |
243 do { |
276 do { |
244 n = IOUtil.write(fd, src, -1, nd); |
277 n = IOUtil.write(fd, src, -1, direct, alignment, nd); |
245 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
278 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
246 return IOStatus.normalize(n); |
279 return IOStatus.normalize(n); |
247 } finally { |
280 } finally { |
248 threads.remove(ti); |
281 threads.remove(ti); |
249 end(n > 0); |
282 end(n > 0); |
259 throw new IndexOutOfBoundsException(); |
292 throw new IndexOutOfBoundsException(); |
260 ensureOpen(); |
293 ensureOpen(); |
261 if (!writable) |
294 if (!writable) |
262 throw new NonWritableChannelException(); |
295 throw new NonWritableChannelException(); |
263 synchronized (positionLock) { |
296 synchronized (positionLock) { |
|
297 if (direct) |
|
298 Util.checkChannelPositionAligned(position(), alignment); |
264 long n = 0; |
299 long n = 0; |
265 int ti = -1; |
300 int ti = -1; |
266 try { |
301 try { |
267 begin(); |
302 begin(); |
268 ti = threads.add(); |
303 ti = threads.add(); |
269 if (!isOpen()) |
304 if (!isOpen()) |
270 return 0; |
305 return 0; |
271 do { |
306 do { |
272 n = IOUtil.write(fd, srcs, offset, length, nd); |
307 n = IOUtil.write(fd, srcs, offset, length, |
|
308 direct, alignment, nd); |
273 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
309 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
274 return IOStatus.normalize(n); |
310 return IOStatus.normalize(n); |
275 } finally { |
311 } finally { |
276 threads.remove(ti); |
312 threads.remove(ti); |
277 end(n > 0); |
313 end(n > 0); |
750 throw new NullPointerException(); |
786 throw new NullPointerException(); |
751 if (position < 0) |
787 if (position < 0) |
752 throw new IllegalArgumentException("Negative position"); |
788 throw new IllegalArgumentException("Negative position"); |
753 if (!readable) |
789 if (!readable) |
754 throw new NonReadableChannelException(); |
790 throw new NonReadableChannelException(); |
|
791 if (direct) |
|
792 Util.checkChannelPositionAligned(position, alignment); |
755 ensureOpen(); |
793 ensureOpen(); |
756 if (nd.needsPositionLock()) { |
794 if (nd.needsPositionLock()) { |
757 synchronized (positionLock) { |
795 synchronized (positionLock) { |
758 return readInternal(dst, position); |
796 return readInternal(dst, position); |
759 } |
797 } |
772 if (interruptible) begin(); |
810 if (interruptible) begin(); |
773 ti = threads.add(); |
811 ti = threads.add(); |
774 if (!isOpen()) |
812 if (!isOpen()) |
775 return -1; |
813 return -1; |
776 do { |
814 do { |
777 n = IOUtil.read(fd, dst, position, nd); |
815 n = IOUtil.read(fd, dst, position, direct, alignment, nd); |
778 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
816 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
779 return IOStatus.normalize(n); |
817 return IOStatus.normalize(n); |
780 } finally { |
818 } finally { |
781 threads.remove(ti); |
819 threads.remove(ti); |
782 if (interruptible) end(n > 0); |
820 if (interruptible) end(n > 0); |
789 throw new NullPointerException(); |
827 throw new NullPointerException(); |
790 if (position < 0) |
828 if (position < 0) |
791 throw new IllegalArgumentException("Negative position"); |
829 throw new IllegalArgumentException("Negative position"); |
792 if (!writable) |
830 if (!writable) |
793 throw new NonWritableChannelException(); |
831 throw new NonWritableChannelException(); |
|
832 if (direct) |
|
833 Util.checkChannelPositionAligned(position, alignment); |
794 ensureOpen(); |
834 ensureOpen(); |
795 if (nd.needsPositionLock()) { |
835 if (nd.needsPositionLock()) { |
796 synchronized (positionLock) { |
836 synchronized (positionLock) { |
797 return writeInternal(src, position); |
837 return writeInternal(src, position); |
798 } |
838 } |
809 begin(); |
849 begin(); |
810 ti = threads.add(); |
850 ti = threads.add(); |
811 if (!isOpen()) |
851 if (!isOpen()) |
812 return -1; |
852 return -1; |
813 do { |
853 do { |
814 n = IOUtil.write(fd, src, position, nd); |
854 n = IOUtil.write(fd, src, position, direct, alignment, nd); |
815 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
855 } while ((n == IOStatus.INTERRUPTED) && isOpen()); |
816 return IOStatus.normalize(n); |
856 return IOStatus.normalize(n); |
817 } finally { |
857 } finally { |
818 threads.remove(ti); |
858 threads.remove(ti); |
819 end(n > 0); |
859 end(n > 0); |