src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java
changeset 51364 31d9e82b2e64
parent 50681 4254bed3c09d
child 52196 420445d16008
child 56868 67c7659ecda5
equal deleted inserted replaced
51363:a6fa2016cff1 51364:31d9e82b2e64
    25 
    25 
    26 package jdk.internal.net.http;
    26 package jdk.internal.net.http;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.net.ConnectException;
    29 import java.net.ConnectException;
    30 import java.time.Duration;
    30 import java.net.http.HttpConnectTimeoutException;
    31 import java.util.Iterator;
    31 import java.util.Iterator;
    32 import java.util.LinkedList;
    32 import java.util.LinkedList;
    33 import java.security.AccessControlContext;
    33 import java.security.AccessControlContext;
    34 import java.util.concurrent.CompletableFuture;
    34 import java.util.concurrent.CompletableFuture;
    35 import java.util.concurrent.CompletionException;
    35 import java.util.concurrent.CompletionException;
    86     static final int max_attempts = Utils.getIntegerNetProperty(
    86     static final int max_attempts = Utils.getIntegerNetProperty(
    87             "jdk.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
    87             "jdk.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
    88     );
    88     );
    89 
    89 
    90     private final LinkedList<HeaderFilter> filters;
    90     private final LinkedList<HeaderFilter> filters;
    91     TimedEvent timedEvent;
    91     ResponseTimerEvent responseTimerEvent;
    92     volatile boolean cancelled;
    92     volatile boolean cancelled;
    93     final PushGroup<T> pushGroup;
    93     final PushGroup<T> pushGroup;
    94 
    94 
    95     /**
    95     /**
    96      * Filter fields. These are attached as required by filters
    96      * Filter fields. These are attached as required by filters
   132         }
   132         }
   133 
   133 
   134         this.exchange = new Exchange<>(request, this);
   134         this.exchange = new Exchange<>(request, this);
   135     }
   135     }
   136 
   136 
   137     private synchronized Exchange<T> getExchange() {
   137     synchronized Exchange<T> getExchange() {
   138         return exchange;
   138         return exchange;
   139     }
   139     }
   140 
   140 
   141     HttpClientImpl client() {
   141     HttpClientImpl client() {
   142         return client;
   142         return client;
   155         }
   155         }
   156         this.exchange = exchange;
   156         this.exchange = exchange;
   157     }
   157     }
   158 
   158 
   159     private void cancelTimer() {
   159     private void cancelTimer() {
   160         if (timedEvent != null) {
   160         if (responseTimerEvent != null) {
   161             client.cancelTimer(timedEvent);
   161             client.cancelTimer(responseTimerEvent);
   162         }
   162         }
   163     }
   163     }
   164 
   164 
   165     private void requestFilters(HttpRequestImpl r) throws IOException {
   165     private void requestFilters(HttpRequestImpl r) throws IOException {
   166         Log.logTrace("Applying request filters");
   166         Log.logTrace("Applying request filters");
   218         CompletableFuture<Response> cf;
   218         CompletableFuture<Response> cf;
   219         if (attempts.incrementAndGet() > max_attempts) {
   219         if (attempts.incrementAndGet() > max_attempts) {
   220             cf = failedFuture(new IOException("Too many retries", retryCause));
   220             cf = failedFuture(new IOException("Too many retries", retryCause));
   221         } else {
   221         } else {
   222             if (currentreq.timeout().isPresent()) {
   222             if (currentreq.timeout().isPresent()) {
   223                 timedEvent = new TimedEvent(currentreq.timeout().get());
   223                 responseTimerEvent = ResponseTimerEvent.of(this);
   224                 client.registerTimer(timedEvent);
   224                 client.registerTimer(responseTimerEvent);
   225             }
   225             }
   226             try {
   226             try {
   227                 // 1. apply request filters
   227                 // 1. apply request filters
   228                 // if currentreq == previousreq the filters have already
   228                 // if currentreq == previousreq the filters have already
   229                 // been applied once. Applying them a second time might
   229                 // been applied once. Applying them a second time might
   342             if (t.getCause() != null) {
   342             if (t.getCause() != null) {
   343                 t = t.getCause();
   343                 t = t.getCause();
   344             }
   344             }
   345         }
   345         }
   346         if (cancelled && t instanceof IOException) {
   346         if (cancelled && t instanceof IOException) {
   347             t = new HttpTimeoutException("request timed out");
   347             if (!(t instanceof HttpTimeoutException)) {
       
   348                 t = toTimeoutException((IOException)t);
       
   349             }
   348         } else if (retryOnFailure(t)) {
   350         } else if (retryOnFailure(t)) {
   349             Throwable cause = retryCause(t);
   351             Throwable cause = retryCause(t);
   350 
   352 
   351             if (!(t instanceof ConnectException)) {
   353             if (!(t instanceof ConnectException)) {
   352                 if (!canRetryRequest(currentreq)) {
   354                 if (!canRetryRequest(currentreq)) {
   376             }
   378             }
   377         }
   379         }
   378         return failedFuture(t);
   380         return failedFuture(t);
   379     }
   381     }
   380 
   382 
   381     class TimedEvent extends TimeoutEvent {
   383     private HttpTimeoutException toTimeoutException(IOException ioe) {
   382         TimedEvent(Duration duration) {
   384         HttpTimeoutException t = null;
   383             super(duration);
   385 
   384         }
   386         // more specific, "request timed out", when connected
   385         @Override
   387         Exchange<?> exchange = getExchange();
   386         public void handle() {
   388         if (exchange != null) {
   387             if (debug.on()) {
   389             ExchangeImpl<?> exchangeImpl = exchange.exchImpl;
   388                 debug.log("Cancelling MultiExchange due to timeout for request %s",
   390             if (exchangeImpl != null) {
   389                         request);
   391                 if (exchangeImpl.connection().connected()) {
   390             }
   392                     t = new HttpTimeoutException("request timed out");
   391             cancel(new HttpTimeoutException("request timed out"));
   393                     t.initCause(ioe);
   392         }
   394                 }
       
   395             }
       
   396         }
       
   397         if (t == null) {
       
   398             t = new HttpConnectTimeoutException("HTTP connect timed out");
       
   399             t.initCause(new ConnectException("HTTP connect timed out"));
       
   400         }
       
   401         return t;
   393     }
   402     }
   394 }
   403 }