You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ab...@apache.org on 2026/10/05 08:46:32 UTC
(httpcomponents-core) branch master updated: Restore absolute millisecond timestamps in I/O reactor and H2
This is an automated email from the ASF dual-hosted git repository.
arturobernalg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/master by this push:
new 89508f9aa Restore absolute millisecond timestamps in I/O reactor and H2
89508f9aa is described below
commit 89508f9aa6dee849e228386afc40b3ffa7c9f6c1
Author: Arturo Bernal <ab...@apache.org>
AuthorDate: Fri Oct 2 10:07:33 2026 +0200
Restore absolute millisecond timestamps in I/O reactor and H2
Restore the pre-#660 timestamp model for shared reactor and H2 state.
Use absolute millisecond timestamps for IOSession and connection-level
inactivity accounting, while retaining monotonic time for local
elapsed-time calculations.
---
.../impl/nio/AbstractH2StreamMultiplexer.java | 33 +++++++++++-----------
.../apache/hc/core5/http2/impl/nio/H2Stream.java | 7 ++---
.../hc/core5/http2/impl/nio/H2StreamChannel.java | 4 +--
.../apache/hc/core5/http2/nio/pool/H2ConnPool.java | 4 +--
.../impl/nio/TestAbstractH2StreamMultiplexer.java | 18 ++++++------
.../hc/core5/http2/nio/pool/TestH2ConnPool.java | 6 ++--
.../core5/reactor/AbstractSingleCoreIOReactor.java | 10 +++----
.../org/apache/hc/core5/reactor/IOSession.java | 13 ++++-----
.../org/apache/hc/core5/reactor/IOSessionImpl.java | 14 ++++-----
.../apache/hc/core5/reactor/IOSessionRequest.java | 4 +--
.../org/apache/hc/core5/reactor/IOWorkerStats.java | 2 +-
.../apache/hc/core5/reactor/InternalChannel.java | 8 +++---
.../hc/core5/reactor/InternalConnectChannel.java | 10 +++----
.../hc/core5/reactor/MultiCoreIOReactor.java | 18 ++++++------
.../hc/core5/reactor/SingleCoreIOReactor.java | 27 ++++++++----------
.../hc/core5/reactor/TestInternalChannel.java | 7 ++---
.../reactor/TestSocksProxyProtocolHandler.java | 10 +++----
17 files changed, 92 insertions(+), 103 deletions(-)
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
index c71026148..95df8395e 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
@@ -38,7 +38,6 @@
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -147,13 +146,13 @@ enum SettingsHandshake { READY, TRANSMITTED, ACKED }
private volatile boolean peerNoRfc7540Priorities;
- private static final long STREAM_TIMEOUT_GRANULARITY_NANOS = TimeUnit.SECONDS.toNanos(1);
- private long lastStreamTimeoutCheckNanos;
+ private static final long STREAM_TIMEOUT_GRANULARITY_MILLIS = 1000;
+ private long lastStreamTimeoutCheckMillis;
- private static final long VALIDATE_AFTER_INACTIVITY_GRANULARITY_NANOS = TimeUnit.SECONDS.toNanos(1);
+ private static final long VALIDATE_AFTER_INACTIVITY_GRANULARITY_MILLIS = 1000;
private final Timeout validateAfterInactivity;
private final Timeout pingAckTimeout;
- private volatile long lastActivityNanos;
+ private volatile long lastActivityTime;
AbstractH2StreamMultiplexer(
final ProtocolIOSession ioSession,
@@ -214,7 +213,7 @@ enum SettingsHandshake { READY, TRANSMITTED, ACKED }
this.hPackDecoder.setMaxListSize(this.localConfig.getMaxHeaderListSize());
this.lowMark = H2Config.INIT.getInitialWindowSize() / 2;
this.streamListener = streamListener;
- this.lastActivityNanos = System.nanoTime();
+ this.lastActivityTime = System.currentTimeMillis();
this.validateAfterInactivity = validateAfterInactivity;
this.pingAckTimeout = Args.notNull(pingAckTimeout, "PING ACK timeout");
}
@@ -560,8 +559,8 @@ public final void onOutput() throws HttpException, IOException {
if (connState.compareTo(ConnectionHandshake.ACTIVE) <= 0 && remoteSettingState == SettingsHandshake.ACKED) {
final long t = TimeValue.isPositive(validateAfterInactivity) ?
- Math.max(validateAfterInactivity.toNanoseconds(), VALIDATE_AFTER_INACTIVITY_GRANULARITY_NANOS) : 0;
- final boolean hasBeenIdleTooLong = t > 0 && System.nanoTime() - lastActivityNanos > t;
+ Math.max(validateAfterInactivity.toMilliseconds(), VALIDATE_AFTER_INACTIVITY_GRANULARITY_MILLIS) : 0;
+ final boolean hasBeenIdleTooLong = t > 0 && System.currentTimeMillis() - lastActivityTime > t;
if (hasBeenIdleTooLong && ioSession.hasCommands() && pingHandlers.isEmpty()) {
final Timeout socketTimeout = ioSession.getSocketTimeout();
ioSession.setSocketTimeout(pingAckTimeout);
@@ -1545,7 +1544,7 @@ class H2StreamChannelImpl implements H2StreamChannel {
private final AtomicInteger outputWindow;
private volatile boolean localClosed;
- private volatile long localResetNanos = Long.MIN_VALUE;
+ private volatile long localResetTime;
H2StreamChannelImpl(final int id, final int initialInputWindowSize, final int initialOutputWindowSize) {
this.id = id;
@@ -1710,7 +1709,7 @@ public boolean localReset(final int code) throws IOException {
return false;
}
localClosed = true;
- localResetNanos = System.nanoTime();
+ localResetTime = System.currentTimeMillis();
final RawFrame resetStream = frameFactory.createResetStream(id, code);
commitFrameInternal(resetStream);
@@ -1721,8 +1720,8 @@ public boolean localReset(final int code) throws IOException {
}
@Override
- public long getLocalResetNanos() {
- return localResetNanos;
+ public long getLocalResetTime() {
+ return localResetTime;
}
@Override
@@ -1777,14 +1776,14 @@ private void checkStreamTimeouts(final long nowNanos) throws IOException {
}
private void validateStreamTimeouts() throws IOException {
- final long nowNanos = System.nanoTime();
- if ((nowNanos - lastStreamTimeoutCheckNanos) >= STREAM_TIMEOUT_GRANULARITY_NANOS) {
- lastStreamTimeoutCheckNanos = nowNanos;
- checkStreamTimeouts(nowNanos);
+ final long nowMillis = System.currentTimeMillis();
+ if ((nowMillis - lastStreamTimeoutCheckMillis) >= STREAM_TIMEOUT_GRANULARITY_MILLIS) {
+ lastStreamTimeoutCheckMillis = nowMillis;
+ checkStreamTimeouts(System.nanoTime());
}
}
private void updateLastActivity() {
- this.lastActivityNanos = System.nanoTime();
+ this.lastActivityTime = System.currentTimeMillis();
}
}
\ No newline at end of file
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2Stream.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2Stream.java
index 88081f695..ad080cecc 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2Stream.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2Stream.java
@@ -32,7 +32,6 @@
import java.nio.channels.CancelledKeyException;
import java.nio.charset.CharacterCodingException;
import java.util.List;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -51,7 +50,7 @@
class H2Stream implements StreamControl {
- private static final long LINGER_TIME_NANOS = TimeUnit.SECONDS.toNanos(1);
+ private static final long LINGER_TIME = 1000; // 1 second
private final H2StreamChannel channel;
private final H2StreamHandler handler;
@@ -125,8 +124,8 @@ AtomicInteger getInputWindow() {
}
private boolean isPastLingerDeadline() {
- final long localResetNanos = channel.getLocalResetNanos();
- return localResetNanos != Long.MIN_VALUE && System.nanoTime() - localResetNanos > LINGER_TIME_NANOS;
+ final long localResetTime = channel.getLocalResetTime();
+ return localResetTime > 0 && localResetTime + LINGER_TIME < System.currentTimeMillis();
}
boolean isClosedPastLingerDeadline() {
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2StreamChannel.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2StreamChannel.java
index ed99bcf4f..d86159ef9 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2StreamChannel.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/H2StreamChannel.java
@@ -68,10 +68,10 @@ default void terminate() {
}
}
- long getLocalResetNanos();
+ long getLocalResetTime();
default boolean isLocalReset() {
- return getLocalResetNanos() != Long.MIN_VALUE;
+ return getLocalResetTime() > 0;
}
}
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
index fae155bd2..42d189650 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/nio/pool/H2ConnPool.java
@@ -143,8 +143,8 @@ protected void validateSession(
final TimeValue timeValue = validateAfterInactivity;
if (TimeValue.isNonNegative(timeValue)) {
final long lastAccessTime = Math.min(ioSession.getLastReadTime(), ioSession.getLastWriteTime());
- final long deadline = lastAccessTime + timeValue.toNanoseconds();
- if (deadline <= System.nanoTime()) {
+ final long deadline = lastAccessTime + timeValue.toMilliseconds();
+ if (deadline <= System.currentTimeMillis()) {
ioSession.enqueue(new StaleCheckCommand(callback::execute), Command.Priority.NORMAL);
return;
}
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
index 6b665c3f0..23a02b1c8 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
@@ -1893,23 +1893,23 @@ void testKeepAliveDisabledNeverEmitsPing() throws Exception {
Assertions.assertTrue(frames.stream().noneMatch(FrameStub::isPing), "Disabled policy must never emit PING");
}
- private static long getValidateAfterInactivityGranularityNanos() throws Exception {
- final Field field = AbstractH2StreamMultiplexer.class.getDeclaredField("VALIDATE_AFTER_INACTIVITY_GRANULARITY_NANOS");
+ private static long getValidateAfterInactivityGranularityMillis() throws Exception {
+ final Field field = AbstractH2StreamMultiplexer.class.getDeclaredField("VALIDATE_AFTER_INACTIVITY_GRANULARITY_MILLIS");
field.setAccessible(true);
return field.getLong(null);
}
- private static void setLastActivityNanos(final AbstractH2StreamMultiplexer mux, final long nanos) throws Exception {
- final Field field = AbstractH2StreamMultiplexer.class.getDeclaredField("lastActivityNanos");
+ private static void setLastActivityTime(final AbstractH2StreamMultiplexer mux, final long millis) throws Exception {
+ final Field field = AbstractH2StreamMultiplexer.class.getDeclaredField("lastActivityTime");
field.setAccessible(true);
- field.setLong(mux, nanos);
+ field.setLong(mux, millis);
}
private static void makeMuxIdle(final AbstractH2StreamMultiplexer mux, final Timeout validateAfterInactivity) throws Exception {
- final long granularityNanos = getValidateAfterInactivityGranularityNanos();
- final long configuredNanos = validateAfterInactivity != null ? validateAfterInactivity.toNanoseconds() : 0;
- final long effectiveNanos = configuredNanos > 0 ? Math.max(configuredNanos, granularityNanos) : 0;
- setLastActivityNanos(mux, System.nanoTime() - effectiveNanos - TimeUnit.MILLISECONDS.toNanos(10));
+ final long granularityMillis = getValidateAfterInactivityGranularityMillis();
+ final long configuredMillis = validateAfterInactivity != null ? validateAfterInactivity.toMilliseconds() : 0;
+ final long effectiveMillis = configuredMillis > 0 ? Math.max(configuredMillis, granularityMillis) : 0;
+ setLastActivityTime(mux, System.currentTimeMillis() - effectiveMillis - 10);
}
@Test
diff --git a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/nio/pool/TestH2ConnPool.java b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/nio/pool/TestH2ConnPool.java
index 83651e603..b9bf2558c 100644
--- a/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/nio/pool/TestH2ConnPool.java
+++ b/httpcore5-h2/src/test/java/org/apache/hc/core5/http2/nio/pool/TestH2ConnPool.java
@@ -28,7 +28,6 @@
import java.net.InetSocketAddress;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.hc.core5.concurrent.FutureCallback;
@@ -98,9 +97,8 @@ void testValidateSessionEnqueuesStaleCheck() {
final IOSession session = Mockito.mock(IOSession.class);
Mockito.when(session.isOpen()).thenReturn(true);
- final long farPastNanos = System.nanoTime() - TimeUnit.DAYS.toNanos(1);
- Mockito.when(session.getLastReadTime()).thenReturn(farPastNanos);
- Mockito.when(session.getLastWriteTime()).thenReturn(farPastNanos);
+ Mockito.when(session.getLastReadTime()).thenReturn(0L);
+ Mockito.when(session.getLastWriteTime()).thenReturn(0L);
@SuppressWarnings("unchecked")
final Callback<Boolean> callback = (Callback<Boolean>) Mockito.mock(Callback.class);
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractSingleCoreIOReactor.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractSingleCoreIOReactor.java
index 2d59f07e9..fc3de36f1 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractSingleCoreIOReactor.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/AbstractSingleCoreIOReactor.java
@@ -109,14 +109,14 @@ public void execute() {
@Override
public final void awaitShutdown(final TimeValue waitTime) throws InterruptedException {
Args.notNull(waitTime, "Wait time");
- final long deadlineNanos = System.nanoTime() + waitTime.toNanoseconds();
- long remainingNanos = waitTime.toNanoseconds();
+ final long deadline = System.currentTimeMillis() + waitTime.toMilliseconds();
+ long remaining = waitTime.toMilliseconds();
lock.lock();
try {
while (this.status.get().compareTo(IOReactorStatus.SHUT_DOWN) < 0) {
- condition.await(remainingNanos, TimeUnit.NANOSECONDS);
- remainingNanos = deadlineNanos - System.nanoTime();
- if (remainingNanos <= 0) {
+ condition.await(remaining, TimeUnit.MILLISECONDS);
+ remaining = deadline - System.currentTimeMillis();
+ if (remaining <= 0) {
return;
}
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
index 51c0aebeb..4c2421cc4 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSession.java
@@ -208,26 +208,25 @@ enum Status {
void setSocketTimeout(Timeout timeout);
/**
- * Returns monotonic nanosecond timestamp of the last read event.
+ * Returns the absolute millisecond timestamp of the last read event.
*
- * @return nanosecond timestamp obtained from {@link System#nanoTime()}.
+ * @return timestamp in milliseconds, compatible with {@link System#currentTimeMillis()}.
*/
long getLastReadTime();
/**
- * Returns monotonic nanosecond timestamp of the last write event.
+ * Returns the absolute millisecond timestamp of the last write event.
*
- * @return nanosecond timestamp obtained from {@link System#nanoTime()}.
+ * @return timestamp in milliseconds, compatible with {@link System#currentTimeMillis()}.
*/
long getLastWriteTime();
/**
- * Returns monotonic nanosecond timestamp of the last I/O event including
- * socket timeout reset.
+ * Returns the absolute millisecond timestamp of the last I/O event including socket timeout reset.
*
* @see #getSocketTimeout()
*
- * @return nanosecond timestamp obtained from {@link System#nanoTime()}.
+ * @return timestamp in milliseconds, compatible with {@link System#currentTimeMillis()}.
*/
long getLastEventTime();
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
index 5ee78cd3d..d1421dc8c 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionImpl.java
@@ -88,10 +88,10 @@ public IOSessionImpl(final String type, final SelectionKey key, final SocketChan
this.id = String.format(type + "-%010d", COUNT.getAndIncrement());
this.handlerRef = new AtomicReference<>();
this.status = new AtomicReference<>(Status.ACTIVE);
- final long nowNanos = System.nanoTime();
- this.lastReadTime = nowNanos;
- this.lastWriteTime = nowNanos;
- this.lastEventTime = nowNanos;
+ final long currentTimeMillis = System.currentTimeMillis();
+ this.lastReadTime = currentTimeMillis;
+ this.lastWriteTime = currentTimeMillis;
+ this.lastEventTime = currentTimeMillis;
}
@Override
@@ -221,7 +221,7 @@ public Timeout getSocketTimeout() {
@Override
public void setSocketTimeout(final Timeout timeout) {
this.socketTimeout = Timeout.defaultsToInfinite(timeout);
- this.lastEventTime = System.nanoTime();
+ this.lastEventTime = System.currentTimeMillis();
}
@Override
@@ -255,13 +255,13 @@ public int write(final ByteBuffer src) throws IOException {
@Override
public void updateReadTime() {
- lastReadTime = System.nanoTime();
+ lastReadTime = System.currentTimeMillis();
lastEventTime = lastReadTime;
}
@Override
public void updateWriteTime() {
- lastWriteTime = System.nanoTime();
+ lastWriteTime = System.currentTimeMillis();
lastEventTime = lastWriteTime;
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
index ae25e10a6..57f727194 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOSessionRequest.java
@@ -73,7 +73,7 @@ public IOSessionRequest(
this.closeableRef = new AtomicReference<>();
// Set the time when this request is created
- this.enqueueTime = System.nanoTime();
+ this.enqueueTime = System.currentTimeMillis();
}
public void completed(final ProtocolIOSession ioSession) {
@@ -136,7 +136,7 @@ public String toString() {
// Getter for enqueueTime
@Internal
- public long getEnqueueNanos() {
+ public long getEnqueueTime() {
return enqueueTime;
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOWorkerStats.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOWorkerStats.java
index f17e75d0a..75ec5fea7 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOWorkerStats.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/IOWorkerStats.java
@@ -45,6 +45,6 @@ public interface IOWorkerStats {
int pendingChannelCount();
// Cheap
- long lastSelectNano();
+ long lastSelectMilli();
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalChannel.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalChannel.java
index ff18166a7..acf8c8afc 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalChannel.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalChannel.java
@@ -57,12 +57,12 @@ final void handleIOEvent(final int ops) {
}
}
- final boolean checkTimeout(final long nowNanos) {
+ final boolean checkTimeout(final long currentTimeMillis) {
final Timeout timeout = getTimeout();
if (!timeout.isDisabled()) {
- final long timeoutNanos = timeout.toNanoseconds();
- final long deadlineNanos = getLastEventTime() + timeoutNanos;
- if (nowNanos > deadlineNanos) {
+ final long timeoutMillis = timeout.toMilliseconds();
+ final long deadlineMillis = getLastEventTime() + timeoutMillis;
+ if (currentTimeMillis > deadlineMillis) {
try {
onTimeout(timeout);
} catch (final CancelledKeyException ex) {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalConnectChannel.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalConnectChannel.java
index e90161611..a69ca198a 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalConnectChannel.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/InternalConnectChannel.java
@@ -44,7 +44,7 @@ final class InternalConnectChannel extends InternalChannel {
private final InternalDataChannel dataChannel;
private final IOEventHandlerFactory eventHandlerFactory;
private final IOReactorConfig reactorConfig;
- private final long creationNanos;
+ private final long creationTimeMillis;
InternalConnectChannel(
final SelectionKey key,
@@ -60,7 +60,7 @@ final class InternalConnectChannel extends InternalChannel {
this.dataChannel = dataChannel;
this.eventHandlerFactory = eventHandlerFactory;
this.reactorConfig = reactorConfig;
- this.creationNanos = System.nanoTime();
+ this.creationTimeMillis = System.currentTimeMillis();
}
@Override
@@ -70,8 +70,8 @@ void onIOEvent(final int readyOps) throws IOException {
socketChannel.finishConnect();
}
//check out connectTimeout
- final long nowNanos = System.nanoTime();
- if (checkTimeout(nowNanos)) {
+ final long now = System.currentTimeMillis();
+ if (checkTimeout(now)) {
if (reactorConfig.getSocksProxyAddress() == null) {
dataChannel.upgrade(eventHandlerFactory.createHandler(dataChannel, sessionRequest.attachment));
key.attach(dataChannel);
@@ -95,7 +95,7 @@ Timeout getTimeout() {
@Override
long getLastEventTime() {
- return creationNanos;
+ return creationTimeMillis;
}
@Override
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/MultiCoreIOReactor.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/MultiCoreIOReactor.java
index 3799c9d7f..957a772eb 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/MultiCoreIOReactor.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/MultiCoreIOReactor.java
@@ -88,25 +88,23 @@ public final void initiateShutdown() {
@Override
public final void awaitShutdown(final TimeValue waitTime) throws InterruptedException {
Args.notNull(waitTime, "Wait time");
- final long deadlineNanos = System.nanoTime() + waitTime.toNanoseconds();
- long remainingNanos = waitTime.toNanoseconds();
+ final long deadline = System.currentTimeMillis() + waitTime.toMilliseconds();
+ long remaining = waitTime.toMilliseconds();
for (int i = 0; i < this.ioReactors.length; i++) {
final IOReactor ioReactor = this.ioReactors[i];
if (ioReactor.getStatus().compareTo(IOReactorStatus.SHUT_DOWN) < 0) {
- ioReactor.awaitShutdown(TimeValue.of(remainingNanos, TimeUnit.NANOSECONDS));
- remainingNanos = deadlineNanos - System.nanoTime();
- if (remainingNanos <= 0) {
+ ioReactor.awaitShutdown(TimeValue.of(remaining, TimeUnit.MILLISECONDS));
+ remaining = deadline - System.currentTimeMillis();
+ if (remaining <= 0) {
return;
}
}
}
for (int i = 0; i < this.threads.length; i++) {
final Thread thread = this.threads[i];
- final long millis = TimeUnit.NANOSECONDS.toMillis(remainingNanos);
- final int nanos = (int) (remainingNanos - TimeUnit.MILLISECONDS.toNanos(millis));
- thread.join(millis, nanos);
- remainingNanos = deadlineNanos - System.nanoTime();
- if (remainingNanos <= 0) {
+ thread.join(remaining);
+ remaining = deadline - System.currentTimeMillis();
+ if (remaining <= 0) {
return;
}
}
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
index 462f0e0df..e89906cb4 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
@@ -43,7 +43,6 @@
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -75,9 +74,8 @@ class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements Connect
private final Queue<IOSessionRequest> requestQueue;
private final AtomicBoolean shutdownInitiated;
private final long selectTimeoutMillis;
- private final long selectTimeoutNanos;
- private volatile long lastTimeoutCheckNanos;
- private volatile long lastSelectNanos;
+ private volatile long lastTimeoutCheckMillis;
+ private volatile long lastSelectMillis;
private final IOReactorMetricsListener threadPoolListener;
private final IOFunction<SocketAddress, SocketChannel> socketChannelFactory;
@@ -119,7 +117,6 @@ class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements Connect
this.channelQueue = new ConcurrentLinkedQueue<>();
this.requestQueue = new ConcurrentLinkedQueue<>();
this.selectTimeoutMillis = this.reactorConfig.getSelectInterval().toMilliseconds();
- this.selectTimeoutNanos = TimeUnit.MILLISECONDS.toNanos(this.selectTimeoutMillis);
}
void enqueueChannel(final ChannelEntry entry) throws IOReactorShutdownException {
@@ -155,7 +152,7 @@ void doExecute() throws IOException {
}
// Process selected I/O events
- lastSelectNanos = System.nanoTime();
+ lastSelectMillis = System.currentTimeMillis();
if (readyCount > 0) {
processEvents(this.selector.selectedKeys());
}
@@ -196,11 +193,11 @@ private void initiateSessionShutdown() {
}
private void validateActiveChannels() {
- final long nowNanos = System.nanoTime();
- if ((nowNanos - this.lastTimeoutCheckNanos) >= this.selectTimeoutNanos) {
- this.lastTimeoutCheckNanos = nowNanos;
+ final long currentTimeMillis = System.currentTimeMillis();
+ if ((currentTimeMillis - this.lastTimeoutCheckMillis) >= this.selectTimeoutMillis) {
+ this.lastTimeoutCheckMillis = currentTimeMillis;
for (final SelectionKey key : this.selector.keys()) {
- checkTimeout(key, nowNanos);
+ checkTimeout(key, currentTimeMillis);
}
}
}
@@ -275,10 +272,10 @@ private void processClosedSessions() {
}
}
- private void checkTimeout(final SelectionKey key, final long nowNanos) {
+ private void checkTimeout(final SelectionKey key, final long nowMillis) {
final InternalChannel channel = (InternalChannel) key.attachment();
if (channel != null) {
- channel.checkTimeout(nowNanos);
+ channel.checkTimeout(nowMillis);
}
}
@@ -356,7 +353,7 @@ private void processPendingConnectionRequests() {
for (int i = 0; i < MAX_CHANNEL_REQUESTS && (sessionRequest = this.requestQueue.poll()) != null; i++) {
if (threadPoolListener != null) {
// Calculate wait time safely without keeping long-lived state
- final long waitTimeMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - sessionRequest.getEnqueueNanos());
+ final long waitTimeMillis = System.currentTimeMillis() - sessionRequest.getEnqueueTime();
// Accumulate total wait time and increment count atomically
totalWaitTime.addAndGet(waitTimeMillis);
@@ -531,8 +528,8 @@ public int pendingChannelCount() {
}
@Override
- public long lastSelectNano() {
- return lastSelectNanos;
+ public long lastSelectMilli() {
+ return lastSelectMillis;
}
}
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestInternalChannel.java b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestInternalChannel.java
index f747d46c2..cfd235609 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestInternalChannel.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestInternalChannel.java
@@ -28,7 +28,6 @@
import java.io.IOException;
import java.nio.channels.CancelledKeyException;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -119,10 +118,10 @@ void handleIoEventClosesOnException() {
@Test
void checkTimeoutInvokesCallback() {
try (TestChannel channel = new TestChannel()) {
- channel.lastEventTime = System.nanoTime() - TimeUnit.SECONDS.toNanos(10);
+ channel.lastEventTime = 0;
channel.timeout = Timeout.ofMilliseconds(1);
- final boolean result = channel.checkTimeout(System.nanoTime());
+ final boolean result = channel.checkTimeout(10);
Assertions.assertFalse(result);
Assertions.assertTrue(channel.timedOut.get());
@@ -134,7 +133,7 @@ void checkTimeoutSkipsWhenDisabled() {
try (TestChannel channel = new TestChannel()) {
channel.timeout = Timeout.DISABLED;
- final boolean result = channel.checkTimeout(System.nanoTime());
+ final boolean result = channel.checkTimeout(System.currentTimeMillis());
Assertions.assertTrue(result);
Assertions.assertFalse(channel.timedOut.get());
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
index 64e06823d..9b6b1a182 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/reactor/TestSocksProxyProtocolHandler.java
@@ -136,7 +136,7 @@ private static final class TestIOSession implements IOSession {
this.open = true;
this.eventMask = 0;
this.socketTimeout = Timeout.DISABLED;
- this.lastReadTime = System.nanoTime();
+ this.lastReadTime = System.currentTimeMillis();
this.lastWriteTime = this.lastReadTime;
this.lastEventTime = this.lastReadTime;
}
@@ -153,7 +153,7 @@ public ByteChannel channel() {
@Override
public void setEventMask(final int ops) {
this.eventMask = ops;
- this.lastEventTime = System.nanoTime();
+ this.lastEventTime = System.currentTimeMillis();
}
@Override
@@ -220,7 +220,7 @@ public Timeout getSocketTimeout() {
@Override
public void setSocketTimeout(final Timeout timeout) {
this.socketTimeout = timeout;
- this.lastEventTime = System.nanoTime();
+ this.lastEventTime = System.currentTimeMillis();
}
@Override
@@ -240,13 +240,13 @@ public long getLastEventTime() {
@Override
public void updateReadTime() {
- this.lastReadTime = System.nanoTime();
+ this.lastReadTime = System.currentTimeMillis();
this.lastEventTime = this.lastReadTime;
}
@Override
public void updateWriteTime() {
- this.lastWriteTime = System.nanoTime();
+ this.lastWriteTime = System.currentTimeMillis();
this.lastEventTime = this.lastWriteTime;
}