452465 - 100% CPU spin on page reload.
Fixed by adding a MetaData.recycle() method that properly recycles the MetaData.Request object so that HttpChannelOverHttp.earlyEOF() properly closes the connection when it's idle.
This commit is contained in:
parent
2eb6e06387
commit
57f90ae7d1
|
@ -18,109 +18,119 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.http;
|
package org.eclipse.jetty.http;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class MetaData implements Iterable<HttpField>
|
public class MetaData implements Iterable<HttpField>
|
||||||
{
|
{
|
||||||
private HttpVersion _httpVersion;
|
private HttpVersion _httpVersion;
|
||||||
private HttpFields _fields;
|
private HttpFields _fields;
|
||||||
long _contentLength=Long.MIN_VALUE;
|
private long _contentLength;
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public MetaData()
|
public MetaData()
|
||||||
{
|
{
|
||||||
|
this(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public MetaData(HttpVersion version, HttpFields fields)
|
public MetaData(HttpVersion version, HttpFields fields)
|
||||||
{
|
{
|
||||||
_httpVersion = version;
|
this(version, fields, Long.MIN_VALUE);
|
||||||
_fields = fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public MetaData(HttpVersion version, HttpFields fields, long contentLength)
|
public MetaData(HttpVersion version, HttpFields fields, long contentLength)
|
||||||
{
|
{
|
||||||
_httpVersion = version;
|
_httpVersion = version;
|
||||||
_fields = fields;
|
_fields = fields;
|
||||||
_contentLength=contentLength;
|
_contentLength = contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void recycle()
|
||||||
|
{
|
||||||
|
_httpVersion = null;
|
||||||
|
if (_fields != null)
|
||||||
|
_fields.clear();
|
||||||
|
_contentLength = Long.MIN_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public boolean isRequest()
|
public boolean isRequest()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public boolean isResponse()
|
public boolean isResponse()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the httpVersion.
|
* @return the HTTP version of this MetaData object
|
||||||
* @return the httpVersion
|
|
||||||
*/
|
*/
|
||||||
public HttpVersion getVersion()
|
public HttpVersion getVersion()
|
||||||
{
|
{
|
||||||
return _httpVersion;
|
return _httpVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the httpVersion.
|
* @param httpVersion the HTTP version to set
|
||||||
* @param httpVersion the httpVersion to set
|
|
||||||
*/
|
*/
|
||||||
public void setHttpVersion(HttpVersion httpVersion)
|
public void setHttpVersion(HttpVersion httpVersion)
|
||||||
{
|
{
|
||||||
_httpVersion = httpVersion;
|
_httpVersion = httpVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the fields.
|
* @return the HTTP fields of this MetaData object
|
||||||
* @return the fields
|
|
||||||
*/
|
*/
|
||||||
public HttpFields getFields()
|
public HttpFields getFields()
|
||||||
{
|
{
|
||||||
return _fields;
|
return _fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the fields.
|
* @param fields the HTTP fields to set
|
||||||
* @param fields the fields to set
|
|
||||||
*/
|
*/
|
||||||
public void setFields(HttpFields fields)
|
public void setFields(HttpFields fields)
|
||||||
{
|
{
|
||||||
_fields = fields;
|
_fields = fields;
|
||||||
_contentLength=Long.MIN_VALUE;
|
_contentLength = Long.MIN_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
|
* @return the content length if available, otherwise {@link Long#MIN_VALUE}
|
||||||
|
*/
|
||||||
public long getContentLength()
|
public long getContentLength()
|
||||||
{
|
{
|
||||||
if (_contentLength==Long.MIN_VALUE)
|
if (_contentLength == Long.MIN_VALUE)
|
||||||
{
|
{
|
||||||
HttpField cl = _fields.getField(HttpHeader.CONTENT_LENGTH);
|
if (_fields != null)
|
||||||
_contentLength=(cl==null)?-1:cl.getLongValue();
|
{
|
||||||
|
HttpField field = _fields.getField(HttpHeader.CONTENT_LENGTH);
|
||||||
|
_contentLength = field == null ? -1 : field.getLongValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _contentLength;
|
return _contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
|
* @return an iterator over the HTTP fields
|
||||||
|
* @see #getFields()
|
||||||
|
*/
|
||||||
public Iterator<HttpField> iterator()
|
public Iterator<HttpField> iterator()
|
||||||
{
|
{
|
||||||
return getFields().iterator();
|
HttpFields fields = getFields();
|
||||||
|
return fields == null ? Collections.<HttpField>emptyIterator() : fields.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return 31 * getVersion().hashCode() + getFields().hashCode();
|
HttpVersion version = getVersion();
|
||||||
|
int hash = version == null ? 0 : version.hashCode();
|
||||||
|
HttpFields fields = getFields();
|
||||||
|
return 31 * hash + (fields == null ? 0 : fields.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
@ -128,140 +138,122 @@ public class MetaData implements Iterable<HttpField>
|
||||||
return true;
|
return true;
|
||||||
if (!(o instanceof MetaData))
|
if (!(o instanceof MetaData))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MetaData that = (MetaData)o;
|
MetaData that = (MetaData)o;
|
||||||
|
|
||||||
if (getVersion() != that.getVersion())
|
if (getVersion() != that.getVersion())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return getFields().equals(that.getFields());
|
return Objects.equals(getFields(), that.getFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
for (HttpField field: this)
|
for (HttpField field : this)
|
||||||
out.append(field).append(System.lineSeparator());
|
out.append(field).append(System.lineSeparator());
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
public static class Request extends MetaData
|
public static class Request extends MetaData
|
||||||
{
|
{
|
||||||
private String _method;
|
private String _method;
|
||||||
private HttpURI _uri;
|
private HttpURI _uri;
|
||||||
|
|
||||||
public Request()
|
public Request()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param method
|
|
||||||
* @param uri
|
|
||||||
* @param version
|
|
||||||
* @param fields
|
|
||||||
*/
|
|
||||||
public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields)
|
public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields)
|
||||||
{
|
{
|
||||||
this(method,uri,version,fields,Long.MIN_VALUE);
|
this(method, uri, version, fields, Long.MIN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param method
|
|
||||||
* @param uri
|
|
||||||
* @param version
|
|
||||||
* @param fields
|
|
||||||
*/
|
|
||||||
public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength)
|
public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength)
|
||||||
{
|
{
|
||||||
super(version,fields,contentLength);
|
super(version, fields, contentLength);
|
||||||
_method = method;
|
_method = method;
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields)
|
public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields)
|
||||||
{
|
{
|
||||||
this(method,new HttpURI(scheme==null?null:scheme.asString(),hostPort.getHost(),hostPort.getPort(),uri),version,fields);
|
this(method, new HttpURI(scheme == null ? null : scheme.asString(), hostPort.getHost(), hostPort.getPort(), uri), version, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
|
public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
|
||||||
{
|
{
|
||||||
this(method,new HttpURI(scheme==null?null:scheme.asString(),hostPort.getHost(),hostPort.getPort(),uri),version,fields,contentLength);
|
this(method, new HttpURI(scheme == null ? null : scheme.asString(), hostPort.getHost(), hostPort.getPort(), uri), version, fields, contentLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
|
public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength)
|
||||||
{
|
{
|
||||||
this(method,new HttpURI(scheme,hostPort.getHost(),hostPort.getPort(),uri),version,fields,contentLength);
|
this(method, new HttpURI(scheme, hostPort.getHost(), hostPort.getPort(), uri), version, fields, contentLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recycle()
|
||||||
|
{
|
||||||
|
super.recycle();
|
||||||
|
_method = null;
|
||||||
|
if (_uri != null)
|
||||||
|
_uri.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRequest()
|
public boolean isRequest()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the method.
|
* @return the HTTP method
|
||||||
* @return the method
|
|
||||||
*/
|
*/
|
||||||
public String getMethod()
|
public String getMethod()
|
||||||
{
|
{
|
||||||
return _method;
|
return _method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the method.
|
* @param method the HTTP method to set
|
||||||
* @param method the method to set
|
|
||||||
*/
|
*/
|
||||||
public void setMethod(String method)
|
public void setMethod(String method)
|
||||||
{
|
{
|
||||||
_method = method;
|
_method = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the uri.
|
* @return the HTTP URI
|
||||||
* @return the uri
|
|
||||||
*/
|
*/
|
||||||
public HttpURI getURI()
|
public HttpURI getURI()
|
||||||
{
|
{
|
||||||
return _uri;
|
return _uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the uri.
|
* @return the HTTP URI in string form
|
||||||
* @return the uri
|
|
||||||
*/
|
*/
|
||||||
public String getURIString()
|
public String getURIString()
|
||||||
{
|
{
|
||||||
return _uri==null?null:_uri.toString();
|
return _uri == null ? null : _uri.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the uri.
|
* @param uri the HTTP URI to set
|
||||||
* @param uri the uri to set
|
|
||||||
*/
|
*/
|
||||||
public void setURI(HttpURI uri)
|
public void setURI(HttpURI uri)
|
||||||
{
|
{
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return ((super.hashCode()*31)+_method.hashCode())*31+_uri.hashCode();
|
int hash = super.hashCode();
|
||||||
|
hash = hash * 31 + (_method == null ? 0 : _method.hashCode());
|
||||||
|
return hash * 31 + (_uri == null ? 0 : _uri.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
@ -270,13 +262,12 @@ public class MetaData implements Iterable<HttpField>
|
||||||
if (!(o instanceof MetaData.Request))
|
if (!(o instanceof MetaData.Request))
|
||||||
return false;
|
return false;
|
||||||
MetaData.Request that = (MetaData.Request)o;
|
MetaData.Request that = (MetaData.Request)o;
|
||||||
if (!getMethod().equals(that.getMethod()) ||
|
if (!Objects.equals(getMethod(), that.getMethod()) ||
|
||||||
!getURI().equals(that.getURI()))
|
!Objects.equals(getURI(), that.getURI()))
|
||||||
return false;
|
return false;
|
||||||
return super.equals(o);
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
|
@ -285,9 +276,6 @@ public class MetaData implements Iterable<HttpField>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
/* -------------------------------------------------------- */
|
|
||||||
public static class Response extends MetaData
|
public static class Response extends MetaData
|
||||||
{
|
{
|
||||||
private int _status;
|
private int _status;
|
||||||
|
@ -295,95 +283,71 @@ public class MetaData implements Iterable<HttpField>
|
||||||
|
|
||||||
public Response()
|
public Response()
|
||||||
{
|
{
|
||||||
|
this(null, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* @param version
|
|
||||||
* @param fields
|
|
||||||
* @param status
|
|
||||||
*/
|
|
||||||
public Response(HttpVersion version, int status, HttpFields fields)
|
public Response(HttpVersion version, int status, HttpFields fields)
|
||||||
{
|
{
|
||||||
this(version,status,fields,Long.MIN_VALUE);
|
this(version, status, fields, Long.MIN_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
public Response(HttpVersion version, int status, HttpFields fields, long contentLength)
|
||||||
/**
|
|
||||||
* @param version
|
|
||||||
* @param fields
|
|
||||||
* @param status
|
|
||||||
*/
|
|
||||||
public Response(HttpVersion version, int status, HttpFields fields,long contentLength)
|
|
||||||
{
|
{
|
||||||
super(version,fields,contentLength);
|
super(version, fields, contentLength);
|
||||||
_status=status;
|
_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength)
|
||||||
/**
|
{
|
||||||
* @param version
|
super(version, fields, contentLength);
|
||||||
* @param fields
|
_reason = reason;
|
||||||
* @param status
|
_status = status;
|
||||||
*/
|
|
||||||
public Response(HttpVersion version, int status, String reason, HttpFields fields,long contentLength)
|
|
||||||
{
|
|
||||||
super(version,fields,contentLength);
|
|
||||||
_reason=reason;
|
|
||||||
_status=status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isResponse()
|
public boolean isResponse()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the status.
|
* @return the HTTP status
|
||||||
* @return the status
|
|
||||||
*/
|
*/
|
||||||
public int getStatus()
|
public int getStatus()
|
||||||
{
|
{
|
||||||
return _status;
|
return _status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Get the reason.
|
* @return the HTTP reason
|
||||||
* @return the status
|
|
||||||
*/
|
*/
|
||||||
public String getReason()
|
public String getReason()
|
||||||
{
|
{
|
||||||
return _reason;
|
return _reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the status.
|
* @param status the HTTP status to set
|
||||||
* @param status the status to set
|
|
||||||
*/
|
*/
|
||||||
public void setStatus(int status)
|
public void setStatus(int status)
|
||||||
{
|
{
|
||||||
_status = status;
|
_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/**
|
||||||
/** Set the reason.
|
* @param reason the HTTP reason to set
|
||||||
* @param reason the reason to set
|
|
||||||
*/
|
*/
|
||||||
public void setReason(String reason)
|
public void setReason(String reason)
|
||||||
{
|
{
|
||||||
_reason = reason;
|
_reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
return 31 * getStatus() + super.hashCode();
|
return 31 * super.hashCode() + getStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
|
@ -397,12 +361,10 @@ public class MetaData implements Iterable<HttpField>
|
||||||
return super.equals(o);
|
return super.equals(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("%s %d%s%s",getVersion(), getStatus(), System.lineSeparator(), super.toString());
|
return String.format("%s %d%s%s", getVersion(), getStatus(), System.lineSeparator(), super.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.server;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HostPortHttpField;
|
import org.eclipse.jetty.http.HostPortHttpField;
|
||||||
|
@ -71,7 +70,7 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
|
||||||
_expect = false;
|
_expect = false;
|
||||||
_expect100Continue = false;
|
_expect100Continue = false;
|
||||||
_expect102Processing = false;
|
_expect102Processing = false;
|
||||||
_metadata.getURI().clear();
|
_metadata.recycle();
|
||||||
_connection=null;
|
_connection=null;
|
||||||
_fields.clear();
|
_fields.clear();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue