src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java
author mbaesken
Thu, 28 Nov 2019 13:02:39 +0100
changeset 59323 ae2eb76c486d
parent 53387 c9622e15ba29
permissions -rw-r--r--
8234821: remove unused functions from libjli Reviewed-by: clanger, alanb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     1
/*
53256
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
     2
 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     4
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    10
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    15
 * accompanied this code).
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    16
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    20
 *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    23
 * questions.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    24
 */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    25
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    26
package jdk.internal.net.http;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    27
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    28
import javax.net.ssl.SSLContext;
53256
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
    29
import javax.net.ssl.SSLException;
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
    30
import javax.net.ssl.SSLHandshakeException;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    31
import javax.net.ssl.SSLParameters;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    32
import java.io.IOException;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
    33
import java.io.UncheckedIOException;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    34
import java.lang.ref.Reference;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    35
import java.lang.ref.WeakReference;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    36
import java.net.Authenticator;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
    37
import java.net.ConnectException;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    38
import java.net.CookieHandler;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    39
import java.net.ProxySelector;
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
    40
import java.net.http.HttpConnectTimeoutException;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
    41
import java.net.http.HttpTimeoutException;
49944
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
    42
import java.nio.ByteBuffer;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    43
import java.nio.channels.CancelledKeyException;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    44
import java.nio.channels.ClosedChannelException;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    45
import java.nio.channels.SelectableChannel;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    46
import java.nio.channels.SelectionKey;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    47
import java.nio.channels.Selector;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    48
import java.nio.channels.SocketChannel;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    49
import java.security.AccessControlContext;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    50
import java.security.AccessController;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    51
import java.security.NoSuchAlgorithmException;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    52
import java.security.PrivilegedAction;
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
    53
import java.time.Duration;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    54
import java.time.Instant;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    55
import java.time.temporal.ChronoUnit;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    56
import java.util.ArrayList;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    57
import java.util.HashSet;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    58
import java.util.Iterator;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    59
import java.util.LinkedList;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    60
import java.util.List;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    61
import java.util.Objects;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    62
import java.util.Optional;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    63
import java.util.Set;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    64
import java.util.TreeSet;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    65
import java.util.concurrent.CompletableFuture;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
    66
import java.util.concurrent.CompletionException;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    67
import java.util.concurrent.ExecutionException;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    68
import java.util.concurrent.Executor;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    69
import java.util.concurrent.Executors;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    70
import java.util.concurrent.ThreadFactory;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    71
import java.util.concurrent.atomic.AtomicInteger;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    72
import java.util.concurrent.atomic.AtomicLong;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
    73
import java.util.function.BooleanSupplier;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    74
import java.util.stream.Stream;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    75
import java.net.http.HttpClient;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    76
import java.net.http.HttpRequest;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    77
import java.net.http.HttpResponse;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    78
import java.net.http.HttpResponse.BodyHandler;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    79
import java.net.http.HttpResponse.PushPromiseHandler;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    80
import java.net.http.WebSocket;
49944
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
    81
import jdk.internal.net.http.common.BufferSupplier;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    82
import jdk.internal.net.http.common.Log;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    83
import jdk.internal.net.http.common.Logger;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    84
import jdk.internal.net.http.common.Pair;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    85
import jdk.internal.net.http.common.Utils;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    86
import jdk.internal.net.http.common.OperationTrackers.Trackable;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    87
import jdk.internal.net.http.common.OperationTrackers.Tracker;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    88
import jdk.internal.net.http.websocket.BuilderImpl;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
    89
import jdk.internal.misc.InnocuousThread;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    90
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    91
/**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    92
 * Client implementation. Contains all configuration information and also
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    93
 * the selector manager thread which allows async events to be registered
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    94
 * and delivered when they occur. See AsyncEvent.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    95
 */
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    96
final class HttpClientImpl extends HttpClient implements Trackable {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
    97
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    98
    static final boolean DEBUGELAPSED = Utils.TESTING || Utils.DEBUG;  // dev flag
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
    99
    static final boolean DEBUGTIMEOUT = false; // dev flag
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   100
    final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   101
    final Logger debugelapsed = Utils.getDebugLogger(this::dbgString, DEBUGELAPSED);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   102
    final Logger debugtimeout = Utils.getDebugLogger(this::dbgString, DEBUGTIMEOUT);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   103
    static final AtomicLong CLIENT_IDS = new AtomicLong();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   104
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   105
    // Define the default factory as a static inner class
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   106
    // that embeds all the necessary logic to avoid
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   107
    // the risk of using a lambda that might keep a reference on the
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   108
    // HttpClient instance from which it was created (helps with
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   109
    // heapdump analysis).
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   110
    private static final class DefaultThreadFactory implements ThreadFactory {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   111
        private final String namePrefix;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   112
        private final AtomicInteger nextId = new AtomicInteger();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   113
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   114
        DefaultThreadFactory(long clientID) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   115
            namePrefix = "HttpClient-" + clientID + "-Worker-";
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   116
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   117
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   118
        @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   119
        public Thread newThread(Runnable r) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   120
            String name = namePrefix + nextId.getAndIncrement();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   121
            Thread t;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   122
            if (System.getSecurityManager() == null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   123
                t = new Thread(null, r, name, 0, false);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   124
            } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   125
                t = InnocuousThread.newThread(name, r);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   126
            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   127
            t.setDaemon(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   128
            return t;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   129
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   130
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   131
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   132
    /**
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   133
     * A DelegatingExecutor is an executor that delegates tasks to
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   134
     * a wrapped executor when it detects that the current thread
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   135
     * is the SelectorManager thread. If the current thread is not
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   136
     * the selector manager thread the given task is executed inline.
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   137
     */
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   138
    final static class DelegatingExecutor implements Executor {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   139
        private final BooleanSupplier isInSelectorThread;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   140
        private final Executor delegate;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   141
        DelegatingExecutor(BooleanSupplier isInSelectorThread, Executor delegate) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   142
            this.isInSelectorThread = isInSelectorThread;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   143
            this.delegate = delegate;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   144
        }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   145
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   146
        Executor delegate() {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   147
            return delegate;
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   148
        }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   149
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   150
        @Override
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   151
        public void execute(Runnable command) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   152
            if (isInSelectorThread.getAsBoolean()) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   153
                delegate.execute(command);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   154
            } else {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   155
                command.run();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   156
            }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   157
        }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   158
    }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   159
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   160
    private final CookieHandler cookieHandler;
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   161
    private final Duration connectTimeout;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   162
    private final Redirect followRedirects;
53387
c9622e15ba29 8216561: HttpClient: The logic of retry on connect exception is inverted
dfuchs
parents: 53256
diff changeset
   163
    private final ProxySelector userProxySelector;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   164
    private final ProxySelector proxySelector;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   165
    private final Authenticator authenticator;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   166
    private final Version version;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   167
    private final ConnectionPool connections;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   168
    private final DelegatingExecutor delegatingExecutor;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   169
    private final boolean isDefaultExecutor;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   170
    // Security parameters
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   171
    private final SSLContext sslContext;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   172
    private final SSLParameters sslParams;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   173
    private final SelectorManager selmgr;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   174
    private final FilterFactory filters;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   175
    private final Http2ClientImpl client2;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   176
    private final long id;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   177
    private final String dbgTag;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   178
49944
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   179
    // The SSL DirectBuffer Supplier provides the ability to recycle
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   180
    // buffers used between the socket reader and the SSLEngine, or
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   181
    // more precisely between the SocketTube publisher and the
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   182
    // SSLFlowDelegate reader.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   183
    private final SSLDirectBufferSupplier sslBufferSupplier
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   184
            = new SSLDirectBufferSupplier(this);
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
   185
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   186
    // This reference is used to keep track of the facade HttpClient
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   187
    // that was returned to the application code.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   188
    // It makes it possible to know when the application no longer
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   189
    // holds any reference to the HttpClient.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   190
    // Unfortunately, this information is not enough to know when
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   191
    // to exit the SelectorManager thread. Because of the asynchronous
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   192
    // nature of the API, we also need to wait until all pending operations
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   193
    // have completed.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   194
    private final WeakReference<HttpClientFacade> facadeRef;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   195
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   196
    // This counter keeps track of the number of operations pending
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   197
    // on the HttpClient. The SelectorManager thread will wait
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   198
    // until there are no longer any pending operations and the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   199
    // facadeRef is cleared before exiting.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   200
    //
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   201
    // The pendingOperationCount is incremented every time a send/sendAsync
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   202
    // operation is invoked on the HttpClient, and is decremented when
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   203
    // the HttpResponse<T> object is returned to the user.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   204
    // However, at this point, the body may not have been fully read yet.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   205
    // This is the case when the response T is implemented as a streaming
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   206
    // subscriber (such as an InputStream).
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   207
    //
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   208
    // To take care of this issue the pendingOperationCount will additionally
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   209
    // be incremented/decremented in the following cases:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   210
    //
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   211
    // 1. For HTTP/2  it is incremented when a stream is added to the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   212
    //    Http2Connection streams map, and decreased when the stream is removed
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   213
    //    from the map. This should also take care of push promises.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   214
    // 2. For WebSocket the count is increased when creating a
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   215
    //    DetachedConnectionChannel for the socket, and decreased
