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