Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
Expand All @@ -42,8 +41,12 @@
import java.util.concurrent.Flow;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import jdk.internal.net.http.common.Deadline;
import jdk.internal.net.http.common.FlowTube;
import jdk.internal.net.http.common.Logger;
import jdk.internal.net.http.common.TimeLine;
import jdk.internal.net.http.common.TimeSource;
import jdk.internal.net.http.common.Utils;
import static jdk.internal.net.http.HttpClientImpl.KEEP_ALIVE_TIMEOUT; //seconds

Expand All @@ -63,6 +66,7 @@ final class ConnectionPool {
private final HashMap<CacheKey,LinkedList<HttpConnection>> sslPool;
private final ExpiryList expiryList;
private final String dbgTag; // used for debug
private final TimeLine timeSource;
volatile boolean stopped;

/**
Expand Down Expand Up @@ -124,17 +128,22 @@ public int hashCode() {
}

ConnectionPool(long clientId) {
this("ConnectionPool("+clientId+")");
this(clientId, TimeSource.source());
}

/**
* There should be one of these per HttpClient.
*/
private ConnectionPool(String tag) {
ConnectionPool(long clientId, TimeLine timeSource) {
this("ConnectionPool("+clientId+")", Objects.requireNonNull(timeSource));
}

/**
* There should be one of these per HttpClient.
*/
private ConnectionPool(String tag, TimeLine timeSource) {
dbgTag = tag;
plainPool = new HashMap<>();
sslPool = new HashMap<>();
expiryList = new ExpiryList();
this.timeSource = timeSource;
this.expiryList = new ExpiryList(timeSource);
}

final String dbgString() {
Expand Down Expand Up @@ -181,11 +190,11 @@ private HttpConnection getConnection0(boolean secure,
* Returns the connection to the pool.
*/
void returnToPool(HttpConnection conn) {
returnToPool(conn, Instant.now(), KEEP_ALIVE_TIMEOUT);
returnToPool(conn, timeSource.instant(), KEEP_ALIVE_TIMEOUT);
}

// Called also by whitebox tests
void returnToPool(HttpConnection conn, Instant now, long keepAlive) {
void returnToPool(HttpConnection conn, Deadline now, long keepAlive) {

assert (conn instanceof PlainHttpConnection) || conn.isSecure()
: "Attempting to return unsecure connection to SSL pool: "
Expand Down Expand Up @@ -291,11 +300,11 @@ private CleanupTrigger registerCleanupTrigger(HttpConnection conn) {
*/
long purgeExpiredConnectionsAndReturnNextDeadline() {
if (!expiryList.purgeMaybeRequired()) return 0;
return purgeExpiredConnectionsAndReturnNextDeadline(Instant.now());
return purgeExpiredConnectionsAndReturnNextDeadline(timeSource.instant());
}

// Used for whitebox testing
long purgeExpiredConnectionsAndReturnNextDeadline(Instant now) {
long purgeExpiredConnectionsAndReturnNextDeadline(Deadline now) {
long nextPurge = 0;

// We may be in the process of adding new elements
Expand Down Expand Up @@ -355,8 +364,8 @@ void stop() {

static final class ExpiryEntry {
final HttpConnection connection;
final Instant expiry; // absolute time in seconds of expiry time
ExpiryEntry(HttpConnection connection, Instant expiry) {
final Deadline expiry; // absolute time in seconds of expiry time
ExpiryEntry(HttpConnection connection, Deadline expiry) {
this.connection = connection;
this.expiry = expiry;
}
Expand All @@ -371,8 +380,13 @@ static final class ExpiryEntry {
*/
private static final class ExpiryList {
private final LinkedList<ExpiryEntry> list = new LinkedList<>();
private final TimeLine timeSource;
private volatile boolean mayContainEntries;

ExpiryList(TimeLine timeSource) {
this.timeSource = timeSource;
}

int size() { return list.size(); }

// A loosely accurate boolean whose value is computed
Expand All @@ -384,7 +398,7 @@ boolean purgeMaybeRequired() {

// Returns the next expiry deadline
// should only be called while holding the ConnectionPool stateLock.
Optional<Instant> nextExpiryDeadline() {
Optional<Deadline> nextExpiryDeadline() {
if (list.isEmpty()) return Optional.empty();
else return Optional.of(list.getLast().expiry);
}
Expand All @@ -397,12 +411,12 @@ HttpConnection removeOldest() {

// should only be called while holding the ConnectionPool stateLock.
void add(HttpConnection conn) {
add(conn, Instant.now(), KEEP_ALIVE_TIMEOUT);
add(conn, timeSource.instant(), KEEP_ALIVE_TIMEOUT);
}

// Used by whitebox test.
void add(HttpConnection conn, Instant now, long keepAlive) {
Instant then = now.truncatedTo(ChronoUnit.SECONDS)
void add(HttpConnection conn, Deadline now, long keepAlive) {
Deadline then = now.truncatedTo(ChronoUnit.SECONDS)
.plus(keepAlive, ChronoUnit.SECONDS);

// Elements with the farther deadline are at the head of
Expand Down Expand Up @@ -444,7 +458,7 @@ void remove(HttpConnection c) {

// should only be called while holding the ConnectionPool stateLock.
// Purge all elements whose deadline is before now (now included).
List<HttpConnection> purgeUntil(Instant now) {
List<HttpConnection> purgeUntil(Deadline now) {
if (list.isEmpty()) return Collections.emptyList();

List<HttpConnection> closelist = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashSet;
Expand Down Expand Up @@ -87,11 +86,13 @@
import java.net.http.WebSocket;

import jdk.internal.net.http.common.BufferSupplier;
import jdk.internal.net.http.common.Deadline;
import jdk.internal.net.http.common.HttpBodySubscriberWrapper;
import jdk.internal.net.http.common.Log;
import jdk.internal.net.http.common.Logger;
import jdk.internal.net.http.common.MinimalFuture;
import jdk.internal.net.http.common.Pair;
import jdk.internal.net.http.common.TimeSource;
import jdk.internal.net.http.common.Utils;
import jdk.internal.net.http.common.OperationTrackers.Trackable;
import jdk.internal.net.http.common.OperationTrackers.Tracker;
Expand Down Expand Up @@ -1745,7 +1746,7 @@ private long purgeTimeoutsAndReturnNextDeadline() {
synchronized (this) {
if (timeouts.isEmpty()) return 0L;

Instant now = Instant.now();
Deadline now = TimeSource.now();
Iterator<TimeoutEvent> itr = timeouts.iterator();
while (itr.hasNext()) {
TimeoutEvent event = itr.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import jdk.internal.net.http.common.FlowTube;
import jdk.internal.net.http.common.Log;
import jdk.internal.net.http.common.MinimalFuture;
import jdk.internal.net.http.common.TimeSource;
import jdk.internal.net.http.common.Utils;

/**
Expand Down Expand Up @@ -290,7 +291,7 @@ private boolean canRetryConnect(Throwable e) {
if (unsuccessfulAttempts > 0) return false;
ConnectTimerEvent timer = connectTimerEvent;
if (timer == null) return true;
return timer.deadline().isAfter(Instant.now());
return timer.deadline().isAfter(TimeSource.now());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -29,6 +29,9 @@
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;

import jdk.internal.net.http.common.Deadline;
import jdk.internal.net.http.common.TimeSource;

/**
* Timeout event notified by selector thread. Executes the given handler if
* the timer not canceled first.
Expand All @@ -44,16 +47,16 @@ abstract class TimeoutEvent implements Comparable<TimeoutEvent> {
// see TimeoutEvent::compareTo below;
private final long id = COUNTER.incrementAndGet();
private final Duration duration;
private final Instant deadline;
private final Deadline deadline;

TimeoutEvent(Duration duration) {
this.duration = duration;
deadline = Instant.now().plus(duration);
deadline = TimeSource.now().plus(duration);
}

public abstract void handle();

public Instant deadline() {
public Deadline deadline() {
return deadline;
}

Expand Down
Loading