Fixes #2313 - Dump HTTP/2 channel state.
Dumping also HttpChannelOverHTTP2 when dumping the HTTP2Stream. The channel is now stored as a field in HTTP2Stream rather than as an attribute to save the attributes map allocation. Consequently, IStream has now getter/setter for the property "attachment" that is used to store the channel without having a type dependency on HttpChannel. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
4c24c457de
commit
21bdb367fd
|
@ -223,7 +223,7 @@ public class HTTP2Flusher extends IteratingCallback implements Dumpable
|
|||
IStream stream = entry.stream;
|
||||
if (stream != null && !entry.isControl())
|
||||
{
|
||||
Object channel = stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
Object channel = stream.getAttachment();
|
||||
if (channel instanceof WriteFlusher.Listener)
|
||||
((WriteFlusher.Listener)channel).onFlushed(update - Frame.HEADER_LENGTH);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(HTTP2Stream.class);
|
||||
|
||||
private final AtomicReference<Object> attachment = new AtomicReference<>();
|
||||
private final AtomicReference<ConcurrentMap<String, Object>> attributes = new AtomicReference<>();
|
||||
private final AtomicReference<CloseState> closeState = new AtomicReference<>(CloseState.NOT_CLOSED);
|
||||
private final AtomicReference<Callback> writing = new AtomicReference<>();
|
||||
|
@ -73,6 +74,18 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
return streamId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttachment()
|
||||
{
|
||||
return attachment.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttachment(Object attachment)
|
||||
{
|
||||
this.attachment.set(attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocal()
|
||||
{
|
||||
|
@ -460,7 +473,7 @@ public class HTTP2Stream extends IdleTimeout implements IStream, Callback, Dumpa
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x#%d{sendWindow=%s,recvWindow=%s,reset=%b,%s}", getClass().getSimpleName(),
|
||||
hashCode(), getId(), sendWindow, recvWindow, isReset(), closeState);
|
||||
return String.format("%s@%x#%d{sendWindow=%s,recvWindow=%s,reset=%b,%s,attachment=%s}", getClass().getSimpleName(),
|
||||
hashCode(), getId(), sendWindow, recvWindow, isReset(), closeState, attachment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,17 @@ import org.eclipse.jetty.util.Callback;
|
|||
public interface IStream extends Stream, Closeable
|
||||
{
|
||||
/**
|
||||
* <p>The constant used as attribute key to store/retrieve the HTTP
|
||||
* channel associated with this stream</p>
|
||||
*
|
||||
* @see #setAttribute(String, Object)
|
||||
* @return the object attached to this stream
|
||||
* @see #setAttachment(Object)
|
||||
*/
|
||||
public static final String CHANNEL_ATTRIBUTE = IStream.class.getName() + ".channel";
|
||||
public Object getAttachment();
|
||||
|
||||
/**
|
||||
* Attaches the given object to this stream for later retrieval.
|
||||
*
|
||||
* @param attachment the object to attach to this stream
|
||||
*/
|
||||
public void setAttachment(Object attachment);
|
||||
|
||||
/**
|
||||
* @return whether this stream is local or remote
|
||||
|
|
|
@ -120,4 +120,13 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
super.exchangeTerminated(exchange, result);
|
||||
release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s[send=%s,recv=%s]",
|
||||
super.toString(),
|
||||
sender,
|
||||
receiver);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.jetty.http.HttpFields;
|
|||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.IStream;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
|
@ -64,7 +65,8 @@ public class HttpSenderOverHTTP2 extends HttpSender
|
|||
@Override
|
||||
public void succeeded(Stream stream)
|
||||
{
|
||||
getHttpChannel().setStream(stream);
|
||||
channel.setStream(stream);
|
||||
((IStream)stream).setAttachment(channel);
|
||||
stream.setIdleTimeout(request.getIdleTimeout());
|
||||
|
||||
if (content.hasContent() && !expects100Continue(request))
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.ArrayDeque;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
@ -172,7 +173,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Processing {} on {}", frame, stream);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttachment();
|
||||
if (channel != null)
|
||||
{
|
||||
Runnable task = channel.onRequestContent(frame, callback);
|
||||
|
@ -189,7 +190,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Processing trailers {} on {}", frame, stream);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttachment();
|
||||
if (channel != null)
|
||||
{
|
||||
Runnable task = channel.onRequestTrailers(frame);
|
||||
|
@ -200,7 +201,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
|
||||
public boolean onStreamTimeout(IStream stream, Throwable failure)
|
||||
{
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttachment();
|
||||
boolean result = channel != null && channel.onStreamTimeout(failure, task -> offerTask(task, true));
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} idle timeout on {}: {}", result ? "Processed" : "Ignored", stream, failure);
|
||||
|
@ -211,7 +212,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Processing failure on {}: {}", stream, failure);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttachment();
|
||||
if (channel != null)
|
||||
{
|
||||
Runnable task = channel.onFailure(failure, callback);
|
||||
|
@ -227,13 +228,13 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
public boolean onSessionTimeout(Throwable failure)
|
||||
{
|
||||
ISession session = getSession();
|
||||
boolean result = true;
|
||||
for (Stream stream : session.getStreams())
|
||||
{
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
if (channel != null)
|
||||
result &= channel.isRequestIdle();
|
||||
}
|
||||
// Compute whether all requests are idle.
|
||||
boolean result = session.getStreams().stream()
|
||||
.map(stream -> (IStream)stream)
|
||||
.map(stream -> (HttpChannelOverHTTP2)stream.getAttachment())
|
||||
.filter(Objects::nonNull)
|
||||
.map(HttpChannelOverHTTP2::isRequestIdle)
|
||||
.reduce(true, Boolean::logicalAnd);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} idle timeout on {}: {}", result ? "Processed" : "Ignored", session, failure);
|
||||
return result;
|
||||
|
@ -284,7 +285,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Creating channel {} for {}", channel, this);
|
||||
}
|
||||
stream.setAttribute(IStream.CHANNEL_ATTRIBUTE, channel);
|
||||
stream.setAttachment(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
@ -379,7 +380,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
@Override
|
||||
public void recycle()
|
||||
{
|
||||
getStream().removeAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
getStream().setAttachment(null);
|
||||
super.recycle();
|
||||
offerHttpChannel(this);
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
|
||||
// Consume the existing queued data frames to
|
||||
// avoid stalling the session flow control.
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttachment();
|
||||
if (channel != null)
|
||||
channel.consumeInput();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue