IOUtil.java 12.2 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
8
 * particular file as subject to the "Classpath" exception as provided
9
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
10 11 12 13 14 15 16 17 18 19 20
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
21 22 23
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36
 */

package sun.nio.ch;

import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;


/**
 * File-descriptor based I/O utilities that are shared by NIO classes.
 */

37
public class IOUtil {
D
duke 已提交
38

39 40 41 42 43
    /**
     * Max number of iovec structures that readv/writev supports
     */
    static final int IOV_MAX;

D
duke 已提交
44 45 46
    private IOUtil() { }                // No instantiation

    static int write(FileDescriptor fd, ByteBuffer src, long position,
47
                     NativeDispatcher nd)
D
duke 已提交
48 49 50
        throws IOException
    {
        if (src instanceof DirectBuffer)
51
            return writeFromNativeBuffer(fd, src, position, nd);
D
duke 已提交
52 53 54 55 56 57

        // Substitute a native buffer
        int pos = src.position();
        int lim = src.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);
58
        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
D
duke 已提交
59 60 61 62 63 64
        try {
            bb.put(src);
            bb.flip();
            // Do not update src until we see how many bytes were written
            src.position(pos);

65
            int n = writeFromNativeBuffer(fd, bb, position, nd);
D
duke 已提交
66 67 68 69 70 71
            if (n > 0) {
                // now update src
                src.position(pos + n);
            }
            return n;
        } finally {
72
            Util.offerFirstTemporaryDirectBuffer(bb);
D
duke 已提交
73 74 75 76
        }
    }

    private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
77
                                             long position, NativeDispatcher nd)
D
duke 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90
        throws IOException
    {
        int pos = bb.position();
        int lim = bb.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);

        int written = 0;
        if (rem == 0)
            return 0;
        if (position != -1) {
            written = nd.pwrite(fd,
                                ((DirectBuffer)bb).address() + pos,
91
                                rem, position);
D
duke 已提交
92 93 94 95 96 97 98 99 100 101 102
        } else {
            written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
        }
        if (written > 0)
            bb.position(pos + written);
        return written;
    }

    static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
        throws IOException
    {
103 104
        return write(fd, bufs, 0, bufs.length, nd);
    }
D
duke 已提交
105

106 107 108 109 110
    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                      NativeDispatcher nd)
        throws IOException
    {
        IOVecWrapper vec = IOVecWrapper.get(length);
D
duke 已提交
111

112 113
        boolean completed = false;
        int iov_len = 0;
D
duke 已提交
114 115
        try {

116 117
            // Iterate over buffers to populate native iovec array.
            int count = offset + length;
118 119
            int i = offset;
            while (i < count && iov_len < IOV_MAX) {
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
                ByteBuffer buf = bufs[i];
                int pos = buf.position();
                int lim = buf.limit();
                assert (pos <= lim);
                int rem = (pos <= lim ? lim - pos : 0);
                if (rem > 0) {
                    vec.setBuffer(iov_len, buf, pos, rem);

                    // allocate shadow buffer to ensure I/O is done with direct buffer
                    if (!(buf instanceof DirectBuffer)) {
                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
                        shadow.put(buf);
                        shadow.flip();
                        vec.setShadow(iov_len, shadow);
                        buf.position(pos);  // temporarily restore position in user buffer
                        buf = shadow;
                        pos = shadow.position();
                    }
D
duke 已提交
138

139 140 141 142
                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
                    vec.putLen(iov_len, rem);
                    iov_len++;
                }
143
                i++;
144
            }
145 146 147 148
            if (iov_len == 0)
                return 0L;

            long bytesWritten = nd.writev(fd, vec.address, iov_len);
149 150

            // Notify the buffers how many bytes were taken
151 152 153 154 155 156 157 158 159
            long left = bytesWritten;
            for (int j=0; j<iov_len; j++) {
                if (left > 0) {
                    ByteBuffer buf = vec.getBuffer(j);
                    int pos = vec.getPosition(j);
                    int rem = vec.getRemaining(j);
                    int n = (left > rem) ? rem : (int)left;
                    buf.position(pos + n);
                    left -= n;
160
                }
161 162 163 164 165
                // return shadow buffers to buffer pool
                ByteBuffer shadow = vec.getShadow(j);
                if (shadow != null)
                    Util.offerLastTemporaryDirectBuffer(shadow);
                vec.clearRefs(j);
166
            }
167 168 169 170

            completed = true;
            return bytesWritten;

171
        } finally {
172 173 174 175 176 177 178 179
            // if an error occurred then clear refs to buffers and return any shadow
            // buffers to cache
            if (!completed) {
                for (int j=0; j<iov_len; j++) {
                    ByteBuffer shadow = vec.getShadow(j);
                    if (shadow != null)
                        Util.offerLastTemporaryDirectBuffer(shadow);
                    vec.clearRefs(j);
D
duke 已提交
180 181 182 183 184 185
                }
            }
        }
    }

    static int read(FileDescriptor fd, ByteBuffer dst, long position,
186
                    NativeDispatcher nd)
D
duke 已提交
187 188 189 190 191
        throws IOException
    {
        if (dst.isReadOnly())
            throw new IllegalArgumentException("Read-only buffer");
        if (dst instanceof DirectBuffer)
192
            return readIntoNativeBuffer(fd, dst, position, nd);
D
duke 已提交
193 194

        // Substitute a native buffer
195
        ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
D
duke 已提交
196
        try {
197
            int n = readIntoNativeBuffer(fd, bb, position, nd);
D
duke 已提交
198 199 200 201 202
            bb.flip();
            if (n > 0)
                dst.put(bb);
            return n;
        } finally {
203
            Util.offerFirstTemporaryDirectBuffer(bb);
D
duke 已提交
204 205 206 207
        }
    }

    private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
