http-client-branch: fixing synchronization problem in ping test http-client-branch
authormichaelm
Fri, 24 Nov 2017 20:48:35 +0000
branchhttp-client-branch
changeset 55871 45c88bf0592b
parent 55870 1a13210ce726
child 55872 9c31615e8989
http-client-branch: fixing synchronization problem in ping test
test/jdk/java/net/httpclient/http2/BasicTest.java
test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java
test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java
test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java
--- a/test/jdk/java/net/httpclient/http2/BasicTest.java	Fri Nov 24 18:42:32 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/BasicTest.java	Fri Nov 24 20:48:35 2017 +0000
@@ -40,7 +40,10 @@
 import javax.net.ssl.*;
 import java.nio.file.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
 import jdk.testlibrary.SimpleSSLContext;
 import static jdk.incubator.http.HttpRequest.BodyPublisher.fromFile;
 import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString;
@@ -87,14 +90,23 @@
         }
     }
 
-    static LinkedList<CompletableFuture<Long>> cfs = new LinkedList<>();
+    static List<CompletableFuture<Long>> cfs = Collections
+        .synchronizedList( new LinkedList<>());
+
+    static AtomicReference<CompletableFuture<Long>> currentCF =
+        new AtomicReference<>();
 
     static class EchoWithPingHandler extends Http2EchoHandler {
         @Override
         public void handle(Http2TestExchange exchange) throws IOException {
-            CompletableFuture<Long> cf = new CompletableFuture<>();
-            cfs.add(cf);
-            exchange.sendPing(cf);
+            // ensure only one ping active at a time.
+            currentCF.getAndUpdate((cf) -> {
+                if (cf  == null || cf.isDone()) {
+                    cf = exchange.sendPing();
+                    cfs.add(cf);
+                }
+                return cf;
+            });
             super.handle(exchange);
         }
     }
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java	Fri Nov 24 18:42:32 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java	Fri Nov 24 20:48:35 2017 +0000
@@ -64,9 +64,9 @@
     void serverPush(URI uri, HttpHeadersImpl headers, InputStream content);
 
     /**
-     * Send a PING on this exchanges connection, and complete the given CF
+     * Send a PING on this exchanges connection, and completes the returned CF
      * with the number of milliseconds it took to get a valid response.
      * It may also complete exceptionally
      */
-    void sendPing(CompletableFuture<Long> cf) throws IOException;
+    CompletableFuture<Long> sendPing();
 }
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java	Fri Nov 24 18:42:32 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java	Fri Nov 24 20:48:35 2017 +0000
@@ -79,8 +79,8 @@
     }
 
     @Override
-    public void sendPing(CompletableFuture<Long> cf) throws IOException {
-        conn.sendPing(cf);
+    public CompletableFuture<Long> sendPing() {
+        return conn.sendPing();
     }
 
     @Override
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Fri Nov 24 18:42:32 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Fri Nov 24 20:48:35 2017 +0000
@@ -116,23 +116,28 @@
     }
 
     /**
-     * Sends a PING frame on this connection, and invokes the given
-     * handler when the PING ack is received. The handler is given
-     * an integer, whose value if >= 0, is the number of milliseconds
-     * between PING and ACK, If < 0 signifies an error occured.
+     * Sends a PING frame on this connection, and completes the returned
+     * CF when the PING ack is received. The CF is given
+     * an integer, whose value is the number of milliseconds
+     * between PING and ACK.
      *
      * Only one PING is allowed to be outstanding at any time
      */
-    void sendPing(CompletableFuture<Long> cf) throws IOException {
-        if (pingData != null) {
-            throw new IllegalStateException("PING already outstanding");
+    CompletableFuture<Long> sendPing() {
+        this.pingResponseHandler = new CompletableFuture<>();
+        try {
+            if (pingData != null) {
+                throw new IllegalStateException("PING already outstanding");
+            }
+            pingData = new byte[8];
+            random.nextBytes(pingData);
+            pingStamp.set(System.currentTimeMillis());
+            PingFrame ping = new PingFrame(0, pingData);
+            outputQ.put(ping);
+        } catch (Throwable t) {
+            pingResponseHandler.completeExceptionally(t);
         }
-        pingData = new byte[8];
-        random.nextBytes(pingData);
-        this.pingResponseHandler = cf;
-        pingStamp.set(System.currentTimeMillis());
-        PingFrame ping = new PingFrame(0, pingData);
-        outputQ.put(ping);
+        return pingResponseHandler;
     }
 
     /**