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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 8195160 26 * @summary Test socketchannel vector IO (use -Dseed=X to set PRNG seed) 27 * @requires (os.family == "linux") 28 * @library .. /test/lib /test/jdk/java/nio/channels 29 * @build jdk.test.lib.RandomFactory 30 * @build RsocketTest 31 * @run main/othervm -Djava.net.preferIPv4Stack=true VectorIO 32 * @key randomness 33 */ 34 35 import java.io.IOException; 36 import java.net.InetAddress; 37 import java.net.InetSocketAddress; 38 import java.nio.ByteBuffer; 39 import java.nio.channels.ServerSocketChannel; 40 import java.nio.channels.SocketChannel; 41 import java.util.Random; 42 import jdk.test.lib.RandomFactory; 43 import jdk.net.Sockets; 44 45 public class VectorIO { 46 47 private static Random generator = RandomFactory.getRandom(); 48 49 static int testSize; 50 51 // whether to use the write/read variant with a length parameter 52 static boolean setLength; 53 54 public static void main(String[] args) throws Exception { 55 if (!RsocketTest.isRsocketAvailable()) 56 return; 57 58 testSize = 1; 59 setLength = false; 60 runTest(); 61 for(int i = 15; i < 18; i++) { 62 testSize = i; 63 setLength = !setLength; 64 runTest(); 65 } 66 } 67 68 static void runTest() throws Exception { 69 System.err.println("Length " + testSize); 70 Server sv = new Server(testSize); 71 sv.start(); 72 bufferTest(sv.port()); 73 if (sv.finish(8000) == 0) 74 throw new Exception("Failed: Length = " + testSize); 75 } 76 77 static void bufferTest(int port) throws Exception { 78 ByteBuffer[] bufs = new ByteBuffer[testSize]; 79 long total = 0L; 80 for(int i = 0; i < testSize; i++) { 81 String source = "buffer" + i; 82 if (generator.nextBoolean()) 83 bufs[i] = ByteBuffer.allocateDirect(source.length()); 84 else 85 bufs[i] = ByteBuffer.allocate(source.length()); 86 87 bufs[i].put(source.getBytes("8859_1")); 88 bufs[i].flip(); 89 total += bufs[i].remaining(); 90 } 91 92 ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1]; 93 System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length); 94 95 // Get a connection to the server 96 InetAddress lh = InetAddress.getLocalHost(); 97 InetSocketAddress isa = new InetSocketAddress(lh, port); 98 SocketChannel sc = Sockets.openRdmaSocketChannel(); 99 sc.connect(isa); 100 sc.configureBlocking(generator.nextBoolean()); 101 102 // Write the data out 103 long rem = total; 104 while (rem > 0L) { 105 long bytesWritten; 106 if (setLength) { 107 bytesWritten = sc.write(bufsPlus1, 0, bufs.length); 108 } else { 109 bytesWritten = sc.write(bufs); 110 } 111 if (bytesWritten == 0) { 112 if (sc.isBlocking()) { 113 throw new RuntimeException("write did not block"); 114 } else { 115 System.err.println("Non-blocking write() wrote zero bytes"); 116 } 117 Thread.sleep(50); 118 } else { 119 rem -= bytesWritten; 120 } 121 } 122 123 // Clean up 124 sc.close(); 125 } 126 127 static class Server 128 extends TestThread 129 { 130 final int testSize; 131 final ServerSocketChannel ssc; 132 133 Server(int testSize) throws IOException { 134 super("Server " + testSize); 135 this.testSize = testSize; 136 this.ssc = Sockets.openRdmaServerSocketChannel().bind(new InetSocketAddress(0)); 137 } 138 139 int port() { 140 return ssc.socket().getLocalPort(); 141 } 142 143 void go() throws Exception { 144 bufferTest(); 145 } 146 147 void bufferTest() throws Exception { 148 long total = 0L; 149 ByteBuffer[] bufs = new ByteBuffer[testSize]; 150 for(int i=0; i<testSize; i++) { 151 String source = "buffer" + i; 152 if (generator.nextBoolean()) 153 bufs[i] = ByteBuffer.allocateDirect(source.length()); 154 else 155 bufs[i] = ByteBuffer.allocate(source.length()); 156 total += bufs[i].capacity(); 157 } 158 159 ByteBuffer[] bufsPlus1 = new ByteBuffer[bufs.length + 1]; 160 System.arraycopy(bufs, 0, bufsPlus1, 0, bufs.length); 161 162 // Get a connection from client 163 SocketChannel sc = null; 164 165 try { 166 167 ssc.configureBlocking(false); 168 169 for (;;) { 170 sc = ssc.accept(); 171 if (sc != null) { 172 System.err.println("accept() succeeded"); 173 break; 174 } 175 Thread.sleep(50); 176 } 177 178 sc.configureBlocking(generator.nextBoolean()); 179 180 // Read data into multiple buffers 181 long avail = total; 182 while (avail > 0) { 183 long bytesRead; 184 if (setLength) { 185 bytesRead = sc.read(bufsPlus1, 0, bufs.length); 186 } else { 187 bytesRead = sc.read(bufs); 188 } 189 if (bytesRead < 0) 190 break; 191 if (bytesRead == 0) { 192 if (sc.isBlocking()) { 193 throw new RuntimeException("read did not block"); 194 } else { 195 System.err.println 196 ("Non-blocking read() read zero bytes"); 197 } 198 Thread.sleep(50); 199 } 200 avail -= bytesRead; 201 } 202 203 // Check results 204 for(int i=0; i<testSize; i++) { 205 String expected = "buffer" + i; 206 bufs[i].flip(); 207 int size = bufs[i].capacity(); 208 byte[] data = new byte[size]; 209 for(int j=0; j<size; j++) 210 data[j] = bufs[i].get(); 211 String message = new String(data, "8859_1"); 212 if (!message.equals(expected)) 213 throw new Exception("Wrong data: Got " 214 + message + ", expected " 215 + expected); 216 } 217 218 } finally { 219 // Clean up 220 ssc.close(); 221 if (sc != null) 222 sc.close(); 223 } 224 225 } 226 227 } 228 }