1 /*
2 * Copyright (c) 2000, 2013, 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
30 import java.nio.ByteBuffer;
31
32
33 /**
34 * File-descriptor based I/O utilities that are shared by NIO classes.
35 */
36
37 public class IOUtil {
38
39 /**
40 * Max number of iovec structures that readv/writev supports
41 */
42 static final int IOV_MAX;
43
44 private IOUtil() { } // No instantiation
45
46 static int write(FileDescriptor fd, ByteBuffer src, long position,
47 NativeDispatcher nd)
48 throws IOException
49 {
50 if (src instanceof DirectBuffer)
51 return writeFromNativeBuffer(fd, src, position, nd);
52
53 // Substitute a native buffer
54 int pos = src.position();
55 int lim = src.limit();
56 assert (pos <= lim);
57 int rem = (pos <= lim ? lim - pos : 0);
58 ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
59 try {
60 bb.put(src);
61 bb.flip();
62 // Do not update src until we see how many bytes were written
63 src.position(pos);
64
65 int n = writeFromNativeBuffer(fd, bb, position, nd);
66 if (n > 0) {
67 // now update src
68 src.position(pos + n);
69 }
70 return n;
71 } finally {
72 Util.offerFirstTemporaryDirectBuffer(bb);
73 }
74 }
75
76 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
77 long position, NativeDispatcher nd)
78 throws IOException
79 {
80 int pos = bb.position();
81 int lim = bb.limit();
82 assert (pos <= lim);
83 int rem = (pos <= lim ? lim - pos : 0);
84
85 int written = 0;
86 if (rem == 0)
87 return 0;
88 if (position != -1) {
89 written = nd.pwrite(fd,
90 ((DirectBuffer)bb).address() + pos,
91 rem, position);
92 } else {
93 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
94 }
95 if (written > 0)
96 bb.position(pos + written);
97 return written;
98 }
99
100 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
101 throws IOException
102 {
103 return write(fd, bufs, 0, bufs.length, nd);
104 }
105
106 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
107 NativeDispatcher nd)
108 throws IOException
109 {
110 IOVecWrapper vec = IOVecWrapper.get(length);
111
112 boolean completed = false;
113 int iov_len = 0;
114 try {
115
116 // Iterate over buffers to populate native iovec array.
117 int count = offset + length;
118 int i = offset;
119 while (i < count && iov_len < IOV_MAX) {
120 ByteBuffer buf = bufs[i];
121 int pos = buf.position();
122 int lim = buf.limit();
123 assert (pos <= lim);
124 int rem = (pos <= lim ? lim - pos : 0);
125 if (rem > 0) {
126 vec.setBuffer(iov_len, buf, pos, rem);
127
128 // allocate shadow buffer to ensure I/O is done with direct buffer
129 if (!(buf instanceof DirectBuffer)) {
130 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
131 shadow.put(buf);
132 shadow.flip();
133 vec.setShadow(iov_len, shadow);
134 buf.position(pos); // temporarily restore position in user buffer
135 buf = shadow;
136 pos = shadow.position();
137 }
138
139 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
140 vec.putLen(iov_len, rem);
141 iov_len++;
142 }
143 i++;
144 }
145 if (iov_len == 0)
146 return 0L;
147
148 long bytesWritten = nd.writev(fd, vec.address, iov_len);
149
150 // Notify the buffers how many bytes were taken
169 return bytesWritten;
170
171 } finally {
172 // if an error occurred then clear refs to buffers and return any shadow
173 // buffers to cache
174 if (!completed) {
175 for (int j=0; j<iov_len; j++) {
176 ByteBuffer shadow = vec.getShadow(j);
177 if (shadow != null)
178 Util.offerLastTemporaryDirectBuffer(shadow);
179 vec.clearRefs(j);
180 }
181 }
182 }
183 }
184
185 static int read(FileDescriptor fd, ByteBuffer dst, long position,
186 NativeDispatcher nd)
187 throws IOException
188 {
189 if (dst.isReadOnly())
190 throw new IllegalArgumentException("Read-only buffer");
191 if (dst instanceof DirectBuffer)
192 return readIntoNativeBuffer(fd, dst, position, nd);
193
194 // Substitute a native buffer
195 ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
196 try {
197 int n = readIntoNativeBuffer(fd, bb, position, nd);
198 bb.flip();
199 if (n > 0)
200 dst.put(bb);
201 return n;
202 } finally {
203 Util.offerFirstTemporaryDirectBuffer(bb);
204 }
205 }
206
207 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
208 long position, NativeDispatcher nd)
209 throws IOException
210 {
211 int pos = bb.position();
212 int lim = bb.limit();
213 assert (pos <= lim);
214 int rem = (pos <= lim ? lim - pos : 0);
215
216 if (rem == 0)
217 return 0;
218 int n = 0;
219 if (position != -1) {
220 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
221 rem, position);
222 } else {
223 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
224 }
225 if (n > 0)
226 bb.position(pos + n);
227 return n;
228 }
229
230 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
231 throws IOException
232 {
233 return read(fd, bufs, 0, bufs.length, nd);
234 }
235
236 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
237 NativeDispatcher nd)
238 throws IOException
239 {
240 IOVecWrapper vec = IOVecWrapper.get(length);
241
242 boolean completed = false;
243 int iov_len = 0;
244 try {
245
246 // Iterate over buffers to populate native iovec array.
247 int count = offset + length;
248 int i = offset;
249 while (i < count && iov_len < IOV_MAX) {
250 ByteBuffer buf = bufs[i];
251 if (buf.isReadOnly())
252 throw new IllegalArgumentException("Read-only buffer");
253 int pos = buf.position();
254 int lim = buf.limit();
255 assert (pos <= lim);
256 int rem = (pos <= lim ? lim - pos : 0);
257
258 if (rem > 0) {
259 vec.setBuffer(iov_len, buf, pos, rem);
260
261 // allocate shadow buffer to ensure I/O is done with direct buffer
262 if (!(buf instanceof DirectBuffer)) {
263 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
264 vec.setShadow(iov_len, shadow);
265 buf = shadow;
266 pos = shadow.position();
267 }
268
269 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
270 vec.putLen(iov_len, rem);
271 iov_len++;
272 }
273 i++;
274 }
275 if (iov_len == 0)
276 return 0L;
277
278 long bytesRead = nd.readv(fd, vec.address, iov_len);
279
280 // Notify the buffers how many bytes were read
281 long left = bytesRead;
282 for (int j=0; j<iov_len; j++) {
283 ByteBuffer shadow = vec.getShadow(j);
|
1 /*
2 * Copyright (c) 2000, 2017, 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
30 import java.nio.ByteBuffer;
31
32
33 /**
34 * File-descriptor based I/O utilities that are shared by NIO classes.
35 */
36
37 public class IOUtil {
38
39 /**
40 * Max number of iovec structures that readv/writev supports
41 */
42 static final int IOV_MAX;
43
44 private IOUtil() { } // No instantiation
45
46 static int write(FileDescriptor fd, ByteBuffer src, long position,
47 NativeDispatcher nd)
48 throws IOException
49 {
50 return write(fd, src, position, false, -1, nd);
51 }
52
53 static int write(FileDescriptor fd, ByteBuffer src, long position,
54 boolean directIO, int alignment, NativeDispatcher nd)
55 throws IOException
56 {
57 if (src instanceof DirectBuffer) {
58 return writeFromNativeBuffer(fd, src, position,
59 directIO, alignment, nd);
60 }
61
62 // Substitute a native buffer
63 int pos = src.position();
64 int lim = src.limit();
65 assert (pos <= lim);
66 int rem = (pos <= lim ? lim - pos : 0);
67 ByteBuffer bb;
68 if (directIO) {
69 Util.checkRemainingBufferSizeAligned(rem, alignment);
70 bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
71 } else {
72 bb = Util.getTemporaryDirectBuffer(rem);
73 }
74 try {
75 bb.put(src);
76 bb.flip();
77 // Do not update src until we see how many bytes were written
78 src.position(pos);
79
80 int n = writeFromNativeBuffer(fd, bb, position,
81 directIO, alignment, nd);
82 if (n > 0) {
83 // now update src
84 src.position(pos + n);
85 }
86 return n;
87 } finally {
88 Util.offerFirstTemporaryDirectBuffer(bb);
89 }
90 }
91
92 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
93 long position, boolean directIO,
94 int alignment, NativeDispatcher nd)
95 throws IOException
96 {
97 int pos = bb.position();
98 int lim = bb.limit();
99 assert (pos <= lim);
100 int rem = (pos <= lim ? lim - pos : 0);
101
102 if (directIO) {
103 Util.checkBufferPositionAligned(bb, pos, alignment);
104 Util.checkRemainingBufferSizeAligned(rem, alignment);
105 }
106
107 int written = 0;
108 if (rem == 0)
109 return 0;
110 if (position != -1) {
111 written = nd.pwrite(fd,
112 ((DirectBuffer)bb).address() + pos,
113 rem, position);
114 } else {
115 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
116 }
117 if (written > 0)
118 bb.position(pos + written);
119 return written;
120 }
121
122 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
123 throws IOException
124 {
125 return write(fd, bufs, 0, bufs.length, false, -1, nd);
126 }
127
128 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
129 NativeDispatcher nd)
130 throws IOException
131 {
132 return write(fd, bufs, offset, length, false, -1, nd);
133 }
134
135 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
136 boolean directIO, int alignment, NativeDispatcher nd)
137 throws IOException
138 {
139 IOVecWrapper vec = IOVecWrapper.get(length);
140
141 boolean completed = false;
142 int iov_len = 0;
143 try {
144
145 // Iterate over buffers to populate native iovec array.
146 int count = offset + length;
147 int i = offset;
148 while (i < count && iov_len < IOV_MAX) {
149 ByteBuffer buf = bufs[i];
150 int pos = buf.position();
151 int lim = buf.limit();
152 assert (pos <= lim);
153 int rem = (pos <= lim ? lim - pos : 0);
154 if (directIO)
155 Util.checkRemainingBufferSizeAligned(rem, alignment);
156
157 if (rem > 0) {
158 vec.setBuffer(iov_len, buf, pos, rem);
159
160 // allocate shadow buffer to ensure I/O is done with direct buffer
161 if (!(buf instanceof DirectBuffer)) {
162 ByteBuffer shadow;
163 if (directIO)
164 shadow = Util.getTemporaryAlignedDirectBuffer(rem,
165 alignment);
166 else
167 shadow = Util.getTemporaryDirectBuffer(rem);
168 shadow.put(buf);
169 shadow.flip();
170 vec.setShadow(iov_len, shadow);
171 buf.position(pos); // temporarily restore position in user buffer
172 buf = shadow;
173 pos = shadow.position();
174 }
175
176 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
177 vec.putLen(iov_len, rem);
178 iov_len++;
179 }
180 i++;
181 }
182 if (iov_len == 0)
183 return 0L;
184
185 long bytesWritten = nd.writev(fd, vec.address, iov_len);
186
187 // Notify the buffers how many bytes were taken
206 return bytesWritten;
207
208 } finally {
209 // if an error occurred then clear refs to buffers and return any shadow
210 // buffers to cache
211 if (!completed) {
212 for (int j=0; j<iov_len; j++) {
213 ByteBuffer shadow = vec.getShadow(j);
214 if (shadow != null)
215 Util.offerLastTemporaryDirectBuffer(shadow);
216 vec.clearRefs(j);
217 }
218 }
219 }
220 }
221
222 static int read(FileDescriptor fd, ByteBuffer dst, long position,
223 NativeDispatcher nd)
224 throws IOException
225 {
226 return read(fd, dst, position, false, -1, nd);
227 }
228
229 static int read(FileDescriptor fd, ByteBuffer dst, long position,
230 boolean directIO, int alignment, NativeDispatcher nd)
231 throws IOException
232 {
233 if (dst.isReadOnly())
234 throw new IllegalArgumentException("Read-only buffer");
235 if (dst instanceof DirectBuffer)
236 return readIntoNativeBuffer(fd, dst, position,
237 directIO, alignment, nd);
238
239 // Substitute a native buffer
240 ByteBuffer bb;
241 int rem = dst.remaining();
242 if (directIO) {
243 Util.checkRemainingBufferSizeAligned(rem, alignment);
244 bb = Util.getTemporaryAlignedDirectBuffer(rem,
245 alignment);
246 } else {
247 bb = Util.getTemporaryDirectBuffer(rem);
248 }
249 try {
250 int n = readIntoNativeBuffer(fd, bb, position,
251 directIO, alignment,nd);
252 bb.flip();
253 if (n > 0)
254 dst.put(bb);
255 return n;
256 } finally {
257 Util.offerFirstTemporaryDirectBuffer(bb);
258 }
259 }
260
261 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
262 long position, boolean directIO,
263 int alignment, NativeDispatcher nd)
264 throws IOException
265 {
266 int pos = bb.position();
267 int lim = bb.limit();
268 assert (pos <= lim);
269 int rem = (pos <= lim ? lim - pos : 0);
270
271 if (directIO) {
272 Util.checkBufferPositionAligned(bb, pos, alignment);
273 Util.checkRemainingBufferSizeAligned(rem, alignment);
274 }
275
276 if (rem == 0)
277 return 0;
278 int n = 0;
279 if (position != -1) {
280 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
281 rem, position);
282 } else {
283 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
284 }
285 if (n > 0)
286 bb.position(pos + n);
287 return n;
288 }
289
290 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
291 throws IOException
292 {
293 return read(fd, bufs, 0, bufs.length, false, -1, nd);
294 }
295
296 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
297 NativeDispatcher nd)
298 throws IOException
299 {
300 return read(fd, bufs, offset, bufs.length, false, -1, nd);
301 }
302
303 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
304 boolean directIO, int alignment, NativeDispatcher nd)
305 throws IOException
306 {
307 IOVecWrapper vec = IOVecWrapper.get(length);
308
309 boolean completed = false;
310 int iov_len = 0;
311 try {
312
313 // Iterate over buffers to populate native iovec array.
314 int count = offset + length;
315 int i = offset;
316 while (i < count && iov_len < IOV_MAX) {
317 ByteBuffer buf = bufs[i];
318 if (buf.isReadOnly())
319 throw new IllegalArgumentException("Read-only buffer");
320 int pos = buf.position();
321 int lim = buf.limit();
322 assert (pos <= lim);
323 int rem = (pos <= lim ? lim - pos : 0);
324
325 if (directIO)
326 Util.checkRemainingBufferSizeAligned(rem, alignment);
327
328 if (rem > 0) {
329 vec.setBuffer(iov_len, buf, pos, rem);
330
331 // allocate shadow buffer to ensure I/O is done with direct buffer
332 if (!(buf instanceof DirectBuffer)) {
333 ByteBuffer shadow;
334 if (directIO) {
335 shadow = Util.getTemporaryAlignedDirectBuffer(rem,
336 alignment);
337 } else {
338 shadow = Util.getTemporaryDirectBuffer(rem);
339 }
340 vec.setShadow(iov_len, shadow);
341 buf = shadow;
342 pos = shadow.position();
343 }
344
345 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
346 vec.putLen(iov_len, rem);
347 iov_len++;
348 }
349 i++;
350 }
351 if (iov_len == 0)
352 return 0L;
353
354 long bytesRead = nd.readv(fd, vec.address, iov_len);
355
356 // Notify the buffers how many bytes were read
357 long left = bytesRead;
358 for (int j=0; j<iov_len; j++) {
359 ByteBuffer shadow = vec.getShadow(j);
|