Skip to content

Commit ec6a5f5

Browse files
committed
Optimize release of resources associated by H2 streams: H2StreamHandler#releaseResources should now be called only once
1 parent 1727460 commit ec6a5f5

1 file changed

Lines changed: 24 additions & 11 deletions

File tree

httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.concurrent.ConcurrentHashMap;
4141
import java.util.concurrent.ConcurrentLinkedDeque;
4242
import java.util.concurrent.ConcurrentLinkedQueue;
43+
import java.util.concurrent.atomic.AtomicBoolean;
4344
import java.util.concurrent.atomic.AtomicInteger;
4445

4546
import javax.net.ssl.SSLHandshakeException;
@@ -556,7 +557,7 @@ public final void onTimeout(final Timeout timeout) throws HttpException, IOExcep
556557
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
557558
final Map.Entry<Integer, H2Stream> entry = it.next();
558559
final H2Stream stream = entry.getValue();
559-
stream.reset(new H2StreamResetException(H2Error.NO_ERROR, "Timeout due to inactivity (" + timeout + ")"));
560+
stream.fail(new H2StreamResetException(H2Error.NO_ERROR, "Timeout due to inactivity (" + timeout + ")"));
560561
}
561562
streamMap.clear();
562563
}
@@ -676,7 +677,7 @@ public final void onException(final Exception cause) {
676677
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
677678
final Map.Entry<Integer, H2Stream> entry = it.next();
678679
final H2Stream stream = entry.getValue();
679-
stream.reset(cause);
680+
stream.fail(cause);
680681
}
681682
streamMap.clear();
682683
if (!(cause instanceof ConnectionClosedException)) {
@@ -873,9 +874,8 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
873874
throw new H2ConnectionException(H2Error.FRAME_SIZE_ERROR, "Invalid RST_STREAM frame payload");
874875
}
875876
final int errorCode = payload.getInt();
876-
stream.reset(new H2StreamResetException(errorCode, "Stream reset (" + errorCode + ")"));
877+
stream.fail(new H2StreamResetException(errorCode, "Stream reset (" + errorCode + ")"));
877878
streamMap.remove(streamId);
878-
stream.releaseResources();
879879
requestSessionOutput();
880880
}
881881
}
@@ -1013,7 +1013,7 @@ private void consumeFrame(final RawFrame frame) throws HttpException, IOExceptio
10131013
for (final Iterator<Map.Entry<Integer, H2Stream>> it = streamMap.entrySet().iterator(); it.hasNext(); ) {
10141014
final Map.Entry<Integer, H2Stream> entry = it.next();
10151015
final H2Stream stream = entry.getValue();
1016-
stream.reset(new H2StreamResetException(errorCode, "Connection terminated by the peer (" + errorCode + ")"));
1016+
stream.fail(new H2StreamResetException(errorCode, "Connection terminated by the peer (" + errorCode + ")"));
10171017
}
10181018
streamMap.clear();
10191019
connState = ConnectionHandshake.SHUTDOWN;
@@ -1590,6 +1590,7 @@ static class H2Stream {
15901590
private final H2StreamChannelImpl channel;
15911591
private final H2StreamHandler handler;
15921592
private final boolean remoteInitiated;
1593+
private final AtomicBoolean released;
15931594

15941595
private H2Stream(
15951596
final H2StreamChannelImpl channel,
@@ -1598,6 +1599,7 @@ private H2Stream(
15981599
this.channel = channel;
15991600
this.handler = handler;
16001601
this.remoteInitiated = remoteInitiated;
1602+
this.released = new AtomicBoolean();
16011603
}
16021604

16031605
int getId() {
@@ -1679,15 +1681,21 @@ void produceInputCapacityUpdate() throws IOException {
16791681
handler.updateInputCapacity();
16801682
}
16811683

1682-
void reset(final Exception cause) {
1684+
void fail(final Exception cause) {
16831685
channel.setRemoteEndStream();
16841686
channel.setLocalEndStream();
1685-
handler.failed(cause);
1687+
if (released.compareAndSet(false, true)) {
1688+
handler.failed(cause);
1689+
handler.releaseResources();
1690+
}
16861691
}
16871692

16881693
void localReset(final Exception cause, final int code) throws IOException {
16891694
channel.localReset(code);
1690-
handler.failed(cause);
1695+
if (released.compareAndSet(false, true)) {
1696+
handler.failed(cause);
1697+
handler.releaseResources();
1698+
}
16911699
}
16921700

16931701
void localReset(final Exception cause, final H2Error error) throws IOException {
@@ -1707,17 +1715,22 @@ HandlerFactory<AsyncPushConsumer> getPushHandlerFactory() {
17071715
}
17081716

17091717
void cancel() {
1710-
reset(new RequestNotExecutedException());
1718+
fail(new RequestNotExecutedException());
17111719
}
17121720

17131721
boolean abort() {
17141722
final boolean cancelled = channel.cancel();
1715-
handler.failed(new RequestNotExecutedException());
1723+
if (released.compareAndSet(false, true)) {
1724+
handler.failed(new RequestNotExecutedException());
1725+
handler.releaseResources();
1726+
}
17161727
return cancelled;
17171728
}
17181729

17191730
void releaseResources() {
1720-
handler.releaseResources();
1731+
if (released.compareAndSet(false, true)) {
1732+
handler.releaseResources();
1733+
}
17211734
}
17221735

17231736
void appendState(final StringBuilder buf) {

0 commit comments

Comments
 (0)