0N/A/*
3261N/A * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.nio.ch;
0N/A
0N/Aimport java.io.FileDescriptor;
0N/Aimport java.io.IOException;
0N/Aimport java.nio.ByteBuffer;
0N/A
0N/A
0N/A/**
0N/A * File-descriptor based I/O utilities that are shared by NIO classes.
0N/A */
0N/A
0N/Aclass IOUtil {
0N/A
5204N/A /**
5204N/A * Max number of iovec structures that readv/writev supports
5204N/A */
5204N/A static final int IOV_MAX;
5204N/A
0N/A private IOUtil() { } // No instantiation
0N/A
0N/A static int write(FileDescriptor fd, ByteBuffer src, long position,
6050N/A NativeDispatcher nd)
0N/A throws IOException
0N/A {
0N/A if (src instanceof DirectBuffer)
6050N/A return writeFromNativeBuffer(fd, src, position, nd);
0N/A
0N/A // Substitute a native buffer
0N/A int pos = src.position();
0N/A int lim = src.limit();
0N/A assert (pos <= lim);
0N/A int rem = (pos <= lim ? lim - pos : 0);
3979N/A ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
0N/A try {
0N/A bb.put(src);
0N/A bb.flip();
0N/A // Do not update src until we see how many bytes were written
0N/A src.position(pos);
0N/A
6050N/A int n = writeFromNativeBuffer(fd, bb, position, nd);
0N/A if (n > 0) {
0N/A // now update src
0N/A src.position(pos + n);
0N/A }
0N/A return n;
0N/A } finally {
2655N/A Util.offerFirstTemporaryDirectBuffer(bb);
0N/A }
0N/A }
0N/A
0N/A private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
6050N/A long position, NativeDispatcher nd)
0N/A throws IOException
0N/A {
0N/A int pos = bb.position();
0N/A int lim = bb.limit();
0N/A assert (pos <= lim);
0N/A int rem = (pos <= lim ? lim - pos : 0);
0N/A
0N/A int written = 0;
0N/A if (rem == 0)
0N/A return 0;
0N/A if (position != -1) {
0N/A written = nd.pwrite(fd,
0N/A ((DirectBuffer)bb).address() + pos,
6050N/A rem, position);
0N/A } else {
0N/A written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);
0N/A }
0N/A if (written > 0)
0N/A bb.position(pos + written);
0N/A return written;
0N/A }
0N/A
0N/A static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
0N/A throws IOException
0N/A {
2655N/A return write(fd, bufs, 0, bufs.length, nd);
2655N/A }
0N/A
2655N/A static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
2655N/A NativeDispatcher nd)
2655N/A throws IOException
2655N/A {
2655N/A IOVecWrapper vec = IOVecWrapper.get(length);
0N/A
2655N/A boolean completed = false;
2655N/A int iov_len = 0;
893N/A try {
2655N/A
2655N/A // Iterate over buffers to populate native iovec array.
2655N/A int count = offset + length;
5204N/A int i = offset;
5204N/A while (i < count && iov_len < IOV_MAX) {
2655N/A ByteBuffer buf = bufs[i];
2655N/A int pos = buf.position();
2655N/A int lim = buf.limit();
2655N/A assert (pos <= lim);
2655N/A int rem = (pos <= lim ? lim - pos : 0);
2655N/A if (rem > 0) {
2655N/A vec.setBuffer(iov_len, buf, pos, rem);
2655N/A
2655N/A // allocate shadow buffer to ensure I/O is done with direct buffer
2655N/A if (!(buf instanceof DirectBuffer)) {
2655N/A ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
2655N/A shadow.put(buf);
2655N/A shadow.flip();
2655N/A vec.setShadow(iov_len, shadow);
2655N/A buf.position(pos); // temporarily restore position in user buffer
2655N/A buf = shadow;
2655N/A pos = shadow.position();
2655N/A }
893N/A
2655N/A vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
2655N/A vec.putLen(iov_len, rem);
2655N/A iov_len++;
893N/A }
5204N/A i++;
893N/A }
2655N/A if (iov_len == 0)
2655N/A return 0L;
2655N/A
2655N/A long bytesWritten = nd.writev(fd, vec.address, iov_len);
2655N/A
2655N/A // Notify the buffers how many bytes were taken
2655N/A long left = bytesWritten;
2655N/A for (int j=0; j<iov_len; j++) {
2655N/A if (left > 0) {
2655N/A ByteBuffer buf = vec.getBuffer(j);
2655N/A int pos = vec.getPosition(j);
2655N/A int rem = vec.getRemaining(j);
2655N/A int n = (left > rem) ? rem : (int)left;
2655N/A buf.position(pos + n);
2655N/A left -= n;
2655N/A }
2655N/A // return shadow buffers to buffer pool
2655N/A ByteBuffer shadow = vec.getShadow(j);
2655N/A if (shadow != null)
2655N/A Util.offerLastTemporaryDirectBuffer(shadow);
2655N/A vec.clearRefs(j);
2655N/A }
893N/A
2655N/A completed = true;
2655N/A return bytesWritten;
893N/A
893N/A } finally {
2655N/A // if an error occurred then clear refs to buffers and return any shadow
2655N/A // buffers to cache
2655N/A if (!completed) {
2655N/A for (int j=0; j<iov_len; j++) {
2655N/A ByteBuffer shadow = vec.getShadow(j);
2655N/A if (shadow != null)
2655N/A Util.offerLastTemporaryDirectBuffer(shadow);
2655N/A vec.clearRefs(j);
893N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A static int read(FileDescriptor fd, ByteBuffer dst, long position,
6050N/A NativeDispatcher nd)
0N/A throws IOException
0N/A {
0N/A if (dst.isReadOnly())
0N/A throw new IllegalArgumentException("Read-only buffer");
0N/A if (dst instanceof DirectBuffer)
6050N/A return readIntoNativeBuffer(fd, dst, position, nd);
0N/A
0N/A // Substitute a native buffer
3979N/A ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
0N/A try {
6050N/A int n = readIntoNativeBuffer(fd, bb, position, nd);
0N/A bb.flip();
0N/A if (n > 0)
0N/A dst.put(bb);
0N/A return n;
0N/A } finally {
2655N/A Util.offerFirstTemporaryDirectBuffer(bb);
0N/A }
0N/A }
0N/A
0N/A private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
6050N/A long position, NativeDispatcher nd)
0N/A throws IOException
0N/A {
0N/A int pos = bb.position();
0N/A int lim = bb.limit();
0N/A assert (pos <= lim);
0N/A int rem = (pos <= lim ? lim - pos : 0);
0N/A
0N/A if (rem == 0)
0N/A return 0;
0N/A int n = 0;
0N/A if (position != -1) {
0N/A n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
6050N/A rem, position);
0N/A } else {
0N/A n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
0N/A }
0N/A if (n > 0)
0N/A bb.position(pos + n);
0N/A return n;
0N/A }
0N/A
0N/A static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
0N/A throws IOException
0N/A {
2655N/A return read(fd, bufs, 0, bufs.length, nd);
2655N/A }
2655N/A
2655N/A static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
2655N/A NativeDispatcher nd)
2655N/A throws IOException
2655N/A {
2655N/A IOVecWrapper vec = IOVecWrapper.get(length);
2655N/A
2655N/A boolean completed = false;
2655N/A int iov_len = 0;
2655N/A try {
0N/A
2655N/A // Iterate over buffers to populate native iovec array.
2655N/A int count = offset + length;
5204N/A int i = offset;
5204N/A while (i < count && iov_len < IOV_MAX) {
2655N/A ByteBuffer buf = bufs[i];
2655N/A if (buf.isReadOnly())
2655N/A throw new IllegalArgumentException("Read-only buffer");
2655N/A int pos = buf.position();
2655N/A int lim = buf.limit();
2655N/A assert (pos <= lim);
2655N/A int rem = (pos <= lim ? lim - pos : 0);
2655N/A
2655N/A if (rem > 0) {
2655N/A vec.setBuffer(iov_len, buf, pos, rem);
0N/A
2655N/A // allocate shadow buffer to ensure I/O is done with direct buffer
2655N/A if (!(buf instanceof DirectBuffer)) {
2655N/A ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
2655N/A vec.setShadow(iov_len, shadow);
2655N/A buf = shadow;
2655N/A pos = shadow.position();
2655N/A }
2655N/A
2655N/A vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
2655N/A vec.putLen(iov_len, rem);
2655N/A iov_len++;
893N/A }
5204N/A i++;
0N/A }
2655N/A if (iov_len == 0)
2655N/A return 0L;
2655N/A
2655N/A long bytesRead = nd.readv(fd, vec.address, iov_len);
2655N/A
2655N/A // Notify the buffers how many bytes were read
2655N/A long left = bytesRead;
2655N/A for (int j=0; j<iov_len; j++) {
2655N/A ByteBuffer shadow = vec.getShadow(j);
2655N/A if (left > 0) {
2655N/A ByteBuffer buf = vec.getBuffer(j);
2655N/A int rem = vec.getRemaining(j);
2655N/A int n = (left > rem) ? rem : (int)left;
2655N/A if (shadow == null) {
2655N/A int pos = vec.getPosition(j);
2655N/A buf.position(pos + n);
2655N/A } else {
2655N/A shadow.limit(shadow.position() + n);
2655N/A buf.put(shadow);
2655N/A }
2655N/A left -= n;
2655N/A }
2655N/A if (shadow != null)
2655N/A Util.offerLastTemporaryDirectBuffer(shadow);
2655N/A vec.clearRefs(j);
2655N/A }
0N/A
2655N/A completed = true;
2655N/A return bytesRead;
0N/A
893N/A } finally {
2655N/A // if an error occurred then clear refs to buffers and return any shadow
2655N/A // buffers to cache
2655N/A if (!completed) {
2655N/A for (int j=0; j<iov_len; j++) {
2655N/A ByteBuffer shadow = vec.getShadow(j);
2655N/A if (shadow != null)
2655N/A Util.offerLastTemporaryDirectBuffer(shadow);
2655N/A vec.clearRefs(j);
893N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A static FileDescriptor newFD(int i) {
0N/A FileDescriptor fd = new FileDescriptor();
0N/A setfdVal(fd, i);
0N/A return fd;
0N/A }
0N/A
0N/A static native boolean randomBytes(byte[] someBytes);
0N/A
2731N/A /**
2731N/A * Returns two file descriptors for a pipe encoded in a long.
2731N/A * The read end of the pipe is returned in the high 32 bits,
2731N/A * while the write end is returned in the low 32 bits.
2731N/A */
2731N/A static native long makePipe(boolean blocking);
0N/A
0N/A static native boolean drain(int fd) throws IOException;
0N/A
0N/A static native void configureBlocking(FileDescriptor fd, boolean blocking)
0N/A throws IOException;
0N/A
0N/A static native int fdVal(FileDescriptor fd);
0N/A
0N/A static native void setfdVal(FileDescriptor fd, int value);
0N/A
5204N/A static native int iovMax();
5204N/A
5386N/A static native int fdLimit();
5386N/A
0N/A static native void initIDs();
0N/A
0N/A static {
0N/A // Note that IOUtil.initIDs is called from within Util.load.
0N/A Util.load();
5204N/A IOV_MAX = iovMax();
0N/A }
0N/A
0N/A}