52499
768b1c612100 8213490: Networking area typos and inconsistencies cleanup
prappo
parents: 51364
diff changeset
   216
    //    when the channel is closed.
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   217
    //    In addition, the HttpClient facade is passed to the WebSocket builder,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   218
    //    (instead of the client implementation delegate).
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   219
    // 3. For HTTP/1.1 the count is incremented before starting to parse the body
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   220
    //    response, and decremented when the parser has reached the end of the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   221
    //    response body flow.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   222
    //
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   223
    // This should ensure that the selector manager thread remains alive until
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   224
    // the response has been fully received or the web socket is closed.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   225
    private final AtomicLong pendingOperationCount = new AtomicLong();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   226
    private final AtomicLong pendingWebSocketCount = new AtomicLong();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   227
    private final AtomicLong pendingHttpRequestCount = new AtomicLong();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   228
    private final AtomicLong pendingHttp2StreamCount = new AtomicLong();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   229
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   230
    /** A Set of, deadline first, ordered timeout events. */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   231
    private final TreeSet<TimeoutEvent> timeouts;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   232
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   233
    /**
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   234
     * This is a bit tricky:
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   235
     * 1. an HttpClientFacade has a final HttpClientImpl field.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   236
     * 2. an HttpClientImpl has a final WeakReference<HttpClientFacade> field,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   237
     *    where the referent is the facade created for that instance.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   238
     * 3. We cannot just create the HttpClientFacade in the HttpClientImpl
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   239
     *    constructor, because it would be only weakly referenced and could
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   240
     *    be GC'ed before we can return it.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   241
     * The solution is to use an instance of SingleFacadeFactory which will
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   242
     * allow the caller of new HttpClientImpl(...) to retrieve the facade
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   243
     * after the HttpClientImpl has been created.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   244
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   245
    private static final class SingleFacadeFactory {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   246
        HttpClientFacade facade;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   247
        HttpClientFacade createFacade(HttpClientImpl impl) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   248
            assert facade == null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   249
            return (facade = new HttpClientFacade(impl));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   250
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   251
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   252
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   253
    static HttpClientFacade create(HttpClientBuilderImpl builder) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   254
        SingleFacadeFactory facadeFactory = new SingleFacadeFactory();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   255
        HttpClientImpl impl = new HttpClientImpl(builder, facadeFactory);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   256
        impl.start();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   257
        assert facadeFactory.facade != null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   258
        assert impl.facadeRef.get() == facadeFactory.facade;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   259
        return facadeFactory.facade;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   260
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   261
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   262
    private HttpClientImpl(HttpClientBuilderImpl builder,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   263
                           SingleFacadeFactory facadeFactory) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   264
        id = CLIENT_IDS.incrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   265
        dbgTag = "HttpClientImpl(" + id +")";
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   266
        if (builder.sslContext == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   267
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   268
                sslContext = SSLContext.getDefault();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   269
            } catch (NoSuchAlgorithmException ex) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   270
                throw new InternalError(ex);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   271
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   272
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   273
            sslContext = builder.sslContext;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   274
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   275
        Executor ex = builder.executor;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   276
        if (ex == null) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   277
            ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   278
            isDefaultExecutor = true;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   279
        } else {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   280
            isDefaultExecutor = false;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   281
        }
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   282
        delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   283
        facadeRef = new WeakReference<>(facadeFactory.createFacade(this));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   284
        client2 = new Http2ClientImpl(this);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   285
        cookieHandler = builder.cookieHandler;
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   286
        connectTimeout = builder.connectTimeout;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   287
        followRedirects = builder.followRedirects == null ?
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   288
                Redirect.NEVER : builder.followRedirects;
53387
c9622e15ba29 8216561: HttpClient: The logic of retry on connect exception is inverted
dfuchs
parents: 53256
diff changeset
   289
        this.userProxySelector = builder.proxy;
c9622e15ba29 8216561: HttpClient: The logic of retry on connect exception is inverted
dfuchs
parents: 53256
diff changeset
   290
        this.proxySelector = Optional.ofNullable(userProxySelector)
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   291
                .orElseGet(HttpClientImpl::getDefaultProxySelector);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   292
        if (debug.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   293
            debug.log("proxySelector is %s (user-supplied=%s)",
53387
c9622e15ba29 8216561: HttpClient: The logic of retry on connect exception is inverted
dfuchs
parents: 53256
diff changeset
   294
                      this.proxySelector, userProxySelector != null);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   295
        authenticator = builder.authenticator;
44854
5a486e0acd29 8175814: Update default HttpClient protocol version and optional request version
michaelm
parents: 44639
diff changeset
   296
        if (builder.version == null) {
5a486e0acd29 8175814: Update default HttpClient protocol version and optional request version
michaelm
parents: 44639
diff changeset
   297
            version = HttpClient.Version.HTTP_2;
5a486e0acd29 8175814: Update default HttpClient protocol version and optional request version
michaelm
parents: 44639
diff changeset
   298
        } else {
5a486e0acd29 8175814: Update default HttpClient protocol version and optional request version
michaelm
parents: 44639
diff changeset
   299
            version = builder.version;
5a486e0acd29 8175814: Update default HttpClient protocol version and optional request version
michaelm
parents: 44639
diff changeset
   300
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   301
        if (builder.sslParams == null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   302
            sslParams = getDefaultParams(sslContext);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   303
        } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   304
            sslParams = builder.sslParams;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   305
        }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   306
        connections = new ConnectionPool(id);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   307
        connections.start();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   308
        timeouts = new TreeSet<>();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   309
        try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   310
            selmgr = new SelectorManager(this);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   311
        } catch (IOException e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   312
            // unlikely
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   313
            throw new InternalError(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   314
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   315
        selmgr.setDaemon(true);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   316
        filters = new FilterFactory();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   317
        initFilters();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   318
        assert facadeRef.get() != null;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   319
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   320
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   321
    private void start() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   322
        selmgr.start();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   323
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   324
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   325
    // Called from the SelectorManager thread, just before exiting.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   326
    // Clears the HTTP/1.1 and HTTP/2 cache, ensuring that the connections
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   327
    // that may be still lingering there are properly closed (and their
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   328
    // possibly still opened SocketChannel released).
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   329
    private void stop() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   330
        // Clears HTTP/1.1 cache and close its connections
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   331
        connections.stop();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   332
        // Clears HTTP/2 cache and close its connections.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   333
        client2.stop();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   334
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   335
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   336
    private static SSLParameters getDefaultParams(SSLContext ctx) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   337
        SSLParameters params = ctx.getSupportedSSLParameters();
50985
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   338
        String[] protocols = params.getProtocols();
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   339
        boolean found13 = false;
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   340
        for (String proto : protocols) {
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   341
            if (proto.equals("TLSv1.3")) {
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   342
                found13 = true;
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   343
                break;
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   344
            }
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   345
        }
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   346
        if (found13)
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   347
            params.setProtocols(new String[] {"TLSv1.3", "TLSv1.2"});
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   348
        else
cd41f34e548c 8206001: Enable TLS1.3 by default in Http Client
michaelm
parents: 50681
diff changeset
   349
            params.setProtocols(new String[] {"TLSv1.2"});
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   350
        return params;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   351
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   352
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   353
    private static ProxySelector getDefaultProxySelector() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   354
        PrivilegedAction<ProxySelector> action = ProxySelector::getDefault;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   355
        return AccessController.doPrivileged(action);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   356
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   357
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   358
    // Returns the facade that was returned to the application code.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   359
    // May be null if that facade is no longer referenced.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   360
    final HttpClientFacade facade() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   361
        return facadeRef.get();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   362
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   363
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   364
    // Increments the pendingOperationCount.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   365
    final long reference() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   366
        pendingHttpRequestCount.incrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   367
        return pendingOperationCount.incrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   368
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   369
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   370
    // Decrements the pendingOperationCount.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   371
    final long unreference() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   372
        final long count = pendingOperationCount.decrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   373
        final long httpCount = pendingHttpRequestCount.decrementAndGet();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   374
        final long http2Count = pendingHttp2StreamCount.get();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   375
        final long webSocketCount = pendingWebSocketCount.get();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   376
        if (count == 0 && facade() == null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   377
            selmgr.wakeupSelector();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   378
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   379
        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   380
        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   381
        assert webSocketCount >= 0 : "count of WS operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   382
        assert count >= 0 : "count of pending operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   383
        return count;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   384
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   385
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   386
    // Increments the pendingOperationCount.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   387
    final long streamReference() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   388
        pendingHttp2StreamCount.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   389
        return pendingOperationCount.incrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   390
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   391
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   392
    // Decrements the pendingOperationCount.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   393
    final long streamUnreference() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   394
        final long count = pendingOperationCount.decrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   395
        final long http2Count = pendingHttp2StreamCount.decrementAndGet();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   396
        final long httpCount = pendingHttpRequestCount.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   397
        final long webSocketCount = pendingWebSocketCount.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   398
        if (count == 0 && facade() == null) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   399
            selmgr.wakeupSelector();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   400
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   401
        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   402
        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   403
        assert webSocketCount >= 0 : "count of WS operations < 0";
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   404
        assert count >= 0 : "count of pending operations < 0";
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   405
        return count;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   406
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   407
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   408
    // Increments the pendingOperationCount.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   409
    final long webSocketOpen() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   410
        pendingWebSocketCount.incrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   411
        return pendingOperationCount.incrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   412
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   413
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   414
    // Decrements the pendingOperationCount.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   415
    final long webSocketClose() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   416
        final long count = pendingOperationCount.decrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   417
        final long webSocketCount = pendingWebSocketCount.decrementAndGet();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   418
        final long httpCount = pendingHttpRequestCount.get();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   419
        final long http2Count = pendingHttp2StreamCount.get();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   420
        if (count == 0 && facade() == null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   421
            selmgr.wakeupSelector();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   422
        }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   423
        assert httpCount >= 0 : "count of HTTP/1.1 operations < 0";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   424
        assert http2Count >= 0 : "count of HTTP/2 operations < 0";
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   425
        assert webSocketCount >= 0 : "count of WS operations < 0";
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   426
        assert count >= 0 : "count of pending operations < 0";
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   427
        return count;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   428
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   429
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   430
    // Returns the pendingOperationCount.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   431
    final long referenceCount() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   432
        return pendingOperationCount.get();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   433
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   434
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   435
    final static class HttpClientTracker implements Tracker {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   436
        final AtomicLong httpCount;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   437
        final AtomicLong http2Count;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   438
        final AtomicLong websocketCount;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   439
        final AtomicLong operationsCount;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   440
        final Reference<?> reference;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   441
        final String name;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   442
        HttpClientTracker(AtomicLong http,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   443
                          AtomicLong http2,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   444
                          AtomicLong ws,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   445
                          AtomicLong ops,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   446
                          Reference<?> ref,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   447
                          String name) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   448
            this.httpCount = http;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   449
            this.http2Count = http2;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   450
            this.websocketCount = ws;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   451
            this.operationsCount = ops;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   452
            this.reference = ref;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   453
            this.name = name;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   454
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   455
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   456
        public long getOutstandingOperations() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   457
            return operationsCount.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   458
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   459
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   460
        public long getOutstandingHttpOperations() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   461
            return httpCount.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   462
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   463
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   464
        public long getOutstandingHttp2Streams() { return http2Count.get(); }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   465
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   466
        public long getOutstandingWebSocketOperations() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   467
            return websocketCount.get();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   468
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   469
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   470
        public boolean isFacadeReferenced() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   471
            return reference.get() != null;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   472
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   473
        @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   474
        public String getName() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   475
            return name;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   476
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   477
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   478
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   479
    public Tracker getOperationsTracker() {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   480
        return new HttpClientTracker(pendingHttpRequestCount,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   481
                pendingHttp2StreamCount,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   482
                pendingWebSocketCount,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   483
                pendingOperationCount,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   484
                facadeRef,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   485
                dbgTag);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   486
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   487
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   488
    // Called by the SelectorManager thread to figure out whether it's time
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   489
    // to terminate.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   490
    final boolean isReferenced() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   491
        HttpClient facade = facade();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   492
        return facade != null || referenceCount() > 0;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   493
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   494
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   495
    /**
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   496
     * Wait for activity on given exchange.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   497
     * The following occurs in the SelectorManager thread.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   498
     *
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   499
     *  1) add to selector
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   500
     *  2) If selector fires for this exchange then
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   501
     *     call AsyncEvent.handle()
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   502
     *
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   503
     * If exchange needs to change interest ops, then call registerEvent() again.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   504
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   505
    void registerEvent(AsyncEvent exchange) throws IOException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   506
        selmgr.register(exchange);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   507
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   508
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   509
    /**
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   510
     * Allows an AsyncEvent to modify its interestOps.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   511
     * @param event The modified event.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   512
     */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   513
    void eventUpdated(AsyncEvent event) throws ClosedChannelException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   514
        assert !(event instanceof AsyncTriggerEvent);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   515
        selmgr.eventUpdated(event);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   516
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   517
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   518
    boolean isSelectorThread() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   519
        return Thread.currentThread() == selmgr;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   520
    }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   521
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   522
    Http2ClientImpl client2() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   523
        return client2;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   524
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   525
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   526
    private void debugCompleted(String tag, long startNanos, HttpRequest req) {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   527
        if (debugelapsed.on()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   528
            debugelapsed.log(tag + " elapsed "
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   529
                    + (System.nanoTime() - startNanos)/1000_000L
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   530
                    + " millis for " + req.method()
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   531
                    + " to " + req.uri());
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   532
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   533
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   534
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   535
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   536
    public <T> HttpResponse<T>
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   537
    send(HttpRequest req, BodyHandler<T> responseHandler)
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   538
        throws IOException, InterruptedException
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   539
    {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   540
        CompletableFuture<HttpResponse<T>> cf = null;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   541
        try {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   542
            cf = sendAsync(req, responseHandler, null, null);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   543
            return cf.get();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   544
        } catch (InterruptedException ie) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   545
            if (cf != null )
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   546
                cf.cancel(true);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   547
            throw ie;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   548
        } catch (ExecutionException e) {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   549
            final Throwable throwable = e.getCause();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   550
            final String msg = throwable.getMessage();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   551
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   552
            if (throwable instanceof IllegalArgumentException) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   553
                throw new IllegalArgumentException(msg, throwable);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   554
            } else if (throwable instanceof SecurityException) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   555
                throw new SecurityException(msg, throwable);
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   556
            } else if (throwable instanceof HttpConnectTimeoutException) {
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   557
                HttpConnectTimeoutException hcte = new HttpConnectTimeoutException(msg);
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   558
                hcte.initCause(throwable);
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
   559
                throw hcte;
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   560
            } else if (throwable instanceof HttpTimeoutException) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   561
                throw new HttpTimeoutException(msg);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   562
            } else if (throwable instanceof ConnectException) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   563
                ConnectException ce = new ConnectException(msg);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   564
                ce.initCause(throwable);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   565
                throw ce;
