src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java
branchhttp-client-branch
changeset 56423 ba64c30666cc
parent 56335 7e56c39fa1fa
child 56437 f8b3f053cfbb
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	Wed Apr 11 15:21:25 2018 +0100
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java	Fri Apr 13 10:49:17 2018 +0100
@@ -29,6 +29,7 @@
 import javax.net.ssl.SSLParameters;
 import java.io.IOException;
 import java.lang.System.Logger.Level;
+import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.net.Authenticator;
 import java.net.CookieHandler;
@@ -72,6 +73,8 @@
 import jdk.internal.net.http.common.Log;
 import jdk.internal.net.http.common.Pair;
 import jdk.internal.net.http.common.Utils;
+import jdk.internal.net.http.common.OperationTrackers.Trackable;
+import jdk.internal.net.http.common.OperationTrackers.Tracker;
 import jdk.internal.net.http.websocket.BuilderImpl;
 import jdk.internal.misc.InnocuousThread;
 
@@ -80,7 +83,7 @@
  * the selector manager thread which allows async events to be registered
  * and delivered when they occur. See AsyncEvent.
  */
-class HttpClientImpl extends HttpClient {
+final class HttpClientImpl extends HttpClient implements Trackable {
 
     static final boolean DEBUG = Utils.DEBUG;  // Revisit: temporary dev flag.
     static final boolean DEBUGELAPSED = Utils.TESTING || DEBUG;  // Revisit: temporary dev flag.
@@ -177,6 +180,7 @@
     private final AtomicLong pendingOperationCount = new AtomicLong();
     private final AtomicLong pendingWebSocketCount = new AtomicLong();
     private final AtomicLong pendingHttpRequestCount = new AtomicLong();
+    private final AtomicLong pendingHttp2StreamCount = new AtomicLong();
 
     /** A Set of, deadline first, ordered timeout events. */
     private final TreeSet<TimeoutEvent> timeouts;
@@ -310,11 +314,35 @@
     final long unreference() {
         final long count = pendingOperationCount.decrementAndGet();
         final long httpCount = pendingHttpRequestCount.decrementAndGet();
+        final long http2Count = pendingHttp2StreamCount.get();
         final long webSocketCount = pendingWebSocketCount.get();
         if (count == 0 && facade() == null) {
             selmgr.wakeupSelector();
         }
-        assert httpCount >= 0 : "count of HTTP operations < 0";
+        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
+        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
+        assert webSocketCount >= 0 : "count of WS operations < 0";
+        assert count >= 0 : "count of pending operations < 0";
+        return count;
+    }
+
+    // Increments the pendingOperationCount.
+    final long streamReference() {
+        pendingHttp2StreamCount.incrementAndGet();
+        return pendingOperationCount.incrementAndGet();
+    }
+
+    // Decrements the pendingOperationCount.
+    final long streamUnreference() {
+        final long count = pendingOperationCount.decrementAndGet();
+        final long http2Count = pendingHttp2StreamCount.decrementAndGet();
+        final long httpCount = pendingHttpRequestCount.get();
+        final long webSocketCount = pendingWebSocketCount.get();
+        if (count == 0 && facade() == null) {
+            selmgr.wakeupSelector();
+        }
+        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
+        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
         assert webSocketCount >= 0 : "count of WS operations < 0";
         assert count >= 0 : "count of pending operations < 0";
         return count;
@@ -331,10 +359,12 @@
         final long count = pendingOperationCount.decrementAndGet();
         final long webSocketCount = pendingWebSocketCount.decrementAndGet();
         final long httpCount = pendingHttpRequestCount.get();
+        final long http2Count = pendingHttp2StreamCount.get();
         if (count == 0 && facade() == null) {
             selmgr.wakeupSelector();
         }
-        assert httpCount >= 0 : "count of HTTP operations < 0";
+        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
+        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
         assert webSocketCount >= 0 : "count of WS operations < 0";
         assert count >= 0 : "count of pending operations < 0";
         return count;
@@ -345,6 +375,59 @@
         return pendingOperationCount.get();
     }
 
+    final static class HttpClientTracker implements Tracker {
+        final AtomicLong httpCount;
+        final AtomicLong http2Count;
+        final AtomicLong websocketCount;
+        final AtomicLong operationsCount;
+        final Reference<?> reference;
+        final String name;
+        HttpClientTracker(AtomicLong http,
+                          AtomicLong http2,
+                          AtomicLong ws,
+                          AtomicLong ops,
+                          Reference<?> ref,
+                          String name) {
+            this.httpCount = http;
+            this.http2Count = http2;
+            this.websocketCount = ws;
+            this.operationsCount = ops;
+            this.reference = ref;
+            this.name = name;
+        }
+        @Override
+        public long getOutstandingOperations() {
+            return operationsCount.get();
+        }
+        @Override
+        public long getOutstandingHttpOperations() {
+            return httpCount.get();
+        }
+        @Override
+        public long getOutstandingHttp2Streams() { return http2Count.get(); }
+        @Override
+        public long getOutstandingWebSocketOperations() {
+            return websocketCount.get();
+        }
+        @Override
+        public boolean isFacadeReferenced() {
+            return reference.get() != null;
+        }
+        @Override
+        public String getName() {
+            return name;
+        }
+    }
+
+    public Tracker getOperationsTracker() {
+        return new HttpClientTracker(pendingHttpRequestCount,
+                pendingHttp2StreamCount,
+                pendingWebSocketCount,
+                pendingOperationCount,
+                facadeRef,
+                dbgTag);
+    }
+
     // Called by the SelectorManager thread to figure out whether it's time
     // to terminate.
     final boolean isReferenced() {