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 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);
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;
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
151 long left = bytesWritten;
152 for (int j=0; j<iov_len; j++) {
153 if (left > 0) {
154 ByteBuffer buf = vec.getBuffer(j);
155 int pos = vec.getPosition(j);
156 int rem = vec.getRemaining(j);
157 int n = (left > rem) ? rem : (int)left;
158 buf.position(pos + n);
159 left -= n;
160 }
161 // return shadow buffers to buffer pool
162 ByteBuffer shadow = vec.getShadow(j);
163 if (shadow != null)
164 Util.offerLastTemporaryDirectBuffer(shadow);
165 vec.clearRefs(j);
166 }
167
168 completed = true;
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;
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);
284 if (left > 0) {
285 ByteBuffer buf = vec.getBuffer(j);
286 int rem = vec.getRemaining(j);
287 int n = (left > rem) ? rem : (int)left;
288 if (shadow == null) {
289 int pos = vec.getPosition(j);
290 buf.position(pos + n);
291 } else {
292 shadow.limit(shadow.position() + n);
293 buf.put(shadow);
294 }
295 left -= n;
296 }
297 if (shadow != null)
298 Util.offerLastTemporaryDirectBuffer(shadow);
|
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 import jdk.internal.misc.JavaIOFileDescriptorAccess;
33 import jdk.internal.misc.JavaNioAccess;
34 import jdk.internal.misc.SharedSecrets;
35 import jdk.internal.ref.Cleaner;
36 import sun.security.action.GetPropertyAction;
37
38 /**
39 * File-descriptor based I/O utilities that are shared by NIO classes.
40 */
41
42 public class IOUtil {
43
44 /**
45 * Max number of iovec structures that readv/writev supports
46 */
47 static final int IOV_MAX;
48
49 private static final JavaIOFileDescriptorAccess fdAccess =
50 SharedSecrets.getJavaIOFileDescriptorAccess();
51
52 private IOUtil() { } // No instantiation
53
54 static int write(FileDescriptor fd, ByteBuffer src, long position,
55 NativeDispatcher nd)
56 throws IOException
57 {
58 if (src instanceof DirectBuffer)
59 return writeFromNativeBuffer(fd, src, position, nd);
60
61 // Substitute a native buffer
62 int pos = src.position();
63 int lim = src.limit();
64 assert (pos <= lim);
65 int rem = (pos <= lim ? lim - pos : 0);
66 ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
67 try {
68 bb.put(src);
69 bb.flip();
70 // Do not update src until we see how many bytes were written
71 src.position(pos);
77 }
78 return n;
79 } finally {
80 Util.offerFirstTemporaryDirectBuffer(bb);
81 }
82 }
83
84 private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
85 long position, NativeDispatcher nd)
86 throws IOException
87 {
88 int pos = bb.position();
89 int lim = bb.limit();
90 assert (pos <= lim);
91 int rem = (pos <= lim ? lim - pos : 0);
92
93 int written = 0;
94 if (rem == 0)
95 return 0;
96 if (position != -1) {
97 if (fdAccess.getDirect(fd))
98 written = nd.pwriteDirect(fd,
99 ((DirectBuffer)bb).address() + pos,
100 rem, position);
101 else
102 written = nd.pwrite(fd,
103 ((DirectBuffer)bb).address() + pos,
104 rem, position);
105 } else {
106 if (fdAccess.getDirect(fd))
107 written = nd.writeDirect(fd, ((DirectBuffer)bb).address() + pos, rem);
108 else
109 written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
110 }
111 if (written > 0)
112 bb.position(pos + written);
113 return written;
114 }
115
116 static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
117 throws IOException
118 {
119 return write(fd, bufs, 0, bufs.length, nd);
120 }
121
122 static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
123 NativeDispatcher nd)
124 throws IOException
125 {
126 IOVecWrapper vec = IOVecWrapper.get(length);
127
128 boolean completed = false;
144 // allocate shadow buffer to ensure I/O is done with direct buffer
145 if (!(buf instanceof DirectBuffer)) {
146 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
147 shadow.put(buf);
148 shadow.flip();
149 vec.setShadow(iov_len, shadow);
150 buf.position(pos); // temporarily restore position in user buffer
151 buf = shadow;
152 pos = shadow.position();
153 }
154
155 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
156 vec.putLen(iov_len, rem);
157 iov_len++;
158 }
159 i++;
160 }
161 if (iov_len == 0)
162 return 0L;
163
164 long bytesWritten;
165 if (fdAccess.getDirect(fd))
166 bytesWritten = nd.writevDirect(fd, vec.address, iov_len);
167 else
168 bytesWritten = nd.writev(fd, vec.address, iov_len);
169
170 // Notify the buffers how many bytes were taken
171 long left = bytesWritten;
172 for (int j=0; j<iov_len; j++) {
173 if (left > 0) {
174 ByteBuffer buf = vec.getBuffer(j);
175 int pos = vec.getPosition(j);
176 int rem = vec.getRemaining(j);
177 int n = (left > rem) ? rem : (int)left;
178 buf.position(pos + n);
179 left -= n;
180 }
181 // return shadow buffers to buffer pool
182 ByteBuffer shadow = vec.getShadow(j);
183 if (shadow != null)
184 Util.offerLastTemporaryDirectBuffer(shadow);
185 vec.clearRefs(j);
186 }
187
188 completed = true;
220 dst.put(bb);
221 return n;
222 } finally {
223 Util.offerFirstTemporaryDirectBuffer(bb);
224 }
225 }
226
227 private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
228 long position, NativeDispatcher nd)
229 throws IOException
230 {
231 int pos = bb.position();
232 int lim = bb.limit();
233 assert (pos <= lim);
234 int rem = (pos <= lim ? lim - pos : 0);
235
236 if (rem == 0)
237 return 0;
238 int n = 0;
239 if (position != -1) {
240 if (fdAccess.getDirect(fd))
241 n = nd.preadDirect(fd, ((DirectBuffer)bb).address() + pos,
242 rem, position);
243 else
244 n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
245 rem, position);
246 } else {
247 if (fdAccess.getDirect(fd))
248 n = nd.readDirect(fd, ((DirectBuffer)bb).address() + pos, rem);
249 else
250 n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
251 }
252 if (n > 0)
253 bb.position(pos + n);
254 return n;
255 }
256
257 static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
258 throws IOException
259 {
260 return read(fd, bufs, 0, bufs.length, nd);
261 }
262
263 static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
264 NativeDispatcher nd)
265 throws IOException
266 {
267 IOVecWrapper vec = IOVecWrapper.get(length);
268
269 boolean completed = false;
284
285 if (rem > 0) {
286 vec.setBuffer(iov_len, buf, pos, rem);
287
288 // allocate shadow buffer to ensure I/O is done with direct buffer
289 if (!(buf instanceof DirectBuffer)) {
290 ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
291 vec.setShadow(iov_len, shadow);
292 buf = shadow;
293 pos = shadow.position();
294 }
295
296 vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
297 vec.putLen(iov_len, rem);
298 iov_len++;
299 }
300 i++;
301 }
302 if (iov_len == 0)
303 return 0L;
304 long bytesRead;
305 if (fdAccess.getDirect(fd))
306 bytesRead = nd.readvDirect(fd, vec.address, iov_len);
307 else
308 bytesRead = nd.readv(fd, vec.address, iov_len);
309
310 // Notify the buffers how many bytes were read
311 long left = bytesRead;
312 for (int j=0; j<iov_len; j++) {
313 ByteBuffer shadow = vec.getShadow(j);
314 if (left > 0) {
315 ByteBuffer buf = vec.getBuffer(j);
316 int rem = vec.getRemaining(j);
317 int n = (left > rem) ? rem : (int)left;
318 if (shadow == null) {
319 int pos = vec.getPosition(j);
320 buf.position(pos + n);
321 } else {
322 shadow.limit(shadow.position() + n);
323 buf.put(shadow);
324 }
325 left -= n;
326 }
327 if (shadow != null)
328 Util.offerLastTemporaryDirectBuffer(shadow);
|