151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.nio.ch;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.FileDescriptor;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.nio.ByteBuffer;
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * File-descriptor based I/O utilities that are shared by NIO classes.
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass IOUtil {
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Max number of iovec structures that readv/writev supports
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final int IOV_MAX;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private IOUtil() { }                // No instantiation
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static int write(FileDescriptor fd, ByteBuffer src, long position,
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     NativeDispatcher nd)
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (src instanceof DirectBuffer)
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return writeFromNativeBuffer(fd, src, position, nd);
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Substitute a native buffer
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = src.position();
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = src.limit();
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.put(src);
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.flip();
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Do not update src until we see how many bytes were written
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            src.position(pos);
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = writeFromNativeBuffer(fd, bb, position, nd);
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (n > 0) {
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // now update src
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                src.position(pos + n);
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return n;
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Util.offerFirstTemporaryDirectBuffer(bb);
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             long position, NativeDispatcher nd)
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = bb.position();
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = bb.limit();
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int written = 0;
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (rem == 0)
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (position != -1) {
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            written = nd.pwrite(fd,
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                ((DirectBuffer)bb).address() + pos,
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                rem, position);
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (written > 0)
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.position(pos + written);
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return written;
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return write(fd, bufs, 0, bufs.length, nd);
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                      NativeDispatcher nd)
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        IOVecWrapper vec = IOVecWrapper.get(length);
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean completed = false;
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int iov_len = 0;
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Iterate over buffers to populate native iovec array.
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int count = offset + length;
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int i = offset;
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (i < count && iov_len < IOV_MAX) {
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ByteBuffer buf = bufs[i];
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int pos = buf.position();
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int lim = buf.limit();
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert (pos <= lim);
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int rem = (pos <= lim ? lim - pos : 0);
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (rem > 0) {
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.setBuffer(iov_len, buf, pos, rem);
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // allocate shadow buffer to ensure I/O is done with direct buffer
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!(buf instanceof DirectBuffer)) {
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        shadow.put(buf);
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        shadow.flip();
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        vec.setShadow(iov_len, shadow);
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buf.position(pos);  // temporarily restore position in user buffer
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buf = shadow;
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos = shadow.position();
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.putLen(iov_len, rem);
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    iov_len++;
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                i++;
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (iov_len == 0)
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0L;
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long bytesWritten = nd.writev(fd, vec.address, iov_len);
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Notify the buffers how many bytes were taken
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long left = bytesWritten;
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int j=0; j<iov_len; j++) {
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (left > 0) {
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ByteBuffer buf = vec.getBuffer(j);
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int pos = vec.getPosition(j);
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int rem = vec.getRemaining(j);
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int n = (left > rem) ? rem : (int)left;
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    buf.position(pos + n);
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    left -= n;
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // return shadow buffers to buffer pool
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ByteBuffer shadow = vec.getShadow(j);
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (shadow != null)
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Util.offerLastTemporaryDirectBuffer(shadow);
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vec.clearRefs(j);
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            completed = true;
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return bytesWritten;
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if an error occurred then clear refs to buffers and return any shadow
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // buffers to cache
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!completed) {
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (int j=0; j<iov_len; j++) {
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ByteBuffer shadow = vec.getShadow(j);
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (shadow != null)
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        Util.offerLastTemporaryDirectBuffer(shadow);
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.clearRefs(j);
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static int read(FileDescriptor fd, ByteBuffer dst, long position,
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    NativeDispatcher nd)
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (dst.isReadOnly())
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Read-only buffer");
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (dst instanceof DirectBuffer)
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return readIntoNativeBuffer(fd, dst, position, nd);
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Substitute a native buffer
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int n = readIntoNativeBuffer(fd, bb, position, nd);
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.flip();
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (n > 0)
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                dst.put(bb);
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return n;
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            Util.offerFirstTemporaryDirectBuffer(bb);
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                            long position, NativeDispatcher nd)
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int pos = bb.position();
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lim = bb.limit();
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert (pos <= lim);
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rem = (pos <= lim ? lim - pos : 0);
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (rem == 0)
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = 0;
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (position != -1) {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         rem, position);
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n > 0)
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bb.position(pos + n);
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return n;
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return read(fd, bufs, 0, bufs.length, nd);
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                     NativeDispatcher nd)
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        IOVecWrapper vec = IOVecWrapper.get(length);
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean completed = false;
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int iov_len = 0;
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Iterate over buffers to populate native iovec array.
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int count = offset + length;
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int i = offset;
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (i < count && iov_len < IOV_MAX) {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ByteBuffer buf = bufs[i];
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (buf.isReadOnly())
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    throw new IllegalArgumentException("Read-only buffer");
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int pos = buf.position();
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int lim = buf.limit();
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                assert (pos <= lim);
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int rem = (pos <= lim ? lim - pos : 0);
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (rem > 0) {
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.setBuffer(iov_len, buf, pos, rem);
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // allocate shadow buffer to ensure I/O is done with direct buffer
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!(buf instanceof DirectBuffer)) {
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        vec.setShadow(iov_len, shadow);
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buf = shadow;
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos = shadow.position();
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.putLen(iov_len, rem);
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    iov_len++;
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                i++;
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (iov_len == 0)
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return 0L;
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long bytesRead = nd.readv(fd, vec.address, iov_len);
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Notify the buffers how many bytes were read
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long left = bytesRead;
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int j=0; j<iov_len; j++) {
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ByteBuffer shadow = vec.getShadow(j);
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (left > 0) {
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ByteBuffer buf = vec.getBuffer(j);
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int rem = vec.getRemaining(j);
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int n = (left > rem) ? rem : (int)left;
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (shadow == null) {
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        int pos = vec.getPosition(j);
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buf.position(pos + n);
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        shadow.limit(shadow.position() + n);
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buf.put(shadow);
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    left -= n;
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (shadow != null)
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Util.offerLastTemporaryDirectBuffer(shadow);
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                vec.clearRefs(j);
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            completed = true;
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return bytesRead;
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } finally {
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // if an error occurred then clear refs to buffers and return any shadow
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // buffers to cache
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!completed) {
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                for (int j=0; j<iov_len; j++) {
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ByteBuffer shadow = vec.getShadow(j);
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (shadow != null)
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        Util.offerLastTemporaryDirectBuffer(shadow);
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    vec.clearRefs(j);
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static FileDescriptor newFD(int i) {
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        FileDescriptor fd = new FileDescriptor();
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        setfdVal(fd, i);
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return fd;
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native boolean randomBytes(byte[] someBytes);
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns two file descriptors for a pipe encoded in a long.
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The read end of the pipe is returned in the high 32 bits,
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * while the write end is returned in the low 32 bits.
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native long makePipe(boolean blocking);
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native boolean drain(int fd) throws IOException;
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native void configureBlocking(FileDescriptor fd, boolean blocking)
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        throws IOException;
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native int fdVal(FileDescriptor fd);
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native void setfdVal(FileDescriptor fd, int value);
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native int iovMax();
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static native int fdLimit();
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static {
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        IOV_MAX = iovMax();
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
352