This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push: new 67c4c72 Refactor int[] to class to improve maintainability # Conflicts: # java/org/apache/coyote/http2/Http2UpgradeHandler.java 67c4c72 is described below commit 67c4c72f6e51bf1c0cfa1d10c115962be1a8fe0a Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu May 30 21:09:10 2019 +0100 Refactor int[] to class to improve maintainability # Conflicts: # java/org/apache/coyote/http2/Http2UpgradeHandler.java --- .../apache/coyote/http2/Http2UpgradeHandler.java | 150 ++++++++++++++------- 1 file changed, 99 insertions(+), 51 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index a1aa77c..22ea45f 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -138,26 +138,7 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU private final AtomicInteger nextLocalStreamId = new AtomicInteger(2); private final PingManager pingManager = new PingManager(); private volatile int newStreamsSinceLastPrune = 0; - // Tracking for when the connection is blocked (windowSize < 1) - // The int array must have 3 elements. There are: - // [0] - The number of bytes the Stream requires from the connection - // window. This excludes any allocation that has already been made. - // [1] - The number of bytes that has been allocated from the connection - // window. This excludes any bytes that have been written since the - // allocation was made. - // [2] - 1 if the stream thread has been notified that an allocation has - // been made but has not yet consumed that allocation. 0 in all - // other cases. The purpose of this is to avoid the incorrect - // triggering of a timeout for the following sequence of events: - // window update 1 - // allocation 1 - // notify 1 - // window update 2 - // allocation 2 - // act on notify 1 (using allocation 1 and 2) - // notify 2 - // act on notify 2 (timeout due to no allocation) - private final ConcurrentMap<AbstractStream,int[]> backLogStreams = new ConcurrentHashMap<>(); + private final ConcurrentMap<AbstractStream, BacklogTracker> backLogStreams = new ConcurrentHashMap<>(); private long backLogSize = 0; // Stream concurrency control @@ -785,21 +766,21 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU long windowSize = getWindowSize(); if (windowSize < 1 || backLogSize > 0) { // Has this stream been granted an allocation - int[] value = backLogStreams.get(stream); - if (value == null) { - value = new int[] { reservation, 0, 0 }; - backLogStreams.put(stream, value); + BacklogTracker tracker = backLogStreams.get(stream); + if (tracker == null) { + tracker = new BacklogTracker(reservation); + backLogStreams.put(stream, tracker); backLogSize += reservation; // Add the parents as well AbstractStream parent = stream.getParentStream(); - while (parent != null && backLogStreams.putIfAbsent(parent, new int[3]) == null) { + while (parent != null && backLogStreams.putIfAbsent(parent, new BacklogTracker()) == null) { parent = parent.getParentStream(); } } else { - if (value[1] > 0) { - allocation = value[1]; + if (tracker.getUnusedAllocation() > 0) { + allocation = tracker.getUnusedAllocation(); decrementWindowSize(allocation); - if (value[0] == 0) { + if (tracker.getRemainingReservation() == 0) { // The reservation has been fully allocated // so this stream can be removed from the // backlog. @@ -808,10 +789,7 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU // This allocation has been used. Leave the // stream on the backlog as it still has // more bytes to write. - // Reset the allocation to zero. - value[1] = 0; - // Clear the notify in progress marker - value[2] = 0; + tracker.useAllocation(); } } } @@ -837,12 +815,12 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU // Has this stream been granted an allocation // Note: If the stream in not in this Map then the // requested write has been fully allocated - int[] value; + BacklogTracker tracker; // Ensure allocations made in other threads are visible synchronized (this) { - value = backLogStreams.get(stream); + tracker = backLogStreams.get(stream); } - if (value != null && value[1] == 0) { + if (tracker != null && tracker.getUnusedAllocation() == 0) { if (log.isDebugEnabled()) { log.debug(sm.getString("upgradeHandler.noAllocation", connectionId, stream.getIdentifier())); @@ -938,13 +916,13 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU while (leftToAllocate > 0) { leftToAllocate = allocate(this, leftToAllocate); } - for (Entry<AbstractStream,int[]> entry : backLogStreams.entrySet()) { - int allocation = entry.getValue()[1]; + for (Entry<AbstractStream,BacklogTracker> entry : backLogStreams.entrySet()) { + int allocation = entry.getValue().getUnusedAllocation(); if (allocation > 0) { backLogSize -= allocation; - if (entry.getValue()[2] == 0) { + if (!entry.getValue().isNotifyInProgress()) { result.add(entry.getKey()); - entry.getValue()[2] = 1; + entry.getValue().startNotify(); } } } @@ -967,20 +945,14 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU stream.getIdentifier(), Integer.toString(allocation))); } // Allocate to the specified stream - int[] value = backLogStreams.get(stream); - if (value[0] >= allocation) { - value[0] -= allocation; - value[1] += allocation; + BacklogTracker tracker = backLogStreams.get(stream); + + int leftToAllocate = tracker.allocate(allocation); + + if (leftToAllocate == 0) { return 0; } - // There was some left over so allocate that to the children of the - // stream. - int leftToAllocate = allocation; - value[1] = value[0]; - value[0] = 0; - leftToAllocate -= value[1]; - if (log.isDebugEnabled()) { log.debug(sm.getString("upgradeHandler.allocate.left", getConnectionId(), stream.getIdentifier(), Integer.toString(leftToAllocate))); @@ -1804,5 +1776,81 @@ public class Http2UpgradeHandler extends AbstractStream implements InternalHttpU public boolean isNewStreamAllowed() { return newStreamsAllowed; } - } + } + + + private static class BacklogTracker { + + private int remainingReservation; + private int unusedAllocation; + private boolean notifyInProgress; + + public BacklogTracker() { + } + + public BacklogTracker(int reservation) { + remainingReservation = reservation; + } + + /** + * @return The number of bytes requiring an allocation from the + * Connection flow control window + */ + public int getRemainingReservation() { + return remainingReservation; + } + + /** + * + * @return The number of bytes allocated from the Connection flow + * control window but not yet written + */ + public int getUnusedAllocation() { + return unusedAllocation; + } + + /** + * The purpose of this is to avoid the incorrect triggering of a timeout + * for the following sequence of events: + * <ol> + * <li>window update 1</li> + * <li>allocation 1</li> + * <li>notify 1</li> + * <li>window update 2</li> + * <li>allocation 2</li> + * <li>act on notify 1 (using allocation 1 and 2)</li> + * <li>notify 2</li> + * <li>act on notify 2 (timeout due to no allocation)</li> + * </ol> + * + * @return {@code true} if a notify has been issued but the associated + * allocation has not been used, otherwise {@code false} + */ + public boolean isNotifyInProgress() { + return notifyInProgress; + } + + public void useAllocation() { + unusedAllocation = 0; + notifyInProgress = false; + } + + public void startNotify() { + notifyInProgress = true; + } + + private int allocate(int allocation) { + if (remainingReservation >= allocation) { + remainingReservation -= allocation; + unusedAllocation += allocation; + return 0; + } + + int left = allocation - remainingReservation; + unusedAllocation += remainingReservation; + remainingReservation = 0; + + return left; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org