--- /dev/null 2018-06-30 13:49:24.634979840 -0700 +++ new/src/jdk.net/linux/classes/rdma/ch/RdmaSocketInputStream.java 2018-06-30 14:07:19.609167042 -0700 @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved. + * 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 + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + * + * 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. + */ + +package rdma.ch; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.net.Socket; +import java.net.SocketException; + +import sun.net.ConnectionResetException; + +class RdmaSocketInputStream extends FileInputStream +{ + static { + init(); + } + + private boolean eof; + private RdmaSocketImpl impl = null; + private byte temp[]; + private Socket socket = null; + + RdmaSocketInputStream(RdmaSocketImpl impl) throws IOException { + super(impl.getFileDescriptor()); + this.impl = impl; + socket = impl.getSocket(); + } + + public final FileChannel getChannel() { + return null; + } + + private native int rdmaSocketRead0(FileDescriptor fd, + byte b[], int off, int len, + int timeout) + throws IOException; + + + private int rdmaSocketRead(FileDescriptor fd, + byte b[], int off, int len, + int timeout) + throws IOException { + return rdmaSocketRead0(fd, b, off, len, timeout); + } + + public int read(byte b[]) throws IOException { + return read(b, 0, b.length); + } + + public int read(byte b[], int off, int length) throws IOException { + return read(b, off, length, impl.getTimeout()); + } + + int read(byte b[], int off, int length, int timeout) throws IOException { + int n; + + if (eof) { + return -1; + } + + if (impl.isConnectionReset()) { + throw new SocketException("Connection reset"); + } + + if (length <= 0 || off < 0 || length > b.length - off) { + if (length == 0) { + return 0; + } + throw new ArrayIndexOutOfBoundsException("length == " + length + + " off == " + off + " buffer length == " + b.length); + } + + boolean gotReset = false; + + FileDescriptor fd = impl.acquireFD(); + try { + n = rdmaSocketRead(fd, b, off, length, timeout); + if (n > 0) { + return n; + } + } catch (ConnectionResetException rstExc) { + gotReset = true; + } finally { + impl.releaseFD(); + } + + if (gotReset) { + impl.setConnectionResetPending(); + impl.acquireFD(); + try { + n = rdmaSocketRead(fd, b, off, length, timeout); + if (n > 0) { + return n; + } + } catch (ConnectionResetException rstExc) { + } finally { + impl.releaseFD(); + } + } + + if (impl.isClosedOrPending()) { + throw new SocketException("Socket closed"); + } + if (impl.isConnectionResetPending()) { + impl.setConnectionReset(); + } + if (impl.isConnectionReset()) { + throw new SocketException("Connection reset"); + } + eof = true; + return -1; + } + + /** + * Reads a single byte from the socket. + */ + public int read() throws IOException { + if (eof) { + return -1; + } + temp = new byte[1]; + int n = read(temp, 0, 1); + if (n <= 0) { + return -1; + } + return temp[0] & 0xff; + } + + /** + * Skips n bytes of input. + * @param numbytes the number of bytes to skip + * @return the actual number of bytes skipped. + * @exception IOException If an I/O error has occurred. + */ + public long skip(long numbytes) throws IOException { + if (numbytes <= 0) { + return 0; + } + long n = numbytes; + int buflen = (int) Math.min(1024, n); + byte data[] = new byte[buflen]; + while (n > 0) { + int r = read(data, 0, (int) Math.min((long) buflen, n)); + if (r < 0) { + break; + } + n -= r; + } + return numbytes - n; + } + + /** + * Returns the number of bytes that can be read without blocking. + * @return the number of immediately available bytes + */ + public int available() throws IOException { + return impl.available(); + } + + /** + * Closes the stream. + */ + private boolean closing = false; + public void close() throws IOException { + // Prevent recursion. See BugId 4484411 + if (closing) + return; + closing = true; + if (socket != null) { + if (!socket.isClosed()) + socket.close(); + } else + impl.close(); + closing = false; + } + + void setEOF(boolean eof) { + this.eof = eof; + } + + /** + * Perform class load-time initializations. + */ + private static native void init(); +}