Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/IOUtil.java
38918 views
/*1* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.io.FileDescriptor;28import java.io.IOException;29import java.nio.ByteBuffer;303132/**33* File-descriptor based I/O utilities that are shared by NIO classes.34*/3536public class IOUtil {3738/**39* Max number of iovec structures that readv/writev supports40*/41static final int IOV_MAX;4243private IOUtil() { } // No instantiation4445static int write(FileDescriptor fd, ByteBuffer src, long position,46NativeDispatcher nd)47throws IOException48{49if (src instanceof DirectBuffer)50return writeFromNativeBuffer(fd, src, position, nd);5152// Substitute a native buffer53int pos = src.position();54int lim = src.limit();55assert (pos <= lim);56int rem = (pos <= lim ? lim - pos : 0);57ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);58try {59bb.put(src);60bb.flip();61// Do not update src until we see how many bytes were written62src.position(pos);6364int n = writeFromNativeBuffer(fd, bb, position, nd);65if (n > 0) {66// now update src67src.position(pos + n);68}69return n;70} finally {71Util.offerFirstTemporaryDirectBuffer(bb);72}73}7475private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,76long position, NativeDispatcher nd)77throws IOException78{79int pos = bb.position();80int lim = bb.limit();81assert (pos <= lim);82int rem = (pos <= lim ? lim - pos : 0);8384int written = 0;85if (rem == 0)86return 0;87if (position != -1) {88written = nd.pwrite(fd,89((DirectBuffer)bb).address() + pos,90rem, position);91} else {92written = nd.write(fd, ((DirectBuffer)bb).address() + pos, rem);93}94if (written > 0)95bb.position(pos + written);96return written;97}9899static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)100throws IOException101{102return write(fd, bufs, 0, bufs.length, nd);103}104105static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,106NativeDispatcher nd)107throws IOException108{109IOVecWrapper vec = IOVecWrapper.get(length);110111boolean completed = false;112int iov_len = 0;113try {114115// Iterate over buffers to populate native iovec array.116int count = offset + length;117int i = offset;118while (i < count && iov_len < IOV_MAX) {119ByteBuffer buf = bufs[i];120int pos = buf.position();121int lim = buf.limit();122assert (pos <= lim);123int rem = (pos <= lim ? lim - pos : 0);124if (rem > 0) {125vec.setBuffer(iov_len, buf, pos, rem);126127// allocate shadow buffer to ensure I/O is done with direct buffer128if (!(buf instanceof DirectBuffer)) {129ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);130shadow.put(buf);131shadow.flip();132vec.setShadow(iov_len, shadow);133buf.position(pos); // temporarily restore position in user buffer134buf = shadow;135pos = shadow.position();136}137138vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);139vec.putLen(iov_len, rem);140iov_len++;141}142i++;143}144if (iov_len == 0)145return 0L;146147long bytesWritten = nd.writev(fd, vec.address, iov_len);148149// Notify the buffers how many bytes were taken150long left = bytesWritten;151for (int j=0; j<iov_len; j++) {152if (left > 0) {153ByteBuffer buf = vec.getBuffer(j);154int pos = vec.getPosition(j);155int rem = vec.getRemaining(j);156int n = (left > rem) ? rem : (int)left;157buf.position(pos + n);158left -= n;159}160// return shadow buffers to buffer pool161ByteBuffer shadow = vec.getShadow(j);162if (shadow != null)163Util.offerLastTemporaryDirectBuffer(shadow);164vec.clearRefs(j);165}166167completed = true;168return bytesWritten;169170} finally {171// if an error occurred then clear refs to buffers and return any shadow172// buffers to cache173if (!completed) {174for (int j=0; j<iov_len; j++) {175ByteBuffer shadow = vec.getShadow(j);176if (shadow != null)177Util.offerLastTemporaryDirectBuffer(shadow);178vec.clearRefs(j);179}180}181}182}183184static int read(FileDescriptor fd, ByteBuffer dst, long position,185NativeDispatcher nd)186throws IOException187{188if (dst.isReadOnly())189throw new IllegalArgumentException("Read-only buffer");190if (dst instanceof DirectBuffer)191return readIntoNativeBuffer(fd, dst, position, nd);192193// Substitute a native buffer194ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());195try {196int n = readIntoNativeBuffer(fd, bb, position, nd);197bb.flip();198if (n > 0)199dst.put(bb);200return n;201} finally {202Util.offerFirstTemporaryDirectBuffer(bb);203}204}205206private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,207long position, NativeDispatcher nd)208throws IOException209{210int pos = bb.position();211int lim = bb.limit();212assert (pos <= lim);213int rem = (pos <= lim ? lim - pos : 0);214215if (rem == 0)216return 0;217int n = 0;218if (position != -1) {219n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,220rem, position);221} else {222n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);223}224if (n > 0)225bb.position(pos + n);226return n;227}228229static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)230throws IOException231{232return read(fd, bufs, 0, bufs.length, nd);233}234235static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,236NativeDispatcher nd)237throws IOException238{239IOVecWrapper vec = IOVecWrapper.get(length);240241boolean completed = false;242int iov_len = 0;243try {244245// Iterate over buffers to populate native iovec array.246int count = offset + length;247int i = offset;248while (i < count && iov_len < IOV_MAX) {249ByteBuffer buf = bufs[i];250if (buf.isReadOnly())251throw new IllegalArgumentException("Read-only buffer");252int pos = buf.position();253int lim = buf.limit();254assert (pos <= lim);255int rem = (pos <= lim ? lim - pos : 0);256257if (rem > 0) {258vec.setBuffer(iov_len, buf, pos, rem);259260// allocate shadow buffer to ensure I/O is done with direct buffer261if (!(buf instanceof DirectBuffer)) {262ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);263vec.setShadow(iov_len, shadow);264buf = shadow;265pos = shadow.position();266}267268vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);269vec.putLen(iov_len, rem);270iov_len++;271}272i++;273}274if (iov_len == 0)275return 0L;276277long bytesRead = nd.readv(fd, vec.address, iov_len);278279// Notify the buffers how many bytes were read280long left = bytesRead;281for (int j=0; j<iov_len; j++) {282ByteBuffer shadow = vec.getShadow(j);283if (left > 0) {284ByteBuffer buf = vec.getBuffer(j);285int rem = vec.getRemaining(j);286int n = (left > rem) ? rem : (int)left;287if (shadow == null) {288int pos = vec.getPosition(j);289buf.position(pos + n);290} else {291shadow.limit(shadow.position() + n);292buf.put(shadow);293}294left -= n;295}296if (shadow != null)297Util.offerLastTemporaryDirectBuffer(shadow);298vec.clearRefs(j);299}300301completed = true;302return bytesRead;303304} finally {305// if an error occurred then clear refs to buffers and return any shadow306// buffers to cache307if (!completed) {308for (int j=0; j<iov_len; j++) {309ByteBuffer shadow = vec.getShadow(j);310if (shadow != null)311Util.offerLastTemporaryDirectBuffer(shadow);312vec.clearRefs(j);313}314}315}316}317318public static FileDescriptor newFD(int i) {319FileDescriptor fd = new FileDescriptor();320setfdVal(fd, i);321return fd;322}323324static native boolean randomBytes(byte[] someBytes);325326/**327* Returns two file descriptors for a pipe encoded in a long.328* The read end of the pipe is returned in the high 32 bits,329* while the write end is returned in the low 32 bits.330*/331static native long makePipe(boolean blocking);332333static native boolean drain(int fd) throws IOException;334335public static native void configureBlocking(FileDescriptor fd,336boolean blocking)337throws IOException;338339public static native int fdVal(FileDescriptor fd);340341static native void setfdVal(FileDescriptor fd, int value);342343static native int fdLimit();344345static native int iovMax();346347static native void initIDs();348349/**350* Used to trigger loading of native libraries351*/352public static void load() { }353354static {355java.security.AccessController.doPrivileged(356new java.security.PrivilegedAction<Void>() {357public Void run() {358System.loadLibrary("net");359System.loadLibrary("nio");360return null;361}362});363364initIDs();365366IOV_MAX = iovMax();367}368369}370371372