< prev index next >

test/jdk/sun/net/www/http/HttpClient/MultiThreadTest.java

Print this page


   1 /*
   2  * Copyright (c) 2002, 2010, 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 /*
  25  * @test
  26  * @bug 4636628
  27  * @summary HttpURLConnection duplicates HTTP GET requests when used with multiple threads
  28 */
  29 
  30 /*
  31  * This tests keep-alive behavior using chunkedinputstreams
  32  * It checks that keep-alive connections are used and also
  33  * that requests are not being repeated (due to errors)
  34  *
  35  * It also checks that the keepalive connections are closed eventually
  36  * because the test will not terminate if the connections
  37  * are not closed by the keep-alive timer.
  38  */
  39 
  40 import java.net.*;
  41 import java.io.*;



  42 
  43 public class MultiThreadTest extends Thread {
  44 
  45     /*
  46      * Is debugging enabled - start with -d to enable.
  47      */
  48     static boolean debug = false;
  49 
  50     static Object threadlock = new Object ();
  51     static int threadCounter = 0;
  52 
  53     static Object getLock() { return threadlock; }
  54 
  55     static void debug(String msg) {
  56         if (debug)
  57             System.out.println(msg);
  58     }
  59 
  60     static int reqnum = 0;
  61 
  62     void doRequest(String uri) throws Exception {
  63         URL url = new URL(uri + "?foo="+reqnum);
  64         reqnum ++;
  65         HttpURLConnection http = (HttpURLConnection)url.openConnection();
  66 
  67         InputStream in = http.getInputStream();
  68         byte b[] = new byte[100];


  77         http.disconnect();
  78     }
  79 
  80     String uri;
  81     byte[] b;
  82     int requests;
  83 
  84     MultiThreadTest(int port, int requests) throws Exception {
  85         uri = "http://localhost:" +
  86                      port + "/foo.html";
  87 
  88         b = new byte [256];
  89         this.requests = requests;
  90 
  91         synchronized (threadlock) {
  92             threadCounter ++;
  93         }
  94     }
  95 
  96     public void run () {


  97         try {
  98             for (int i=0; i<requests; i++) {
  99                 doRequest (uri);
 100             }
 101         } catch (Exception e) {
 102             throw new RuntimeException (e.getMessage());
 103         } finally {
 104             synchronized (threadlock) {
 105                 threadCounter --;
 106                 if (threadCounter == 0) {
 107                     threadlock.notifyAll();
 108                 }
 109             }
 110         }

 111     }
 112 
 113     static int threads=5;
 114 
 115     public static void main(String args[]) throws Exception {

 116 
 117         int x = 0, arg_len = args.length;
 118         int requests = 20;
 119 
 120         if (arg_len > 0 && args[0].equals("-d")) {
 121             debug = true;
 122             x = 1;
 123             arg_len --;
 124         }
 125         if (arg_len > 0) {
 126             threads = Integer.parseInt (args[x]);
 127             requests = Integer.parseInt (args[x+1]);
 128         }
 129 
 130         /* start the server */
 131         ServerSocket ss = new ServerSocket(0);
 132         Server svr = new Server(ss);
 133         svr.start();
 134 
 135         Object lock = MultiThreadTest.getLock();


 140             }
 141             try {
 142                 lock.wait();
 143             } catch (InterruptedException e) {}
 144         }
 145 
 146         // shutdown server - we're done.
 147         svr.shutdown();
 148 
 149         int cnt = svr.connectionCount();
 150         MultiThreadTest.debug("Connections = " + cnt);
 151         int reqs = Worker.getRequests ();
 152         MultiThreadTest.debug("Requests = " + reqs);
 153         System.out.println ("Connection count = " + cnt + " Request count = " + reqs);
 154         if (cnt > threads) { // could be less
 155             throw new RuntimeException ("Expected "+threads + " connections: used " +cnt);
 156         }
 157         if  (reqs != threads*requests) {
 158             throw new RuntimeException ("Expected "+ threads*requests+ " requests: got " +reqs);
 159         }





 160     }
 161 }
 162 
 163     /*
 164      * Server thread to accept connection and create worker threads
 165      * to service each connection.
 166      */
 167     class Server extends Thread {
 168         ServerSocket ss;
 169         int connectionCount;
 170         boolean shutdown = false;

 171 
 172         Server(ServerSocket ss) {
 173             this.ss = ss;
 174         }
 175 




 176         public synchronized int connectionCount() {
 177             return connectionCount;
 178         }
 179 
 180         public synchronized void shutdown() {
 181             shutdown = true;
 182         }
 183 
 184         public void run() {
 185             try {
 186                 ss.setSoTimeout(2000);
 187 
 188                 for (;;) {
 189                     Socket s;
 190                     try {
 191                         MultiThreadTest.debug("server: calling accept.");
 192                         s = ss.accept();
 193                         MultiThreadTest.debug("server: return accept.");
 194                     } catch (SocketTimeoutException te) {
 195                         MultiThreadTest.debug("server: STE");
 196                         synchronized (this) {
 197                             if (shutdown) {
 198                                 MultiThreadTest.debug("server: Shuting down.");
 199                                 return;
 200                             }
 201                         }
 202                         continue;
 203                     }
 204 
 205                     int id;

 206                     synchronized (this) {
 207                         id = connectionCount++;


 208                     }
 209 
 210                     Worker w = new Worker(s, id);
 211                     w.start();
 212                     MultiThreadTest.debug("server: Started worker " + id);
 213                 }
 214 
 215             } catch (Exception e) {
 216                 e.printStackTrace();
 217             } finally {
 218                 try {
 219                     ss.close();
 220                 } catch (Exception e) { }
 221             }
 222         }
 223     }
 224 
 225     /*
 226      * Worker thread to service single connection - can service
 227      * multiple http requests on same connection.
 228      */
 229     class Worker extends Thread {
 230         Socket s;


 251 
 252         int readUntil (InputStream in, char[] seq) throws IOException {
 253             int i=0, count=0;
 254             while (true) {
 255                 int c = in.read();
 256                 if (c == -1)
 257                     return -1;
 258                 count++;
 259                 if (c == seq[i]) {
 260                     i++;
 261                     if (i == seq.length)
 262                         return count;
 263                     continue;
 264                 } else {
 265                     i = 0;
 266                 }
 267             }
 268         }
 269 
 270         public void run() {


 271             try {
 272                 int max = 400;
 273                 byte b[] = new byte[1000];
 274                 InputStream in = new BufferedInputStream (s.getInputStream());
 275                 // response to client
 276                 PrintStream out = new PrintStream(
 277                                     new BufferedOutputStream(
 278                                                 s.getOutputStream() ));
 279 
 280                 for (;;) {
 281 
 282                     // read entire request from client
 283                     int n=0;
 284 
 285                     n = readUntil (in, new char[] {'\r','\n', '\r','\n'});
 286 
 287                     if (n <= 0) {
 288                         MultiThreadTest.debug("worker: " + id + ": Shutdown");
 289                         s.close();
 290                         return;


 301                     out.print("Connection: Keep-Alive\r\n");
 302                     out.print ("Keep-Alive: timeout=15, max="+max+"\r\n");
 303                     out.print("\r\n");
 304                     out.print ("6\r\nHello \r\n");
 305                     out.print ("5\r\nWorld\r\n");
 306                     out.print ("0\r\n\r\n");
 307                     out.flush();
 308 
 309                     if (--max == 0) {
 310                         s.close();
 311                         return;
 312                     }
 313                 }
 314 
 315             } catch (Exception e) {
 316                 e.printStackTrace();
 317             } finally {
 318                 try {
 319                     s.close();
 320                 } catch (Exception e) { }


 321             }
 322         }
 323     }
   1 /*
   2  * Copyright (c) 2002, 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 /*
  25  * @test
  26  * @bug 4636628
  27  * @summary HttpURLConnection duplicates HTTP GET requests when used with multiple threads
  28 */
  29 
  30 /*
  31  * This tests keep-alive behavior using chunkedinputstreams
  32  * It checks that keep-alive connections are used and also
  33  * that requests are not being repeated (due to errors)
  34  *
  35  * It also checks that the keepalive connections are closed eventually
  36  * because the test will not terminate if the connections
  37  * are not closed by the keep-alive timer.
  38  */
  39 
  40 import java.net.*;
  41 import java.io.*;
  42 import java.time.Duration;
  43 import java.util.ArrayList;
  44 import java.util.List;
  45 
  46 public class MultiThreadTest extends Thread {
  47 
  48     /*
  49      * Is debugging enabled - start with -d to enable.
  50      */
  51     static boolean debug = true; // disable debug once stability proven
  52 
  53     static Object threadlock = new Object ();
  54     static int threadCounter = 0;
  55 
  56     static Object getLock() { return threadlock; }
  57 
  58     static void debug(String msg) {
  59         if (debug)
  60             System.out.println(msg);
  61     }
  62 
  63     static int reqnum = 0;
  64 
  65     void doRequest(String uri) throws Exception {
  66         URL url = new URL(uri + "?foo="+reqnum);
  67         reqnum ++;
  68         HttpURLConnection http = (HttpURLConnection)url.openConnection();
  69 
  70         InputStream in = http.getInputStream();
  71         byte b[] = new byte[100];


  80         http.disconnect();
  81     }
  82 
  83     String uri;
  84     byte[] b;
  85     int requests;
  86 
  87     MultiThreadTest(int port, int requests) throws Exception {
  88         uri = "http://localhost:" +
  89                      port + "/foo.html";
  90 
  91         b = new byte [256];
  92         this.requests = requests;
  93 
  94         synchronized (threadlock) {
  95             threadCounter ++;
  96         }
  97     }
  98 
  99     public void run () {
 100         long start = System.nanoTime();
 101 
 102         try {
 103             for (int i=0; i<requests; i++) {
 104                 doRequest (uri);
 105             }
 106         } catch (Exception e) {
 107             throw new RuntimeException (e.getMessage());
 108         } finally {
 109             synchronized (threadlock) {
 110                 threadCounter --;
 111                 if (threadCounter == 0) {
 112                     threadlock.notifyAll();
 113                 }
 114             }
 115         }
 116         debug("client: end - " + Duration.ofNanos(System.nanoTime() - start));
 117     }
 118 
 119     static int threads=5;
 120 
 121     public static void main(String args[]) throws Exception {
 122         long start = System.nanoTime();
 123 
 124         int x = 0, arg_len = args.length;
 125         int requests = 20;
 126 
 127         if (arg_len > 0 && args[0].equals("-d")) {
 128             debug = true;
 129             x = 1;
 130             arg_len --;
 131         }
 132         if (arg_len > 0) {
 133             threads = Integer.parseInt (args[x]);
 134             requests = Integer.parseInt (args[x+1]);
 135         }
 136 
 137         /* start the server */
 138         ServerSocket ss = new ServerSocket(0);
 139         Server svr = new Server(ss);
 140         svr.start();
 141 
 142         Object lock = MultiThreadTest.getLock();


 147             }
 148             try {
 149                 lock.wait();
 150             } catch (InterruptedException e) {}
 151         }
 152 
 153         // shutdown server - we're done.
 154         svr.shutdown();
 155 
 156         int cnt = svr.connectionCount();
 157         MultiThreadTest.debug("Connections = " + cnt);
 158         int reqs = Worker.getRequests ();
 159         MultiThreadTest.debug("Requests = " + reqs);
 160         System.out.println ("Connection count = " + cnt + " Request count = " + reqs);
 161         if (cnt > threads) { // could be less
 162             throw new RuntimeException ("Expected "+threads + " connections: used " +cnt);
 163         }
 164         if  (reqs != threads*requests) {
 165             throw new RuntimeException ("Expected "+ threads*requests+ " requests: got " +reqs);
 166         }
 167         for (Thread worker : svr.workers()) {
 168             worker.join(60_000);
 169         }
 170 
 171         debug("main thread end - " + Duration.ofNanos(System.nanoTime() - start));
 172     }
 173 }
 174 
 175     /*
 176      * Server thread to accept connection and create worker threads
 177      * to service each connection.
 178      */
 179     class Server extends Thread {
 180         ServerSocket ss;
 181         int connectionCount;
 182         boolean shutdown = false;
 183         private List<Worker> workers = new ArrayList<>();
 184 
 185         Server(ServerSocket ss) {
 186             this.ss = ss;
 187         }
 188 
 189         public synchronized List<Worker> workers() {
 190             return workers;
 191         }
 192 
 193         public synchronized int connectionCount() {
 194             return connectionCount;
 195         }
 196 
 197         public synchronized void shutdown() {
 198             shutdown = true;
 199         }
 200 
 201         public void run() {
 202             try {
 203                 ss.setSoTimeout(2000);
 204 
 205                 for (;;) {
 206                     Socket s;
 207                     try {
 208                         MultiThreadTest.debug("server: calling accept.");
 209                         s = ss.accept();
 210                         MultiThreadTest.debug("server: return accept.");
 211                     } catch (SocketTimeoutException te) {
 212                         MultiThreadTest.debug("server: STE");
 213                         synchronized (this) {
 214                             if (shutdown) {
 215                                 MultiThreadTest.debug("server: Shuting down.");
 216                                 return;
 217                             }
 218                         }
 219                         continue;
 220                     }
 221 
 222                     int id;
 223                     Worker w;
 224                     synchronized (this) {
 225                         id = connectionCount++;
 226                         w = new Worker(s, id);
 227                         workers.add(w);
 228                     }


 229                     w.start();
 230                     MultiThreadTest.debug("server: Started worker " + id);
 231                 }
 232 
 233             } catch (Exception e) {
 234                 e.printStackTrace();
 235             } finally {
 236                 try {
 237                     ss.close();
 238                 } catch (Exception e) { }
 239             }
 240         }
 241     }
 242 
 243     /*
 244      * Worker thread to service single connection - can service
 245      * multiple http requests on same connection.
 246      */
 247     class Worker extends Thread {
 248         Socket s;


 269 
 270         int readUntil (InputStream in, char[] seq) throws IOException {
 271             int i=0, count=0;
 272             while (true) {
 273                 int c = in.read();
 274                 if (c == -1)
 275                     return -1;
 276                 count++;
 277                 if (c == seq[i]) {
 278                     i++;
 279                     if (i == seq.length)
 280                         return count;
 281                     continue;
 282                 } else {
 283                     i = 0;
 284                 }
 285             }
 286         }
 287 
 288         public void run() {
 289             long start = System.nanoTime();
 290 
 291             try {
 292                 int max = 400;
 293                 byte b[] = new byte[1000];
 294                 InputStream in = new BufferedInputStream (s.getInputStream());
 295                 // response to client
 296                 PrintStream out = new PrintStream(
 297                                     new BufferedOutputStream(
 298                                                 s.getOutputStream() ));
 299 
 300                 for (;;) {
 301 
 302                     // read entire request from client
 303                     int n=0;
 304 
 305                     n = readUntil (in, new char[] {'\r','\n', '\r','\n'});
 306 
 307                     if (n <= 0) {
 308                         MultiThreadTest.debug("worker: " + id + ": Shutdown");
 309                         s.close();
 310                         return;


 321                     out.print("Connection: Keep-Alive\r\n");
 322                     out.print ("Keep-Alive: timeout=15, max="+max+"\r\n");
 323                     out.print("\r\n");
 324                     out.print ("6\r\nHello \r\n");
 325                     out.print ("5\r\nWorld\r\n");
 326                     out.print ("0\r\n\r\n");
 327                     out.flush();
 328 
 329                     if (--max == 0) {
 330                         s.close();
 331                         return;
 332                     }
 333                 }
 334 
 335             } catch (Exception e) {
 336                 e.printStackTrace();
 337             } finally {
 338                 try {
 339                     s.close();
 340                 } catch (Exception e) { }
 341                 MultiThreadTest.debug("worker: " + id  + " end - " +
 342                             Duration.ofNanos(System.nanoTime() - start));
 343             }
 344         }
 345     }
< prev index next >