You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2023/01/20 19:04:56 UTC
[tomcat] 07/12: Implement new allocation algorithm
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 14d3637bec7708d6a359165db889b6362d03925a
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Dec 7 11:14:46 2022 +0000
Implement new allocation algorithm
Currently using defaults as priorities aren't read yet.
---
.../apache/coyote/http2/AbstractNonZeroStream.java | 55 +---
java/org/apache/coyote/http2/AbstractStream.java | 47 ----
java/org/apache/coyote/http2/Constants.java | 6 +-
.../apache/coyote/http2/Http2UpgradeHandler.java | 310 +++++++--------------
.../apache/coyote/http2/LocalStrings.properties | 2 -
.../apache/coyote/http2/LocalStrings_cs.properties | 1 -
.../apache/coyote/http2/LocalStrings_es.properties | 2 -
.../apache/coyote/http2/LocalStrings_fr.properties | 2 -
.../apache/coyote/http2/LocalStrings_ja.properties | 2 -
.../apache/coyote/http2/LocalStrings_ko.properties | 2 -
.../coyote/http2/LocalStrings_zh_CN.properties | 2 -
java/org/apache/coyote/http2/Stream.java | 24 +-
12 files changed, 129 insertions(+), 326 deletions(-)
diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
index 0876fc88c6..5a9c3e3a48 100644
--- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java
+++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
@@ -17,7 +17,6 @@
package org.apache.coyote.http2;
import java.nio.ByteBuffer;
-import java.util.Iterator;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -36,8 +35,6 @@ abstract class AbstractNonZeroStream extends AbstractStream {
protected final StreamStateMachine state;
- private volatile int weight = Constants.DEFAULT_WEIGHT;
-
AbstractNonZeroStream(String connectionId, Integer identifier) {
super(identifier);
@@ -51,12 +48,6 @@ abstract class AbstractNonZeroStream extends AbstractStream {
}
- @Override
- final int getWeight() {
- return weight;
- }
-
-
/*
* General method used when reprioritising a stream and care needs to be
* taken not to create circular references.
@@ -71,27 +62,7 @@ abstract class AbstractNonZeroStream extends AbstractStream {
parent.getIdAsString(), Integer.toString(weight)));
}
- // Check if new parent is a descendant of this stream
- if (isDescendant(parent)) {
- parent.detachFromParent();
- // Cast is always safe since any descendant of this stream must be
- // an instance of AbstractNonZeroStream
- getParentStream().addChild((AbstractNonZeroStream) parent);
- }
-
- if (exclusive) {
- // Need to move children of the new parent to be children of this
- // stream. Slightly convoluted to avoid concurrent modification.
- Iterator<AbstractNonZeroStream> parentsChildren = parent.getChildStreams().iterator();
- while (parentsChildren.hasNext()) {
- AbstractNonZeroStream parentsChild = parentsChildren.next();
- parentsChildren.remove();
- this.addChild(parentsChild);
- }
- }
- detachFromParent();
- parent.addChild(this);
- this.weight = weight;
+ // TODO
}
@@ -109,29 +80,7 @@ abstract class AbstractNonZeroStream extends AbstractStream {
parent.getIdAsString(), Integer.toString(weight)));
}
- parent.addChild(this);
- this.weight = weight;
- }
-
-
- /*
- * Used when "recycling" a stream and replacing a Stream instance with a
- * RecycledStream instance.
- *
- * Replace this stream with the provided stream in the parent/child
- * hierarchy.
- *
- * Changes to the priority tree need to be synchronized at the connection
- * level. This is the caller's responsibility.
- */
- void replaceStream(AbstractNonZeroStream replacement) {
- getParentStream().addChild(replacement);
- detachFromParent();
- for (AbstractNonZeroStream child : getChildStreams()) {
- replacement.addChild(child);
- }
- getChildStreams().clear();
- replacement.weight = weight;
+ // TODO
}
diff --git a/java/org/apache/coyote/http2/AbstractStream.java b/java/org/apache/coyote/http2/AbstractStream.java
index dc651d30e9..d3533c5bd8 100644
--- a/java/org/apache/coyote/http2/AbstractStream.java
+++ b/java/org/apache/coyote/http2/AbstractStream.java
@@ -16,9 +16,6 @@
*/
package org.apache.coyote.http2;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
@@ -35,8 +32,6 @@ abstract class AbstractStream {
private final Integer identifier;
private final String idAsString;
- private volatile AbstractStream parentStream = null;
- private final Set<AbstractNonZeroStream> childStreams = ConcurrentHashMap.newKeySet();
private long windowSize = ConnectionSettingsBase.DEFAULT_INITIAL_WINDOW_SIZE;
private volatile int connectionAllocationRequested = 0;
@@ -64,46 +59,6 @@ abstract class AbstractStream {
}
- final void detachFromParent() {
- if (parentStream != null) {
- parentStream.getChildStreams().remove(this);
- parentStream = null;
- }
- }
-
-
- final void addChild(AbstractNonZeroStream child) {
- child.setParentStream(this);
- childStreams.add(child);
- }
-
-
- final boolean isDescendant(AbstractStream stream) {
- // Is the passed in Stream a descendant of this Stream?
- // Start at the passed in Stream and work up
- AbstractStream parent = stream.getParentStream();
- while (parent != null && parent != this) {
- parent = parent.getParentStream();
- }
- return parent != null;
- }
-
-
- final AbstractStream getParentStream() {
- return parentStream;
- }
-
-
- final void setParentStream(AbstractStream parentStream) {
- this.parentStream = parentStream;
- }
-
-
- final Set<AbstractNonZeroStream> getChildStreams() {
- return childStreams;
- }
-
-
final synchronized void setWindowSize(long windowSize) {
this.windowSize = windowSize;
}
@@ -181,6 +136,4 @@ abstract class AbstractStream {
abstract String getConnectionId();
-
- abstract int getWeight();
}
diff --git a/java/org/apache/coyote/http2/Constants.java b/java/org/apache/coyote/http2/Constants.java
index 739ae7eb12..e1ee63bb34 100644
--- a/java/org/apache/coyote/http2/Constants.java
+++ b/java/org/apache/coyote/http2/Constants.java
@@ -19,7 +19,11 @@ package org.apache.coyote.http2;
public class Constants {
// Prioritisation
- public static final int DEFAULT_WEIGHT = 16;
+ public static final int DEFAULT_URGENCY = 3;
+ public static final boolean DEFAULT_INCREMENTAL = false;
+ // Range 0 to 7 inclusive
+ public static final int URGENCY_RANGE = 8;
+
// Parsing
static final int DEFAULT_HEADER_READ_BUFFER_SIZE = 1024;
diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index a2405994a8..a5ebde3b26 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -20,15 +20,15 @@ import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Queue;
import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@@ -94,8 +94,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private static final HeaderSink HEADER_SINK = new HeaderSink();
- private final Object priorityTreeLock = new Object();
-
protected final String connectionId;
protected final Http2Protocol protocol;
@@ -131,7 +129,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private final AtomicInteger nextLocalStreamId = new AtomicInteger(2);
private final PingManager pingManager = getPingManager();
private volatile int newStreamsSinceLastPrune = 0;
- private final Set<AbstractStream> backLogStreams = ConcurrentHashMap.newKeySet();
+ private final Set<Stream> backLogStreams = new HashSet<>();
private long backLogSize = 0;
// The time at which the connection will timeout unless data arrives before
// then. -1 means no timeout.
@@ -954,11 +952,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
stream.setConnectionAllocationRequested(reservation);
backLogSize += reservation;
backLogStreams.add(stream);
- // Add the parents as well
- AbstractStream parent = stream.getParentStream();
- while (parent != null && backLogStreams.add(parent)) {
- parent = parent.getParentStream();
- }
}
} else if (windowSize < reservation) {
allocation = (int) windowSize;
@@ -1070,8 +1063,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private synchronized Set<AbstractStream> releaseBackLog(int increment) throws Http2Exception {
Set<AbstractStream> result = new HashSet<>();
- int remaining = increment;
- if (backLogSize < remaining) {
+ if (backLogSize < increment) {
// Can clear the whole backlog
for (AbstractStream stream : backLogStreams) {
if (stream.getConnectionAllocationRequested() > 0) {
@@ -1079,23 +1071,90 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
stream.setConnectionAllocationRequested(0);
}
}
- remaining -= backLogSize;
+ // Cast is safe due to test above
+ int remaining = increment - (int) backLogSize;
backLogSize = 0;
super.incrementWindowSize(remaining);
result.addAll(backLogStreams);
backLogStreams.clear();
} else {
- allocate(this, remaining);
- Iterator<AbstractStream> streamIter = backLogStreams.iterator();
- while (streamIter.hasNext()) {
- AbstractStream stream = streamIter.next();
- if (stream.getConnectionAllocationMade() > 0) {
- backLogSize -= stream.getConnectionAllocationMade();
- backLogSize -= stream.getConnectionAllocationRequested();
- stream.setConnectionAllocationRequested(0);
- result.add(stream);
- streamIter.remove();
+ // Can't clear the whole backlog.
+ // Need streams in priority order
+ Set<Stream> orderedStreams = new ConcurrentSkipListSet<>(Comparator.comparingInt(Stream::getUrgency)
+ .thenComparing(Stream::getIncremental).thenComparing(Stream::getIdAsInt));
+ orderedStreams.addAll(backLogStreams);
+
+ // Iteration 1. Need to work out how much we can clear.
+ long urgencyWhereAllocationIsExhausted = 0;
+ long requestedAllocationForIncrementalStreams = 0;
+ int remaining = increment;
+ Iterator<Stream> orderedStreamsIterator = orderedStreams.iterator();
+ while (orderedStreamsIterator.hasNext()) {
+ Stream s = orderedStreamsIterator.next();
+ if (urgencyWhereAllocationIsExhausted < s.getUrgency()) {
+ if (remaining < 1) {
+ break;
+ }
+ requestedAllocationForIncrementalStreams = 0;
+ }
+ urgencyWhereAllocationIsExhausted = s.getUrgency();
+ if (s.getIncremental()) {
+ requestedAllocationForIncrementalStreams += s.getConnectionAllocationRequested();
+ remaining -= s.getConnectionAllocationRequested();
+ } else {
+ remaining -= s.getConnectionAllocationRequested();
+ if (remaining < 1) {
+ break;
+ }
+ }
+ }
+
+ // Iteration 2. Allocate.
+ // Reset for second iteration
+ remaining = increment;
+ orderedStreamsIterator = orderedStreams.iterator();
+ while (orderedStreamsIterator.hasNext()) {
+ Stream s = orderedStreamsIterator.next();
+ if (s.getUrgency() < urgencyWhereAllocationIsExhausted) {
+ // Can fully allocate
+ remaining = allocate(s, remaining);
+ result.add(s);
+ orderedStreamsIterator.remove();
+ backLogStreams.remove(s);
+ } else if (requestedAllocationForIncrementalStreams == 0) {
+ // Allocation ran out in non-incremental streams so fully
+ // allocate in iterator order until allocation is exhausted
+ remaining = allocate(s, remaining);
+ result.add(s);
+ if (s.getConnectionAllocationRequested() == 0) {
+ // Fully allocated
+ orderedStreamsIterator.remove();
+ backLogStreams.remove(s);
+ }
+ if (remaining < 1) {
+ break;
+ }
+ } else {
+ // Allocation ran out in incremental streams. Distribute
+ // remaining allocation between the incremental streams at
+ // this urgency level.
+ if (s.getUrgency() != urgencyWhereAllocationIsExhausted) {
+ break;
+ }
+
+ int share = (int) (s.getConnectionAllocationRequested() * remaining / requestedAllocationForIncrementalStreams);
+ if (share == 0) {
+ share = 1;
+ }
+ allocate(s, share);
+ result.add(s);
+ if (s.getConnectionAllocationRequested() == 0) {
+ // Fully allocated (unlikely but possible due to
+ // rounding if only a few bytes required).
+ orderedStreamsIterator.remove();
+ backLogStreams.remove(s);
+ }
}
}
}
@@ -1123,67 +1182,12 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
leftToAllocate = leftToAllocate - allocatedThisTime;
}
- if (leftToAllocate == 0) {
- return 0;
- }
-
if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.allocate.left",
getConnectionId(), stream.getIdAsString(), Integer.toString(leftToAllocate)));
}
- // Recipients are children of the current stream that are in the
- // backlog.
- Set<AbstractStream> recipients = new HashSet<>(stream.getChildStreams());
- recipients.retainAll(backLogStreams);
-
- // Loop until we run out of allocation or recipients
- while (leftToAllocate > 0) {
- if (recipients.size() == 0) {
- if (stream.getConnectionAllocationMade() == 0) {
- backLogStreams.remove(stream);
- }
- if (stream.getIdAsInt() == 0) {
- throw new IllegalStateException();
- }
- return leftToAllocate;
- }
-
- int totalWeight = 0;
- for (AbstractStream recipient : recipients) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.allocate.recipient",
- getConnectionId(), stream.getIdAsString(), recipient.getIdAsString(),
- Integer.toString(recipient.getWeight())));
- }
- totalWeight += recipient.getWeight();
- }
-
- // Use an Iterator so fully allocated children/recipients can be
- // removed.
- Iterator<AbstractStream> iter = recipients.iterator();
- int allocated = 0;
- while (iter.hasNext()) {
- AbstractStream recipient = iter.next();
- int share = leftToAllocate * recipient.getWeight() / totalWeight;
- if (share == 0) {
- // This is to avoid rounding issues triggering an infinite
- // loop. It will cause a very slight over allocation but
- // HTTP/2 should cope with that.
- share = 1;
- }
- int remainder = allocate(recipient, share);
- // Remove recipients that receive their full allocation so that
- // they are excluded from the next allocation round.
- if (remainder > 0) {
- iter.remove();
- }
- allocated += (share - remainder);
- }
- leftToAllocate -= allocated;
- }
-
- return 0;
+ return leftToAllocate;
}
@@ -1289,7 +1293,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
// maximum number of concurrent streams.
long max = localSettings.getMaxConcurrentStreams();
- // Only need ~+10% for streams that are in the priority tree,
// Ideally need to retain information for a "significant" amount of time
// after sending END_STREAM (RFC 7540, page 20) so we detect potential
// connection error. 5x seems reasonable. The client will have had
@@ -1307,100 +1310,23 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
int toClose = size - (int) max;
- if (toClose < 1) {
- return;
- }
- // Need to try and close some streams.
- // Try to close streams in this order
- // 1. Completed streams used for a request with no children
- // 2. Completed streams used for a request with children
- // 3. Closed final streams
- //
- // The pruning halts as soon as enough streams have been pruned.
-
- // Use these sets to track the different classes of streams
- TreeSet<Integer> candidatesStepTwo = new TreeSet<>();
- TreeSet<Integer> candidatesStepThree = new TreeSet<>();
-
- // Step 1
- // Iterator is in key order so we automatically have the oldest streams
- // first
- // Tests depend on parent/child relationship between streams so need to
- // lock on priorityTreeLock to ensure a consistent view.
- synchronized (priorityTreeLock) {
- for (AbstractNonZeroStream stream : streams.values()) {
- // Never remove active streams
- if (stream instanceof Stream && ((Stream) stream).isActive()) {
- continue;
- }
-
- if (stream.isClosedFinal()) {
- // This stream went from IDLE to CLOSED and is likely to have
- // been created by the client as part of the priority tree.
- // Candidate for step 3.
- candidatesStepThree.add(stream.getIdentifier());
- } else if (stream.getChildStreams().size() == 0) {
- // Prune it
- AbstractStream parent = stream.getParentStream();
- streams.remove(stream.getIdentifier());
- stream.detachFromParent();
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.pruned", connectionId, stream.getIdAsString()));
- }
- if (--toClose < 1) {
- return;
- }
-
- // If removing this child made the parent childless then see if
- // the parent can be removed.
- // Don't try and remove Stream 0 as that is the connection
- // Don't try and remove 'newer' streams. We'll get to them as we
- // work through the ordered list of streams.
- while (toClose > 0 && parent.getIdAsInt() > 0 && parent.getIdAsInt() < stream.getIdAsInt() &&
- parent.getChildStreams().isEmpty()) {
- // This cast is safe since we know parent ID > 0 therefore
- // this isn't the connection
- stream = (AbstractNonZeroStream) parent;
- parent = stream.getParentStream();
- streams.remove(stream.getIdentifier());
- stream.detachFromParent();
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.pruned", connectionId, stream.getIdAsString()));
- }
- if (--toClose < 1) {
- return;
- }
- // Also need to remove this stream from the step 2 list
- candidatesStepTwo.remove(stream.getIdentifier());
- }
- } else {
- // Closed, with children. Candidate for step 2.
- candidatesStepTwo.add(stream.getIdentifier());
- }
- }
- }
-
- // Process the P2 list
- for (Integer streamIdToRemove : candidatesStepTwo) {
- removeStreamFromPriorityTree(streamIdToRemove);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.pruned", connectionId, streamIdToRemove));
- }
- if (--toClose < 1) {
+ // Need to try and prune some streams. Prune streams starting with the
+ // oldest. Pruning stops as soon as enough streams have been pruned.
+ // Iterator is in key order.
+ for (AbstractNonZeroStream stream : streams.values()) {
+ if (toClose < 1) {
return;
}
- }
-
- while (toClose > 0 && candidatesStepThree.size() > 0) {
- Integer streamIdToRemove = candidatesStepThree.pollLast();
- removeStreamFromPriorityTree(streamIdToRemove);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.prunedPriority", connectionId, streamIdToRemove));
+ if (stream instanceof Stream && ((Stream) stream).isActive()) {
+ continue;
}
- if (--toClose < 1) {
- return;
+ streams.remove(stream.getIdentifier());
+ toClose--;
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("upgradeHandler.pruned", connectionId, stream.getIdAsString()));
}
+
}
if (toClose > 0) {
@@ -1410,33 +1336,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
- private void removeStreamFromPriorityTree(Integer streamIdToRemove) {
- synchronized (priorityTreeLock) {
- AbstractNonZeroStream streamToRemove = streams.remove(streamIdToRemove);
- // Move the removed Stream's children to the removed Stream's
- // parent.
- Set<AbstractNonZeroStream> children = streamToRemove.getChildStreams();
- if (children.size() == 1) {
- // Shortcut
- children.iterator().next().rePrioritise(
- streamToRemove.getParentStream(), streamToRemove.getWeight());
- } else {
- int totalWeight = 0;
- for (AbstractNonZeroStream child : children) {
- totalWeight += child.getWeight();
- }
- for (AbstractNonZeroStream child : children) {
- children.iterator().next().rePrioritise(
- streamToRemove.getParentStream(),
- streamToRemove.getWeight() * child.getWeight() / totalWeight);
- }
- }
- streamToRemove.detachFromParent();
- children.clear();
- }
- }
-
-
void push(Request request, Stream associatedStream) throws IOException {
if (localSettings.getMaxConcurrentStreams() < activeRemoteStreamCount.incrementAndGet()) {
// If there are too many open streams, simply ignore the push
@@ -1471,12 +1370,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
- @Override
- protected final int getWeight() {
- return 0;
- }
-
-
private void reduceOverheadCount(FrameType frameType) {
// A non-overhead frame reduces the overhead count by
// Http2Protocol.DEFAULT_OVERHEAD_REDUCTION_FACTOR. A simple browser
@@ -1909,15 +1802,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
void replaceStream(AbstractNonZeroStream original, AbstractNonZeroStream replacement) {
- synchronized (priorityTreeLock) {
- AbstractNonZeroStream current = streams.get(original.getIdentifier());
- // Might already have been recycled or removed from the priority
- // tree entirely. Only replace it if the full stream is still in the
- // priority tree.
- if (current instanceof Stream) {
- streams.put(original.getIdentifier(), replacement);
- original.replaceStream(replacement);
- }
+ AbstractNonZeroStream current = streams.get(original.getIdentifier());
+ // Only replace the stream if it currently uses the full implementation.
+ if (current instanceof Stream) {
+ streams.put(original.getIdentifier(), replacement);
}
}
diff --git a/java/org/apache/coyote/http2/LocalStrings.properties b/java/org/apache/coyote/http2/LocalStrings.properties
index 547a1880d1..3670d60f42 100644
--- a/java/org/apache/coyote/http2/LocalStrings.properties
+++ b/java/org/apache/coyote/http2/LocalStrings.properties
@@ -127,7 +127,6 @@ streamStateMachine.invalidFrame=Connection [{0}], Stream [{1}], State [{2}], Fra
upgradeHandler.allocate.debug=Connection [{0}], Stream [{1}], allocated [{2}] bytes
upgradeHandler.allocate.left=Connection [{0}], Stream [{1}], [{2}] bytes unallocated - trying to allocate to children
-upgradeHandler.allocate.recipient=Connection [{0}], Stream [{1}], potential recipient [{2}] with weight [{3}]
upgradeHandler.connectionError=Connection error
upgradeHandler.fallToDebug=\n\
\ Note: further occurrences of HTTP/2 stream errors will be logged at DEBUG level.
@@ -144,7 +143,6 @@ upgradeHandler.prefaceReceived=Connection [{0}], Connection preface received fro
upgradeHandler.pruneIncomplete=Connection [{0}], Stream [{1}], Failed to fully prune the connection because there are [{2}] too many active streams
upgradeHandler.pruneStart=Connection [{0}] Starting pruning of old streams. Limit is [{1}] and there are currently [{2}] streams.
upgradeHandler.pruned=Connection [{0}] Pruned completed stream [{1}]
-upgradeHandler.prunedPriority=Connection [{0}] Pruned unused stream [{1}] that may have been part of the priority tree
upgradeHandler.releaseBacklog=Connection [{0}], Stream [{1}] released from backlog
upgradeHandler.reset.receive=Connection [{0}], Stream [{1}], Reset received due to [{2}]
upgradeHandler.enableRfc7450Priorities=Connection [{0}], RFC 7450 priorities may not be enabled after being disabled in the initial connection settings frame (see RFC 9218)
diff --git a/java/org/apache/coyote/http2/LocalStrings_cs.properties b/java/org/apache/coyote/http2/LocalStrings_cs.properties
index 88e888b023..b07e9902d1 100644
--- a/java/org/apache/coyote/http2/LocalStrings_cs.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_cs.properties
@@ -31,7 +31,6 @@ http2Parser.processFramePushPromise=Connection [{0}], Stream [{1}], Rámec pro P
upgradeHandler.pingFailed=Spojení [{0}] pro odeslání příkazu ping na klienta selhalo
upgradeHandler.prefaceReceived=Spojení [{0}], přírava spojení přijata od klienta
upgradeHandler.pruneIncomplete=Plné omezení spojení [{0}] selhalo, neboť streamy byly aktivní / použité v prioritním stromu. Existuje [{2}] příliš mnoho streamů
-upgradeHandler.prunedPriority=Spojení [{0}] omezilo nepoužívaný stream [{1}], který mohl být částí prioritního stromu
upgradeHandler.rst.debug=Spojení [{0}], Stream [{1}], Chyba [{2}], Zpráva [{3}], RST (zavírání streamu)
upgradeHandler.sendPrefaceFail=Spojení [{0}], selhalo odeslánízahájení klientovi
upgradeHandler.socketCloseFailed=Chyba zavírání socketu
diff --git a/java/org/apache/coyote/http2/LocalStrings_es.properties b/java/org/apache/coyote/http2/LocalStrings_es.properties
index acd5243110..2664cc5f8c 100644
--- a/java/org/apache/coyote/http2/LocalStrings_es.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_es.properties
@@ -44,12 +44,10 @@ streamProcessor.error.connection=Conexión [{0}], Flujo [{1}], Ha ocurrido un er
streamStateMachine.debug.change=Conexión [{0}], Flujo [{1}], Estado cambió de [{2}] a [{3}]
upgradeHandler.allocate.left=Conexión [{0}], Flujo [{1}], [{2}] bytes no asignados - tratando de asignar en el hijo
-upgradeHandler.allocate.recipient=Conexión [{0}], Flujo [{1}], recipiente potencial [{2}] con peso [{3}]
upgradeHandler.ioerror=Conexión [{0}]
upgradeHandler.pingFailed=Conexión [{0}] falló al hacer ping al cliente
upgradeHandler.prefaceReceived=Conexión [{0}], Pre face de conexión recibida del cliente\n
upgradeHandler.pruneIncomplete=La conexión [{0}] Falló al podar completamente la conexión porque existen flujos activos / usados en el árbol de priorida. Existen [{2}] muchos flujos
-upgradeHandler.prunedPriority=La conexión [{0}] ha cortado el flujo en desuso [{1}] el cual podía ser parte del árbol prioritario
upgradeHandler.rst.debug=Conexión [{0}], Flujo [{1}], Error [{2}], Mensaje [{3}], RST (cerrando flujo)
upgradeHandler.sendPrefaceFail=La conexión [{0}], Falló al enviar el prefacio al cliente\n
upgradeHandler.socketCloseFailed=Error cerrando el socket
diff --git a/java/org/apache/coyote/http2/LocalStrings_fr.properties b/java/org/apache/coyote/http2/LocalStrings_fr.properties
index e8551e4370..9044d4f47f 100644
--- a/java/org/apache/coyote/http2/LocalStrings_fr.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_fr.properties
@@ -126,7 +126,6 @@ streamStateMachine.invalidFrame=Connection [{0}], Flux [{1}], Etat [{2}], Type d
upgradeHandler.allocate.debug=Connection [{0}], Flux [{1}], [{2}] octets alloués
upgradeHandler.allocate.left=Connection [{0}], Flux [{1}], [{2}] octets désalloués, essai d''allocation aux enfants
-upgradeHandler.allocate.recipient=Connection [{0}], Flux [{1}], receveur potentiel [{2}] avec poids [{3}]
upgradeHandler.connectionError=Erreur de la connection
upgradeHandler.fallToDebug=\n\
\ Note: les occurrences suivantes d'erreurs de stream HTTP/2 seront enregistrées au niveau DEBUG.
@@ -143,7 +142,6 @@ upgradeHandler.prefaceReceived=Connection [{0}], préface de la connection recue
upgradeHandler.pruneIncomplete=Connexion [{0}], Flux [{1}], Erreur lors de l''élimination complète de la connexion parce que des flux sont encore actifs / utilisés dans l''arbre de priorité, il y a [{2}] flux en trop
upgradeHandler.pruneStart=Connection [{0}] Début de l''élimination des anciens flux, la limite est de [{1}] et il y a actuellement [{2}] flux
upgradeHandler.pruned=Connection [{0}] Elimination du flux terminé [{1}]
-upgradeHandler.prunedPriority=La connexion [{0}] a élagué le flux inutilisé [{1}] qui faisait peut-être partie de l''arbre de priorité
upgradeHandler.releaseBacklog=Connection [{0}], Flux [{1}] enlevée de la file d''attente
upgradeHandler.reset.receive=Connection [{0}], Stream [{1}], Reset a été reçu à cause de [{2}]
upgradeHandler.rst.debug=Connexion [{0}], Flux [{1}], Erreur [{2}], Message [{3}], RST (fermeture du flux)
diff --git a/java/org/apache/coyote/http2/LocalStrings_ja.properties b/java/org/apache/coyote/http2/LocalStrings_ja.properties
index b0e237d260..a9b7b8b59d 100644
--- a/java/org/apache/coyote/http2/LocalStrings_ja.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_ja.properties
@@ -126,7 +126,6 @@ streamStateMachine.invalidFrame=コネクション [{0}]、ストリーム [{1}]
upgradeHandler.allocate.debug=コネクション [{0}]、ストリーム [{1}]、割り当てられた [{2}] バイト
upgradeHandler.allocate.left=コネクション [{0}]、ストリーム [{1}]、[{2}] バイトが未割り当て - 子への割り当てを試みています
-upgradeHandler.allocate.recipient=コネクション [{0}]、ストリーム [{1}]、重み [{3}] の潜在的な受信者 [{2}]
upgradeHandler.connectionError=接続エラー
upgradeHandler.fallToDebug=注: HTTP/2 ストリームのエラーがさらに発生すると、DEBUG レベルでログに記録されます。
upgradeHandler.goaway.debug=コネクション [{0}]、Goaway、最終ストリーム [{1}]、エラーコード [{2}]、デバッグデータ [{3}]
@@ -142,7 +141,6 @@ upgradeHandler.prefaceReceived=コネクション [{0}]、クライアントか
upgradeHandler.pruneIncomplete=コネクション [{0}]、ストリーム [{1}]、コネクションを削除できませんでした。アクティブなストリーム数 [{2}] は多すぎます。
upgradeHandler.pruneStart=コネクション [{0}] 古いストリームのプルーニングを開始します。 上限は [{1}] で、現在 [{2}] ストリームがあります。
upgradeHandler.pruned=コネクション [{0}]、完了したストリーム [{1}] は削除します。
-upgradeHandler.prunedPriority=コネクション [{0}]、優先度木に登録されていた可能性のある未使用のストリーム [{1}] を取り除きました。
upgradeHandler.releaseBacklog=コネクション [{0}]、ストリーム [{1}] はバックログから解放されました
upgradeHandler.reset.receive=Connection[{0}]、Stream[{1}]、[{2}]のためにリセットを受信しました
upgradeHandler.rst.debug=コネクション [{0}]、ストリーム [{1}]、エラー [{2}]、メッセージ [{3}]、RST (ストリームを切断します)
diff --git a/java/org/apache/coyote/http2/LocalStrings_ko.properties b/java/org/apache/coyote/http2/LocalStrings_ko.properties
index e8b1825382..a8adb1f976 100644
--- a/java/org/apache/coyote/http2/LocalStrings_ko.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_ko.properties
@@ -125,7 +125,6 @@ streamStateMachine.invalidFrame=연결 [{0}], 스트림 [{1}], 상태 [{2}], 프
upgradeHandler.allocate.debug=연결 [{0}], 스트림 [{1}], [{2}] 바이트를 할당함.
upgradeHandler.allocate.left=연결 [{0}], 스트림 [{1}], [{2}] 바이트들이 할당 해제되었습니다 - 자식들에 할당하려 시도합니다.
-upgradeHandler.allocate.recipient=연결 [{0}], 스트림 [{1}], 가중치 [{3}]의 잠재적 수신자 [{2}]
upgradeHandler.connectionError=연결 오류
upgradeHandler.goaway.debug=연결 [{0}], Goaway, 마지막 스트림 [{1}], 오류 코드 [{2}], 디버그 데이터 [{3}]
upgradeHandler.init=연결 [{0}], 상태 [{1}]
@@ -140,7 +139,6 @@ upgradeHandler.prefaceReceived=연결 [{0}]: 연결 preface를 클라이언트
upgradeHandler.pruneIncomplete=연결 [{0}]: 스트림들이 Priority tree에서 활성화되어 있거나 사용되고 있기 때문에, 해당 연결을 완전히 제거하지 못했습니다. 너무 많은 스트림들이 존재합니다: [{2}].
upgradeHandler.pruneStart=연결 [{0}]: 이전 스트림들에 대한 가지치기를 시작합니다. 한계값은 [{1}] 이고, 현재 [{2}]개의 스트림들이 존재합니다.
upgradeHandler.pruned=연결 [{0}]이(가) 완료된 스트림 [{1}]을(를) 제거했습니다.
-upgradeHandler.prunedPriority=연결 [{0}]이(가) 사용되지 않는 스트림 [{1}]을(를) 제거합니다. 해당 스트림은 priority tree의 일부였을 수 있습니다.
upgradeHandler.releaseBacklog=연결 [{0}], 스트림 [{1}]이(가) 백로그로부터 해제되었습니다.
upgradeHandler.reset.receive=연결 [{0}], 스트림 [{1}], [{2}](으)로 인해 리셋을 수신했습니다.
upgradeHandler.rst.debug=연결 [{0}], 스트림 [{1}], 오류 [{2}], 메시지 [{3}], RST (스트림을 닫습니다)
diff --git a/java/org/apache/coyote/http2/LocalStrings_zh_CN.properties b/java/org/apache/coyote/http2/LocalStrings_zh_CN.properties
index d0713e931a..ec4c7612ba 100644
--- a/java/org/apache/coyote/http2/LocalStrings_zh_CN.properties
+++ b/java/org/apache/coyote/http2/LocalStrings_zh_CN.properties
@@ -126,7 +126,6 @@ streamStateMachine.invalidFrame=连接{0}、流{1}、状态{2}、帧类型{3}
upgradeHandler.allocate.debug=连接[{0}],流[{1}],已分配[{2}]字节
upgradeHandler.allocate.left=连接[{0}],流[{1}],[{2}]字节未分配 - 尝试分配给子项
-upgradeHandler.allocate.recipient=(:连接[{0}],流[{1}],潜在接收者[{2}],权重为[{3}]
upgradeHandler.connectionError=连接错误
upgradeHandler.goaway.debug=连接[{0}],离开,最后的流[{1}],错误码[{2}],调试数据[{3}]
upgradeHandler.init=连接[{0}],状态[{1}]
@@ -141,7 +140,6 @@ upgradeHandler.prefaceReceived=连接[{0}],从客户端收到连接准备。
upgradeHandler.pruneIncomplete=连接[{0}],流[{1}],无法完全修剪连接,因为有[{2}]个活动流太多
upgradeHandler.pruneStart=连接[{0}]正在开始修剪旧流。限制为[{1}],当前有[{2}]个流。
upgradeHandler.pruned=连接[{0}]已修剪完成的流[{1}]
-upgradeHandler.prunedPriority=连接[{0}]已经成为了属于优先级树中未使用的流[{1}]
upgradeHandler.releaseBacklog=连接[{0}],流[{1}]已从待办事项列表中释放
upgradeHandler.reset.receive=连接[{0}],流[{1}],由于[{2}]而重置
upgradeHandler.rst.debug=连接[{0}],流[{1}],错误[{2}],消息[{3}],RST(关闭流)
diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index 53850fc384..f255029993 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -95,6 +95,9 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
private Object pendingWindowUpdateForStreamLock = new Object();
private int pendingWindowUpdateForStream = 0;
+ private volatile int urgency = Constants.DEFAULT_URGENCY;
+ private volatile boolean incremental = Constants.DEFAULT_INCREMENTAL;
+
Stream(Integer identifier, Http2UpgradeHandler handler) {
this(identifier, handler, null);
@@ -104,7 +107,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
Stream(Integer identifier, Http2UpgradeHandler handler, Request coyoteRequest) {
super(handler.getConnectionId(), identifier);
this.handler = handler;
- handler.addChild(this);
setWindowSize(handler.getRemoteSettings().getInitialWindowSize());
if (coyoteRequest == null) {
// HTTP/2 new request
@@ -833,6 +835,26 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
+ public int getUrgency() {
+ return urgency;
+ }
+
+
+ public void setUrgency(int urgency) {
+ this.urgency = urgency;
+ }
+
+
+ public boolean getIncremental() {
+ return incremental;
+ }
+
+
+ public void setIncremental(boolean incremental) {
+ this.incremental = incremental;
+ }
+
+
class StreamOutputBuffer implements HttpOutputBuffer, WriteBuffer.Sink {
private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org