1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.net.rdma; 27 28 import java.io.FileDescriptor; 29 import java.io.FileOutputStream; 30 import java.io.IOException; 31 import java.nio.channels.FileChannel; 32 import java.net.Socket; 33 import java.net.SocketException; 34 35 class RdmaSocketOutputStream extends FileOutputStream 36 { 37 static { 38 init(); 39 } 40 41 private RdmaSocketImpl impl = null; 42 private byte temp[] = new byte[1]; 43 private Socket socket = null; 44 45 RdmaSocketOutputStream(RdmaSocketImpl impl) throws IOException { 46 super(impl.getFileDescriptor()); 47 this.impl = impl; 48 socket = impl.getSocket(); 49 } 50 51 public final FileChannel getChannel() { 52 return null; 53 } 54 55 /** 56 * Writes to the socket. 57 * @param fd the FileDescriptor 58 * @param b the data to be written 59 * @param off the start offset in the data 60 * @param len the number of bytes that are written 61 * @exception IOException If an I/O error has occurred. 62 */ 63 private native void rdmaSocketWrite0(FileDescriptor fd, byte[] b, 64 int off, int len) throws IOException; 65 66 /** 67 * Writes to the socket with appropriate locking of the 68 * FileDescriptor. 69 * @param b the data to be written 70 * @param off the start offset in the data 71 * @param len the number of bytes that are written 72 * @exception IOException If an I/O error has occurred. 73 */ 74 private void rdmaSocketWrite(byte b[], int off, int len) 75 throws IOException { 76 if (len <= 0 || off < 0 || len > b.length - off) { 77 if (len == 0) { 78 return; 79 } 80 throw new ArrayIndexOutOfBoundsException("len == " + len 81 + " off == " + off + " buffer length == " + b.length); 82 } 83 84 FileDescriptor fd = impl.acquireFD(); 85 try { 86 rdmaSocketWrite0(fd, b, off, len); 87 } catch (SocketException se) { 88 if (se instanceof sun.net.ConnectionResetException) { 89 impl.setConnectionResetPending(); 90 se = new SocketException("Connection reset"); 91 } 92 if (impl.isClosedOrPending()) { 93 throw new SocketException("Socket closed"); 94 } else { 95 throw se; 96 } 97 } finally { 98 impl.releaseFD(); 99 } 100 } 101 102 /** 103 * Writes a byte to the socket. 104 * @param b the data to be written 105 * @exception IOException If an I/O error has occurred. 106 */ 107 public void write(int b) throws IOException { 108 temp[0] = (byte)b; 109 rdmaSocketWrite(temp, 0, 1); 110 } 111 112 /** 113 * Writes the contents of the buffer <i>b</i> to the socket. 114 * @param b the data to be written 115 * @exception SocketException If an I/O error has occurred. 116 */ 117 public void write(byte b[]) throws IOException { 118 rdmaSocketWrite(b, 0, b.length); 119 } 120 121 /** 122 * Writes <i>length</i> bytes from buffer <i>b</i> starting at 123 * offset <i>len</i>. 124 * @param b the data to be written 125 * @param off the start offset in the data 126 * @param len the number of bytes that are written 127 * @exception SocketException If an I/O error has occurred. 128 */ 129 public void write(byte b[], int off, int len) throws IOException { 130 rdmaSocketWrite(b, off, len); 131 } 132 133 /** 134 * Closes the stream. 135 */ 136 private boolean closing = false; 137 public void close() throws IOException { 138 if (closing) 139 return; 140 closing = true; 141 if (socket != null) { 142 if (!socket.isClosed()) 143 socket.close(); 144 } else 145 impl.close(); 146 closing = false; 147 } 148 149 /** 150 * Perform class load-time initializations. 151 */ 152 private static native void init(); 153 154 }