| author | alanb |
| Wed Apr 06 20:51:55 2011 +0100 (13 months ago) | |
| changeset 3990 | cd86fbf11e33 |
| parent 3261 | a06412e13bf7 |
| permissions | -rw-r--r-- |
1 /*
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
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
32
33 /**
34 * File-descriptor based I/O utilities that are shared by NIO classes.
35 */
36
37 class IOUtil {
38
39 private IOUtil() { } // No instantiation
40
41 static int write(FileDescriptor fd, ByteBuffer src, long position,
42 NativeDispatcher nd, Object lock)
43 throws IOException
44 {
45 if (src instanceof DirectBuffer)
46 return writeFromNativeBuffer(fd, src, position, nd, lock);
47
48 // Substitute a native buffer
49 int pos = src.position();
50 int lim = src.limit();
51 assert (pos <= lim);
52 int rem = (pos <= lim ? lim - pos : 0);
53 ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
54 try {
55 bb.put(src);
56 bb.flip();
57 // Do not update src until we see how many bytes were written
58 src.position(pos);
59
60 int n = writeFromNativeBuffer(fd, bb, position, nd, lock);
61 if (n > 0) {
62 // now update src
63 src.position(pos + n);
64 }
65 return n;
66 } finally {
67 Util.offerFirstTemporaryDirectBuffer(bb);
68 }
69 }
70
71 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
72 long position, NativeDispatcher nd,
73 Object lock)
74 throws IOException
75 {
76 int pos = bb.position();
77 int lim = bb.limit();
78 assert (pos <= lim);
79 int rem = (pos <= lim ? lim - pos : 0);
80
81 int written = 0;
82 if (rem == 0)
83 return 0;
84 if (position != -1) {
85 written = nd.pwrite(fd,
86 ((DirectBuffer)bb).address() + pos,
87 rem, position, lock);
88 } else {
89 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
90 }
91 if (written > 0)
92 bb.position(pos + written);
93 return written;
94 }
95
96 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
97 throws IOException
98 {
99 return write(fd, bufs, 0, bufs.length, nd);
100 }
101
102 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
103 NativeDispatcher nd)
104 throws IOException
105 {
106 IOVecWrapper vec = IOVecWrapper.get(length);
107
108 boolean completed = false;
109 int iov_len = 0;
110 try {
111
112 // Iterate over buffers to populate native iovec array.
113 int count = offset + length;
114 for (int i=offset; i<count; i++) {
115 ByteBuffer buf = bufs[i];
116 int pos = buf.position();
117 int lim = buf.limit();
118 assert (pos <= lim);
119 int rem = (pos <= lim ? lim - pos : 0);
120 if (rem > 0) {
121 vec.setBuffer(iov_len, buf, pos, rem);
122
123 // allocate shadow buffer to ensure I/O is done with direct buffer
124 if (!(buf instanceof DirectBuffer)) {
125 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
126 shadow.put(buf);
127 shadow.flip();
128 vec.setShadow(iov_len, shadow);
129 buf.position(pos); // temporarily restore position in user buffer
130 buf = shadow;
131 pos = shadow.position();
132 }
133
134 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
135 vec.putLen(iov_len, rem);
136 iov_len++;
137 }
138 }
139 if (iov_len == 0)
140 return 0L;
141
142 long bytesWritten = nd.writev(fd, vec.address, iov_len);
143
144 // Notify the buffers how many bytes were taken
145 long left = bytesWritten;
146 for (int j=0; j<iov_len; j++) {
147 if (left > 0) {
148 ByteBuffer buf = vec.getBuffer(j);
149 int pos = vec.getPosition(j);
150 int rem = vec.getRemaining(j);
151 int n = (left > rem) ? rem : (int)left;
152 buf.position(pos + n);
153 left -= n;
154 }
155 // return shadow buffers to buffer pool
156 ByteBuffer shadow = vec.getShadow(j);
157 if (shadow != null)
158 Util.offerLastTemporaryDirectBuffer(shadow);
159 vec.clearRefs(j);
160 }
161
162 completed = true;
163 return bytesWritten;
164
165 } finally {
166 // if an error occurred then clear refs to buffers and return any shadow
167 // buffers to cache
168 if (!completed) {
169 for (int j=0; j<iov_len; j++) {
170 ByteBuffer shadow = vec.getShadow(j);
171 if (shadow != null)
172 Util.offerLastTemporaryDirectBuffer(shadow);
173 vec.clearRefs(j);
174 }
175 }
176 }
177 }
178
179 static int read(FileDescriptor fd, ByteBuffer dst, long position,
180 NativeDispatcher nd, Object lock)
181 throws IOException
182 {
183 if (dst.isReadOnly())
184 throw new IllegalArgumentException("Read-only buffer");
185 if (dst instanceof DirectBuffer)
186 return readIntoNativeBuffer(fd, dst, position, nd, lock);
187
188 // Substitute a native buffer
189 ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
190 try {
191 int n = readIntoNativeBuffer(fd, bb, position, nd, lock);
192 bb.flip();
193 if (n > 0)
194 dst.put(bb);
195 return n;
196 } finally {
197 Util.offerFirstTemporaryDirectBuffer(bb);
198 }
199 }
200
201 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
202 long position, NativeDispatcher nd,
203 Object lock)
204 throws IOException
205 {
206 int pos = bb.position();
207 int lim = bb.limit();
208 assert (pos <= lim);
209 int rem = (pos <= lim ? lim - pos : 0);
210
211 if (rem == 0)
212 return 0;
213 int n = 0;
214 if (position != -1) {
215 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
216 rem, position, lock);
217 } else {
218 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
219 }
220 if (n > 0)
221 bb.position(pos + n);
222 return n;
223 }
224
225 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
226 throws IOException
227 {
228 return read(fd, bufs, 0, bufs.length, nd);
229 }
230
231 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
232 NativeDispatcher nd)
233 throws IOException
234 {
235 IOVecWrapper vec = IOVecWrapper.get(length);
236
237 boolean completed = false;
238 int iov_len = 0;
239 try {
240
241 // Iterate over buffers to populate native iovec array.
242 int count = offset + length;
243 for (int i=offset; i<count; i++) {
244 ByteBuffer buf = bufs[i];
245 if (buf.isReadOnly())
246 throw new IllegalArgumentException("Read-only buffer");
247 int pos = buf.position();
248 int lim = buf.limit();
249 assert (pos <= lim);
250 int rem = (pos <= lim ? lim - pos : 0);
251
252 if (rem > 0) {
253 vec.setBuffer(iov_len, buf, pos, rem);
254
255 // allocate shadow buffer to ensure I/O is done with direct buffer
256 if (!(buf instanceof DirectBuffer)) {
257 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
258 vec.setShadow(iov_len, shadow);
259 buf = shadow;
260 pos = shadow.position();
261 }
262
263 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
264 vec.putLen(iov_len, rem);
265 iov_len++;
266 }
267 }
268 if (iov_len == 0)
269 return 0L;
270
271 long bytesRead = nd.readv(fd, vec.address, iov_len);
272
273 // Notify the buffers how many bytes were read
274 long left = bytesRead;
275 for (int j=0; j<iov_len; j++) {
276 ByteBuffer shadow = vec.getShadow(j);
277 if (left > 0) {
278 ByteBuffer buf = vec.getBuffer(j);
279 int rem = vec.getRemaining(j);
280 int n = (left > rem) ? rem : (int)left;
281 if (shadow == null) {
282 int pos = vec.getPosition(j);
283 buf.position(pos + n);
284 } else {
285 shadow.limit(shadow.position() + n);
286 buf.put(shadow);
287 }
288 left -= n;
289 }
290 if (shadow != null)
291 Util.offerLastTemporaryDirectBuffer(shadow);
292 vec.clearRefs(j);
293 }
294
295 completed = true;
296 return bytesRead;
297
298 } finally {
299 // if an error occurred then clear refs to buffers and return any shadow
300 // buffers to cache
301 if (!completed) {
302 for (int j=0; j<iov_len; j++) {
303 ByteBuffer shadow = vec.getShadow(j);
304 if (shadow != null)
305 Util.offerLastTemporaryDirectBuffer(shadow);
306 vec.clearRefs(j);
307 }
308 }
309 }
310 }
311
312 static FileDescriptor newFD(int i) {
313 FileDescriptor fd = new FileDescriptor();
314 setfdVal(fd, i);
315 return fd;
316 }
317
318 static native boolean randomBytes(byte[] someBytes);
319
320 /**
321 * Returns two file descriptors for a pipe encoded in a long.
322 * The read end of the pipe is returned in the high 32 bits,
323 * while the write end is returned in the low 32 bits.
324 */
325 static native long makePipe(boolean blocking);
326
327 static native boolean drain(int fd) throws IOException;
328
329 static native void configureBlocking(FileDescriptor fd, boolean blocking)
330 throws IOException;
331
332 static native int fdVal(FileDescriptor fd);
333
334 static native void setfdVal(FileDescriptor fd, int value);
335
336 static native void initIDs();
337
338 static {
339 // Note that IOUtil.initIDs is called from within Util.load.
340 Util.load();
341 }
342
343 }