208
                                            long position, NativeDispatcher nd)
D
duke 已提交
209 210 211 212 213 214 215 216 217 218 219 220
        throws IOException
    {
        int pos = bb.position();
        int lim = bb.limit();
        assert (pos <= lim);
        int rem = (pos <= lim ? lim - pos : 0);

        if (rem == 0)
            return 0;
        int n = 0;
        if (position != -1) {
            n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
221
                         rem, position);
D
duke 已提交
222 223 224 225 226 227 228 229 230 231 232
        } else {
            n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
        }
        if (n > 0)
            bb.position(pos + n);
        return n;
    }

    static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
        throws IOException
    {
233 234
        return read(fd, bufs, 0, bufs.length, nd);
    }
D
duke 已提交
235

236 237 238 239 240
    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
                     NativeDispatcher nd)
        throws IOException
    {
        IOVecWrapper vec = IOVecWrapper.get(length);
D
duke 已提交
241

242 243
        boolean completed = false;
        int iov_len = 0;
D
duke 已提交
244 245
        try {

246 247
            // Iterate over buffers to populate native iovec array.
            int count = offset + length;
248 249
            int i = offset;
            while (i < count && iov_len < IOV_MAX) {
250 251 252 253 254 255 256
                ByteBuffer buf = bufs[i];
                if (buf.isReadOnly())
                    throw new IllegalArgumentException("Read-only buffer");
                int pos = buf.position();
                int lim = buf.limit();
                assert (pos <= lim);
                int rem = (pos <= lim ? lim - pos : 0);
D
duke 已提交
257

258 259
                if (rem > 0) {
                    vec.setBuffer(iov_len, buf, pos, rem);
260

261 262 263 264 265 266
                    // allocate shadow buffer to ensure I/O is done with direct buffer
                    if (!(buf instanceof DirectBuffer)) {
                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
                        vec.setShadow(iov_len, shadow);
                        buf = shadow;
                        pos = shadow.position();
267
                    }
268 269 270 271

                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
                    vec.putLen(iov_len, rem);
                    iov_len++;
D
duke 已提交
272
                }
273
                i++;
D
duke 已提交
274
            }
275 276
            if (iov_len == 0)
                return 0L;
D
duke 已提交
277

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
            long bytesRead = nd.readv(fd, vec.address, iov_len);

            // Notify the buffers how many bytes were read
            long left = bytesRead;
            for (int j=0; j<iov_len; j++) {
                ByteBuffer shadow = vec.getShadow(j);
                if (left > 0) {
                    ByteBuffer buf = vec.getBuffer(j);
                    int rem = vec.getRemaining(j);
                    int n = (left > rem) ? rem : (int)left;
                    if (shadow == null) {
                        int pos = vec.getPosition(j);
                        buf.position(pos + n);
                    } else {
                        shadow.limit(shadow.position() + n);
                        buf.put(shadow);
294
                    }
295
                    left -= n;
296
                }
297 298 299
                if (shadow != null)
                    Util.offerLastTemporaryDirectBuffer(shadow);
                vec.clearRefs(j);
300
            }
301 302 303 304

            completed = true;
            return bytesRead;

305
        } finally {
306 307 308 309 310 311 312 313
            // if an error occurred then clear refs to buffers and return any shadow
            // buffers to cache
            if (!completed) {
                for (int j=0; j<iov_len; j++) {
                    ByteBuffer shadow = vec.getShadow(j);
                    if (shadow != null)
                        Util.offerLastTemporaryDirectBuffer(shadow);
                    vec.clearRefs(j);
314
                }
D
duke 已提交
315 316 317 318
            }
        }
    }

319
    public static FileDescriptor newFD(int i) {
D
duke 已提交
320 321 322 323 324 325 326
        FileDescriptor fd = new FileDescriptor();
        setfdVal(fd, i);
        return fd;
    }

    static native boolean randomBytes(byte[] someBytes);

327 328 329 330 331 332
    /**
     * Returns two file descriptors for a pipe encoded in a long.
     * The read end of the pipe is returned in the high 32 bits,
     * while the write end is returned in the low 32 bits.
     */
    static native long makePipe(boolean blocking);
D
duke 已提交
333 334 335

    static native boolean drain(int fd) throws IOException;

336 337
    public static native void configureBlocking(FileDescriptor fd,
                                                boolean blocking)
D
duke 已提交
338 339
        throws IOException;

340
    public static native int fdVal(FileDescriptor fd);
D
duke 已提交
341 342 343

    static native void setfdVal(FileDescriptor fd, int value);

344 345
    static native int fdLimit();

346 347
    static native int iovMax();

D
duke 已提交
348 349
    static native void initIDs();

350 351 352 353 354
    /**
     * Used to trigger loading of native libraries
     */
    public static void load() { }

D
duke 已提交
355
    static {
356 357 358 359 360 361 362 363 364 365 366
        java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction<Void>() {
                    public Void run() {
                        System.loadLibrary("net");
                        System.loadLibrary("nio");
                        return null;
                    }
                });

        initIDs();

367
        IOV_MAX = iovMax();
D
duke 已提交
368 369 370
    }

}