53256
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   566
            } else if (throwable instanceof SSLHandshakeException) {
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   567
                // special case for SSLHandshakeException
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   568
                SSLHandshakeException he = new SSLHandshakeException(msg);
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   569
                he.initCause(throwable);
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   570
                throw he;
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   571
            } else if (throwable instanceof SSLException) {
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   572
                // any other SSLException is wrapped in a plain
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   573
                // SSLException
bd8df96decba 8216498: Confusing and unneeded wrapping of SSLHandshakeException
dfuchs
parents: 52499
diff changeset
   574
                throw new SSLException(msg, throwable);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   575
            } else if (throwable instanceof IOException) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   576
                throw new IOException(msg, throwable);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   577
            } else {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   578
                throw new IOException(msg, throwable);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   579
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   580
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   581
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   582
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   583
    private static final Executor ASYNC_POOL = new CompletableFuture<Void>().defaultExecutor();
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   584
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   585
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   586
    public <T> CompletableFuture<HttpResponse<T>>
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   587
    sendAsync(HttpRequest userRequest, BodyHandler<T> responseHandler)
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   588
    {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   589
        return sendAsync(userRequest, responseHandler, null);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   590
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   591
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   592
    @Override
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   593
    public <T> CompletableFuture<HttpResponse<T>>
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   594
    sendAsync(HttpRequest userRequest,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   595
              BodyHandler<T> responseHandler,
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   596
              PushPromiseHandler<T> pushPromiseHandler) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   597
        return sendAsync(userRequest, responseHandler, pushPromiseHandler, delegatingExecutor.delegate);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   598
    }
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   599
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   600
    private <T> CompletableFuture<HttpResponse<T>>
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   601
    sendAsync(HttpRequest userRequest,
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   602
              BodyHandler<T> responseHandler,
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   603
              PushPromiseHandler<T> pushPromiseHandler,
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   604
              Executor exchangeExecutor)    {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   605
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   606
        Objects.requireNonNull(userRequest);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   607
        Objects.requireNonNull(responseHandler);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   608
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   609
        AccessControlContext acc = null;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   610
        if (System.getSecurityManager() != null)
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   611
            acc = AccessController.getContext();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   612
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   613
        // Clone the, possibly untrusted, HttpRequest
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   614
        HttpRequestImpl requestImpl = new HttpRequestImpl(userRequest, proxySelector);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   615
        if (requestImpl.method().equals("CONNECT"))
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   616
            throw new IllegalArgumentException("Unsupported method CONNECT");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   617
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   618
        long start = DEBUGELAPSED ? System.nanoTime() : 0;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   619
        reference();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   620
        try {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   621
            if (debugelapsed.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   622
                debugelapsed.log("ClientImpl (async) send %s", userRequest);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   623
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   624
            // When using sendAsync(...) we explicitly pass the
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   625
            // executor's delegate as exchange executor to force
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   626
            // asynchronous scheduling of the exchange.
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   627
            // When using send(...) we don't specify any executor
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   628
            // and default to using the client's delegating executor
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   629
            // which only spawns asynchronous tasks if it detects
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   630
            // that the current thread is the selector manager
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   631
            // thread. This will cause everything to execute inline
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   632
            // until we need to schedule some event with the selector.
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   633
            Executor executor = exchangeExecutor == null
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   634
                    ? this.delegatingExecutor : exchangeExecutor;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   635
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   636
            MultiExchange<T> mex = new MultiExchange<>(userRequest,
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   637
                                                            requestImpl,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   638
                                                            this,
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   639
                                                            responseHandler,
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   640
                                                            pushPromiseHandler,
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   641
                                                            acc);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   642
            CompletableFuture<HttpResponse<T>> res =
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   643
                    mex.responseAsync(executor).whenComplete((b,t) -> unreference());
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   644
            if (DEBUGELAPSED) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   645
                res = res.whenComplete(
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   646
                        (b,t) -> debugCompleted("ClientImpl (async)", start, userRequest));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   647
            }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   648
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   649
            // makes sure that any dependent actions happen in the CF default
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   650
            // executor. This is only needed for sendAsync(...), when
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   651
            // exchangeExecutor is non-null.
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   652
            if (exchangeExecutor != null) {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   653
                res = res.whenCompleteAsync((r, t) -> { /* do nothing */}, ASYNC_POOL);
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   654
            }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   655
            return res;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   656
        } catch(Throwable t) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   657
            unreference();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   658
            debugCompleted("ClientImpl (async)", start, userRequest);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   659
            throw t;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   660
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   661
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   662
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   663
    // Main loop for this client's selector
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   664
    private final static class SelectorManager extends Thread {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   665
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   666
        // For testing purposes we have an internal System property that
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   667
        // can control the frequency at which the selector manager will wake
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   668
        // up when there are no pending operations.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   669
        // Increasing the frequency (shorter delays) might allow the selector
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   670
        // to observe that the facade is no longer referenced and might allow
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   671
        // the selector thread to terminate more timely - for when nothing is
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   672
        // ongoing it will only check for that condition every NODEADLINE ms.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   673
        // To avoid misuse of the property, the delay that can be specified
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   674
        // is comprised between [MIN_NODEADLINE, MAX_NODEADLINE], and its default
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   675
        // value if unspecified (or <= 0) is DEF_NODEADLINE = 3000ms
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   676
        // The property is -Djdk.internal.httpclient.selectorTimeout=<millis>
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   677
        private static final int MIN_NODEADLINE = 1000; // ms
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   678
        private static final int MAX_NODEADLINE = 1000 * 1200; // ms
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   679
        private static final int DEF_NODEADLINE = 3000; // ms
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   680
        private static final long NODEADLINE; // default is DEF_NODEADLINE ms
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   681
        static {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   682
            // ensure NODEADLINE is initialized with some valid value.
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   683
            long deadline =  Utils.getIntegerProperty(
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   684
                "jdk.internal.httpclient.selectorTimeout",
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   685
                DEF_NODEADLINE); // millis
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   686
            if (deadline <= 0) deadline = DEF_NODEADLINE;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   687
            deadline = Math.max(deadline, MIN_NODEADLINE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   688
            NODEADLINE = Math.min(deadline, MAX_NODEADLINE);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   689
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   690
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   691
        private final Selector selector;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   692
        private volatile boolean closed;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   693
        private final List<AsyncEvent> registrations;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   694
        private final List<AsyncTriggerEvent> deregistrations;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   695
        private final Logger debug;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   696
        private final Logger debugtimeout;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   697
        HttpClientImpl owner;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   698
        ConnectionPool pool;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   699
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   700
        SelectorManager(HttpClientImpl ref) throws IOException {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   701
            super(null, null,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   702
                  "HttpClient-" + ref.id + "-SelectorManager",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   703
                  0, false);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   704
            owner = ref;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   705
            debug = ref.debug;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   706
            debugtimeout = ref.debugtimeout;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   707
            pool = ref.connectionPool();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   708
            registrations = new ArrayList<>();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   709
            deregistrations = new ArrayList<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   710
            selector = Selector.open();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   711
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   712
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   713
        void eventUpdated(AsyncEvent e) throws ClosedChannelException {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   714
            if (Thread.currentThread() == this) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   715
                SelectionKey key = e.channel().keyFor(selector);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   716
                if (key != null && key.isValid()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   717
                    SelectorAttachment sa = (SelectorAttachment) key.attachment();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   718
                    sa.register(e);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   719
                } else if (e.interestOps() != 0){
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   720
                    // We don't care about paused events.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   721
                    // These are actually handled by
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   722
                    // SelectorAttachment::resetInterestOps later on.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   723
                    // But if we reach here when trying to resume an
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   724
                    // event then it's better to fail fast.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   725
                    if (debug.on()) debug.log("No key for channel");
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   726
                    e.abort(new IOException("No key for channel"));
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   727
                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   728
            } else {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   729
                register(e);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   730
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   731
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   732
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   733
        // This returns immediately. So caller not allowed to send/receive
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   734
        // on connection.
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   735
        synchronized void register(AsyncEvent e) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   736
            registrations.add(e);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   737
            selector.wakeup();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   738
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   739
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   740
        synchronized void cancel(SocketChannel e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   741
            SelectionKey key = e.keyFor(selector);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   742
            if (key != null) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   743
                key.cancel();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   744
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   745
            selector.wakeup();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   746
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   747
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   748
        void wakeupSelector() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   749
            selector.wakeup();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   750
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   751
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   752
        synchronized void shutdown() {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   753
            Log.logTrace("{0}: shutting down", getName());
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   754
            if (debug.on()) debug.log("SelectorManager shutting down");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   755
            closed = true;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   756
            try {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   757
                selector.close();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   758
            } catch (IOException ignored) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   759
            } finally {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   760
                owner.stop();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   761
            }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   762
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   763
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   764
        @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   765
        public void run() {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   766
            List<Pair<AsyncEvent,IOException>> errorList = new ArrayList<>();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   767
            List<AsyncEvent> readyList = new ArrayList<>();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   768
            List<Runnable> resetList = new ArrayList<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   769
            try {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   770
                if (Log.channel()) Log.logChannel(getName() + ": starting");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   771
                while (!Thread.currentThread().isInterrupted()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   772
                    synchronized (this) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   773
                        assert errorList.isEmpty();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   774
                        assert readyList.isEmpty();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   775
                        assert resetList.isEmpty();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   776
                        for (AsyncTriggerEvent event : deregistrations) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   777
                            event.handle();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   778
                        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   779
                        deregistrations.clear();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   780
                        for (AsyncEvent event : registrations) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   781
                            if (event instanceof AsyncTriggerEvent) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   782
                                readyList.add(event);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   783
                                continue;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   784
                            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   785
                            SelectableChannel chan = event.channel();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   786
                            SelectionKey key = null;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   787
                            try {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   788
                                key = chan.keyFor(selector);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   789
                                SelectorAttachment sa;
45531
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   790
                                if (key == null || !key.isValid()) {
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   791
                                    if (key != null) {
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   792
                                        // key is canceled.
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   793
                                        // invoke selectNow() to purge it
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   794
                                        // before registering the new event.
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   795
                                        selector.selectNow();
fb3dbffad37b 8180044: java/net/httpclient/ManyRequests.java failed due to timeout
dfuchs
parents: 44854
diff changeset
   796
                                    }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   797
                                    sa = new SelectorAttachment(chan, selector);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   798
                                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   799
                                    sa = (SelectorAttachment) key.attachment();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   800
                                }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   801
                                // may throw IOE if channel closed: that's OK
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   802
                                sa.register(event);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   803
                                if (!chan.isOpen()) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   804
                                    throw new IOException("Channel closed");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   805
                                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   806
                            } catch (IOException e) {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   807
                                Log.logTrace("{0}: {1}", getName(), e);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   808
                                if (debug.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   809
                                    debug.log("Got " + e.getClass().getName()
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   810
                                              + " while handling registration events");
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   811
                                chan.close();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   812
                                // let the event abort deal with it
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   813
                                errorList.add(new Pair<>(event, e));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   814
                                if (key != null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   815
                                    key.cancel();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   816
                                    selector.selectNow();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   817
                                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   818
                            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   819
                        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   820
                        registrations.clear();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   821
                        selector.selectedKeys().clear();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   822
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   823
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   824
                    for (AsyncEvent event : readyList) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   825
                        assert event instanceof AsyncTriggerEvent;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   826
                        event.handle();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   827
                    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   828
                    readyList.clear();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   829
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   830
                    for (Pair<AsyncEvent,IOException> error : errorList) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   831
                        // an IOException was raised and the channel closed.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   832
                        handleEvent(error.first, error.second);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   833
                    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   834
                    errorList.clear();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   835
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   836
                    // Check whether client is still alive, and if not,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   837
                    // gracefully stop this thread
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   838
                    if (!owner.isReferenced()) {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   839
                        Log.logTrace("{0}: {1}",
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   840
                                getName(),
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   841
                                "HttpClient no longer referenced. Exiting...");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   842
                        return;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   843
                    }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   844
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   845
                    // Timeouts will have milliseconds granularity. It is important
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   846
                    // to handle them in a timely fashion.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   847
                    long nextTimeout = owner.purgeTimeoutsAndReturnNextDeadline();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   848
                    if (debugtimeout.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   849
                        debugtimeout.log("next timeout: %d", nextTimeout);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   850
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   851
                    // Keep-alive have seconds granularity. It's not really an
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   852
                    // issue if we keep connections linger a bit more in the keep
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   853
                    // alive cache.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   854
                    long nextExpiry = pool.purgeExpiredConnectionsAndReturnNextDeadline();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   855
                    if (debugtimeout.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   856
                        debugtimeout.log("next expired: %d", nextExpiry);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   857
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   858
                    assert nextTimeout >= 0;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   859
                    assert nextExpiry >= 0;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   860
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   861
                    // Don't wait for ever as it might prevent the thread to
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   862
                    // stop gracefully. millis will be 0 if no deadline was found.
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   863
                    if (nextTimeout <= 0) nextTimeout = NODEADLINE;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   864
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   865
                    // Clip nextExpiry at NODEADLINE limit. The default
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   866
                    // keep alive is 1200 seconds (half an hour) - we don't
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   867
                    // want to wait that long.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   868
                    if (nextExpiry <= 0) nextExpiry = NODEADLINE;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   869
                    else nextExpiry = Math.min(NODEADLINE, nextExpiry);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   870
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   871
                    // takes the least of the two.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   872
                    long millis = Math.min(nextExpiry, nextTimeout);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   873
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   874
                    if (debugtimeout.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   875
                        debugtimeout.log("Next deadline is %d",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   876
                                         (millis == 0 ? NODEADLINE : millis));
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   877
                    //debugPrint(selector);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   878
                    int n = selector.select(millis == 0 ? NODEADLINE : millis);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   879
                    if (n == 0) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   880
                        // Check whether client is still alive, and if not,
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   881
                        // gracefully stop this thread
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   882
                        if (!owner.isReferenced()) {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   883
                            Log.logTrace("{0}: {1}",
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   884
                                    getName(),
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   885
                                    "HttpClient no longer referenced. Exiting...");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   886
                            return;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   887
                        }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   888
                        owner.purgeTimeoutsAndReturnNextDeadline();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   889
                        continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   890
                    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   891
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   892
                    Set<SelectionKey> keys = selector.selectedKeys();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   893
                    assert errorList.isEmpty();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   894
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   895
                    for (SelectionKey key : keys) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   896
                        SelectorAttachment sa = (SelectorAttachment) key.attachment();
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   897
                        if (!key.isValid()) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   898
                            IOException ex = sa.chan.isOpen()
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   899
                                    ? new IOException("Invalid key")
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   900
                                    : new ClosedChannelException();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   901
                            sa.pending.forEach(e -> errorList.add(new Pair<>(e,ex)));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   902
                            sa.pending.clear();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   903
                            continue;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   904
                        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   905
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   906
                        int eventsOccurred;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   907
                        try {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   908
                            eventsOccurred = key.readyOps();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   909
                        } catch (CancelledKeyException ex) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   910
                            IOException io = Utils.getIOException(ex);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   911
                            sa.pending.forEach(e -> errorList.add(new Pair<>(e,io)));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   912
                            sa.pending.clear();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   913
                            continue;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   914
                        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   915
                        sa.events(eventsOccurred).forEach(readyList::add);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   916
                        resetList.add(() -> sa.resetInterestOps(eventsOccurred));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   917
                    }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   918
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   919
                    selector.selectNow(); // complete cancellation
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   920
                    selector.selectedKeys().clear();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   921
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   922
                    // handle selected events
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   923
                    readyList.forEach((e) -> handleEvent(e, null));
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   924
                    readyList.clear();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   925
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   926
                    // handle errors (closed channels etc...)
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   927
                    errorList.forEach((p) -> handleEvent(p.first, p.second));
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   928
                    errorList.clear();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   929
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   930
                    // reset interest ops for selected channels
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   931
                    resetList.forEach(r -> r.run());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   932
                    resetList.clear();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   933
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   934
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   935
            } catch (Throwable e) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   936
                if (!closed) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   937
                    // This terminates thread. So, better just print stack trace
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   938
                    String err = Utils.stackTrace(e);
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   939
                    Log.logError("{0}: {1}: {2}", getName(),
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   940
                            "HttpClientImpl shutting down due to fatal error", err);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   941
                }
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   942
                if (debug.on()) debug.log("shutting down", e);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   943
                if (Utils.ASSERTIONSENABLED && !debug.on()) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   944
                    e.printStackTrace(System.err); // always print the stack
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   945
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   946
            } finally {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
   947
                if (Log.channel()) Log.logChannel(getName() + ": stopping");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   948
                shutdown();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   949
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   950
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   951
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   952
//        void debugPrint(Selector selector) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   953
//            System.err.println("Selector: debugprint start");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   954
//            Set<SelectionKey> keys = selector.keys();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   955
//            for (SelectionKey key : keys) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   956
//                SelectableChannel c = key.channel();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   957
//                int ops = key.interestOps();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   958
//                System.err.printf("selector chan:%s ops:%d\n", c, ops);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   959
//            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   960
//            System.err.println("Selector: debugprint end");
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   961
//        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   962
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   963
        /** Handles the given event. The given ioe may be null. */
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   964
        void handleEvent(AsyncEvent event, IOException ioe) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   965
            if (closed || ioe != null) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   966
                event.abort(ioe);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   967
            } else {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
   968
                event.handle();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   969
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   970
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   971
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   972
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   973
    final String debugInterestOps(SelectableChannel channel) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   974
        try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   975
            SelectionKey key = channel.keyFor(selmgr.selector);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   976
            if (key == null) return "channel not registered with selector";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   977
            String keyInterestOps = key.isValid()
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   978
                    ? "key.interestOps=" + key.interestOps() : "invalid key";
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   979
            return String.format("channel registered with selector, %s, sa.interestOps=%s",
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   980
                                 keyInterestOps,
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   981
                                 ((SelectorAttachment)key.attachment()).interestOps);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   982
        } catch (Throwable t) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   983
            return String.valueOf(t);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   984
        }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   985
    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
   986
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   987
    /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   988
     * Tracks multiple user level registrations associated with one NIO
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   989
     * registration (SelectionKey). In this implementation, registrations
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   990
     * are one-off and when an event is posted the registration is cancelled
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   991
     * until explicitly registered again.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   992
     *
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   993
     * <p> No external synchronization required as this class is only used
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   994
     * by the SelectorManager thread. One of these objects required per
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   995
     * connection.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   996
     */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   997
    private static class SelectorAttachment {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   998
        private final SelectableChannel chan;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
   999
        private final Selector selector;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1000
        private final Set<AsyncEvent> pending;
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1001
        private final static Logger debug =
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1002
                Utils.getDebugLogger("SelectorAttachment"::toString, Utils.DEBUG);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1003
        private int interestOps;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1004
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1005
        SelectorAttachment(SelectableChannel chan, Selector selector) {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1006
            this.pending = new HashSet<>();
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1007
            this.chan = chan;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1008
            this.selector = selector;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1009
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1010
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1011
        void register(AsyncEvent e) throws ClosedChannelException {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1012
            int newOps = e.interestOps();
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1013
            // re register interest if we are not already interested
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1014
            // in the event. If the event is paused, then the pause will
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1015
            // be taken into account later when resetInterestOps is called.
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1016
            boolean reRegister = (interestOps & newOps) != newOps;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1017
            interestOps |= newOps;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1018
            pending.add(e);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1019
            if (debug.on())
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1020
                debug.log("Registering %s for %d (%s)", e, newOps, reRegister);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1021
            if (reRegister) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1022
                // first time registration happens here also
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1023
                try {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1024
                    chan.register(selector, interestOps, this);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1025
                } catch (Throwable x) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1026
                    abortPending(x);
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1027
                }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1028
            } else if (!chan.isOpen()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1029
                abortPending(new ClosedChannelException());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1030
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1031
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1032
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1033
        /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1034
         * Returns a Stream<AsyncEvents> containing only events that are
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1035
         * registered with the given {@code interestOps}.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1036
         */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1037
        Stream<AsyncEvent> events(int interestOps) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1038
            return pending.stream()
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1039
                    .filter(ev -> (ev.interestOps() & interestOps) != 0);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1040
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1041
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1042
        /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1043
         * Removes any events with the given {@code interestOps}, and if no
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1044
         * events remaining, cancels the associated SelectionKey.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1045
         */
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1046
        void resetInterestOps(int interestOps) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1047
            int newOps = 0;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1048
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1049
            Iterator<AsyncEvent> itr = pending.iterator();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1050
            while (itr.hasNext()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1051
                AsyncEvent event = itr.next();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1052
                int evops = event.interestOps();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1053
                if (event.repeating()) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1054
                    newOps |= evops;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1055
                    continue;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1056
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1057
                if ((evops & interestOps) != 0) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1058
                    itr.remove();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1059
                } else {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1060
                    newOps |= evops;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1061
                }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1062
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1063
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1064
            this.interestOps = newOps;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1065
            SelectionKey key = chan.keyFor(selector);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1066
            if (newOps == 0 && key != null && pending.isEmpty()) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1067
                key.cancel();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1068
            } else {
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1069
                try {
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1070
                    if (key == null || !key.isValid()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1071
                        throw new CancelledKeyException();
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1072
                    }
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1073
                    key.interestOps(newOps);
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1074
                    // double check after
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1075
                    if (!chan.isOpen()) {
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1076
                        abortPending(new ClosedChannelException());
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1077
                        return;
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1078
                    }
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1079
                    assert key.interestOps() == newOps;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1080
                } catch (CancelledKeyException x) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1081
                    // channel may have been closed
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1082
                    if (debug.on()) debug.log("key cancelled for " + chan);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1083
                    abortPending(x);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1084
                }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1085
            }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1086
        }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1087
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1088
        void abortPending(Throwable x) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1089
            if (!pending.isEmpty()) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1090
                AsyncEvent[] evts = pending.toArray(new AsyncEvent[0]);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1091
                pending.clear();
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1092
                IOException io = Utils.getIOException(x);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1093
                for (AsyncEvent event : evts) {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1094
                    event.abort(io);
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1095
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1096
            }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1097
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1098
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1099
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1100
    /*package-private*/ SSLContext theSSLContext() {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1101
        return sslContext;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1102
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1103
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1104
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1105
    public SSLContext sslContext() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1106
        return sslContext;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1107
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1108
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1109
    @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1110
    public SSLParameters sslParameters() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1111
        return Utils.copySSLParameters(sslParams);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1112
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1113
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1114
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1115
    public Optional<Authenticator> authenticator() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1116
        return Optional.ofNullable(authenticator);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1117
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1118
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
  1119
    /*package-private*/ final DelegatingExecutor theExecutor() {
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
  1120
        return delegatingExecutor;
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1121
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1122
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1123
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1124
    public final Optional<Executor> executor() {
50681
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
  1125
        return isDefaultExecutor
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
  1126
                ? Optional.empty()
4254bed3c09d 8204679: HTTP Client refresh
chegar
parents: 49944
diff changeset
  1127
                : Optional.of(delegatingExecutor.delegate());
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1128
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1129
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1130
    ConnectionPool connectionPool() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1131
        return connections;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1132
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1133
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1134
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1135
    public Redirect followRedirects() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1136
        return followRedirects;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1137
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1138
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1139
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1140
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1141
    public Optional<CookieHandler> cookieHandler() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1142
        return Optional.ofNullable(cookieHandler);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1143
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1144
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1145
    @Override
51364
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
  1146
    public Optional<Duration> connectTimeout() {
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
  1147
        return Optional.ofNullable(connectTimeout);
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
  1148
    }
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
  1149
31d9e82b2e64 8208391: Differentiate response and connect timeouts in HTTP Client API
chegar
parents: 50985
diff changeset
  1150
    @Override
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1151
    public Optional<ProxySelector> proxy() {
53387
c9622e15ba29 8216561: HttpClient: The logic of retry on connect exception is inverted
dfuchs
parents: 53256
diff changeset
  1152
        return Optional.ofNullable(userProxySelector);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1153
    }
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1154
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1155
    // Return the effective proxy that this client uses.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1156
    ProxySelector proxySelector() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1157
        return proxySelector;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1158
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1159
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1160
    @Override
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1161
    public WebSocket.Builder newWebSocketBuilder() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1162
        // Make sure to pass the HttpClientFacade to the WebSocket builder.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1163
        // This will ensure that the facade is not released before the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1164
        // WebSocket has been created, at which point the pendingOperationCount
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1165
        // will have been incremented by the RawChannelTube.
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1166
        // See RawChannelTube.
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1167
        return new BuilderImpl(this.facade(), proxySelector);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1168
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1169
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1170
    @Override
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1171
    public Version version() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1172
        return version;
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1173
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1174
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1175
    String dbgString() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1176
        return dbgTag;
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1177
    }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1178
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1179
    @Override
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1180
    public String toString() {
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1181
        // Used by tests to get the client's id and compute the
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1182
        // name of the SelectorManager thread.
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1183
        return super.toString() + ("(" + id + ")");
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1184
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1185
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1186
    private void initFilters() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1187
        addFilter(AuthenticationFilter.class);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1188
        addFilter(RedirectFilter.class);
48083
b1c1b4ef4be2 8191494: Refresh incubating HTTP Client
chegar
parents: 47216
diff changeset
  1189
        if (this.cookieHandler != null) {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1190
            addFilter(CookieFilter.class);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1191
        }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1192
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1193
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1194
    private void addFilter(Class<? extends HeaderFilter> f) {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1195
        filters.addFilter(f);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1196
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1197
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1198
    final LinkedList<HeaderFilter> filterChain() {
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1199
        return filters.getFilterChain();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1200
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1201
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1202
    // Timer controls.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1203
    // Timers are implemented through timed Selector.select() calls.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1204
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1205
    synchronized void registerTimer(TimeoutEvent event) {
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1206
        Log.logTrace("Registering timer {0}", event);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1207
        timeouts.add(event);
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1208
        selmgr.wakeupSelector();
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1209
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1210
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1211
    synchronized void cancelTimer(TimeoutEvent event) {
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1212
        Log.logTrace("Canceling timer {0}", event);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1213
        timeouts.remove(event);
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1214
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1215
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1216
    /**
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1217
     * Purges ( handles ) timer events that have passed their deadline, and
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1218
     * returns the amount of time, in milliseconds, until the next earliest
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1219
     * event. A return value of 0 means that there are no events.
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1220
     */
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1221
    private long purgeTimeoutsAndReturnNextDeadline() {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1222
        long diff = 0L;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1223
        List<TimeoutEvent> toHandle = null;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1224
        int remaining = 0;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1225
        // enter critical section to retrieve the timeout event to handle
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1226
        synchronized(this) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1227
            if (timeouts.isEmpty()) return 0L;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1228
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1229
            Instant now = Instant.now();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1230
            Iterator<TimeoutEvent> itr = timeouts.iterator();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1231
            while (itr.hasNext()) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1232
                TimeoutEvent event = itr.next();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1233
                diff = now.until(event.deadline(), ChronoUnit.MILLIS);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1234
                if (diff <= 0) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1235
                    itr.remove();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1236
                    toHandle = (toHandle == null) ? new ArrayList<>() : toHandle;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1237
                    toHandle.add(event);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1238
                } else {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1239
                    break;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1240
                }
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1241
            }
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1242
            remaining = timeouts.size();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1243
        }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1244
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1245
        // can be useful for debugging
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1246
        if (toHandle != null && Log.trace()) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1247
            Log.logTrace("purgeTimeoutsAndReturnNextDeadline: handling "
49765
ee6f7a61f3a5 8197564: HTTP Client implementation
chegar
parents: 48263
diff changeset
  1248
                    +  toHandle.size() + " events, "
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1249
                    + "remaining " + remaining
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1250
                    + ", next deadline: " + (diff < 0 ? 0L : diff));
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1251
        }
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1252
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1253
        // handle timeout events out of critical section
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1254
        if (toHandle != null) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1255
            Throwable failed = null;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1256
            for (TimeoutEvent event : toHandle) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1257
                try {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1258
                   Log.logTrace("Firing timer {0}", event);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1259
                   event.handle();
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1260
                } catch (Error | RuntimeException e) {
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1261
                    // Not expected. Handle remaining events then throw...
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1262
                    // If e is an OOME or SOE it might simply trigger a new
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1263
                    // error from here - but in this case there's not much we
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1264
                    // could do anyway. Just let it flow...
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1265
                    if (failed == null) failed = e;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1266
                    else failed.addSuppressed(e);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1267
                    Log.logTrace("Failed to handle event {0}: {1}", event, e);
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1268
                }
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1269
            }
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1270
            if (failed instanceof Error) throw (Error) failed;
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1271
            if (failed instanceof RuntimeException) throw (RuntimeException) failed;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1272
        }
44639
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1273
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1274
        // return time to wait until next event. 0L if there's no more events.
5c2838d882a5 8178147: Race conditions in timeout handling code in http/2 incubator client
dfuchs
parents: 43984
diff changeset
  1275
        return diff < 0 ? 0L : diff;
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1276
    }
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1277
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1278
    // used for the connection window
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1279
    int getReceiveBufferSize() {
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1280
        return Utils.getIntegerNetProperty(
49944
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1281
                "jdk.httpclient.receiveBufferSize",
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1282
                0 // only set the size if > 0
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1283
        );
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1284
    }
49944
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1285
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1286
    // Optimization for reading SSL encrypted data
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1287
    // --------------------------------------------
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1288
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1289
    // Returns a BufferSupplier that can be used for reading
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1290
    // encrypted bytes of the channel. These buffers can then
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1291
    // be recycled by the SSLFlowDelegate::Reader after their
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1292
    // content has been copied in the SSLFlowDelegate::Reader
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1293
    // readBuf.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1294
    // Because allocating, reading, copying, and recycling
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1295
    // all happen in the SelectorManager thread,
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1296
    // then this BufferSupplier can be shared between all
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1297
    // the SSL connections managed by this client.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1298
    BufferSupplier getSSLBufferSupplier() {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1299
        return sslBufferSupplier;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1300
    }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1301
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1302
    // An implementation of BufferSupplier that manages a pool of
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1303
    // maximum 3 direct byte buffers (SocketTube.MAX_BUFFERS) that
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1304
    // are used for reading encrypted bytes off the channel before
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1305
    // copying and subsequent unwrapping.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1306
    private static final class SSLDirectBufferSupplier implements BufferSupplier {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1307
        private static final int POOL_SIZE = SocketTube.MAX_BUFFERS;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1308
        private final ByteBuffer[] pool = new ByteBuffer[POOL_SIZE];
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1309
        private final HttpClientImpl client;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1310
        private final Logger debug;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1311
        private int tail, count; // no need for volatile: only accessed in SM thread.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1312
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1313
        SSLDirectBufferSupplier(HttpClientImpl client) {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1314
            this.client = Objects.requireNonNull(client);
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1315
            this.debug = client.debug;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1316
        }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1317
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1318
        // Gets a buffer from the pool, or allocates a new one if needed.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1319
        @Override
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1320
        public ByteBuffer get() {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1321
            assert client.isSelectorThread();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1322
            assert tail <= POOL_SIZE : "allocate tail is " + tail;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1323
            ByteBuffer buf;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1324
            if (tail == 0) {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1325
                if (debug.on()) {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1326
                    // should not appear more than SocketTube.MAX_BUFFERS
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1327
                    debug.log("ByteBuffer.allocateDirect(%d)", Utils.BUFSIZE);
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1328
                }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1329
                assert count++ < POOL_SIZE : "trying to allocate more than "
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1330
                            + POOL_SIZE + " buffers";
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1331
                buf = ByteBuffer.allocateDirect(Utils.BUFSIZE);
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1332
            } else {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1333
                assert tail > 0 : "non positive tail value: " + tail;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1334
                tail--;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1335
                buf = pool[tail];
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1336
                pool[tail] = null;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1337
            }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1338
            assert buf.isDirect();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1339
            assert buf.position() == 0;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1340
            assert buf.hasRemaining();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1341
            assert buf.limit() == Utils.BUFSIZE;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1342
            assert tail < POOL_SIZE;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1343
            assert tail >= 0;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1344
            return buf;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1345
        }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1346
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1347
        // Returns the given buffer to the pool.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1348
        @Override
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1349
        public void recycle(ByteBuffer buffer) {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1350
            assert client.isSelectorThread();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1351
            assert buffer.isDirect();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1352
            assert !buffer.hasRemaining();
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1353
            assert tail < POOL_SIZE : "recycle tail is " + tail;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1354
            assert tail >= 0;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1355
            buffer.position(0);
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1356
            buffer.limit(buffer.capacity());
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1357
            // don't fail if assertions are off. we have asserted above.
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1358
            if (tail < POOL_SIZE) {
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1359
                pool[tail] = buffer;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1360
                tail++;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1361
            }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1362
            assert tail <= POOL_SIZE;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1363
            assert tail > 0;
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1364
        }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1365
    }
4690a2871b44 8202423: Small HTTP Client refresh
chegar
parents: 49765
diff changeset
  1366
42460
7133f144981a 8170648: Move java.net.http package out of Java SE to incubator namespace
michaelm
parents:
diff changeset
  1367
}