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