Issue #5198 - GzipHandler should use InflaterPool as well as DeflaterPool
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
17ec87f51c
commit
3bdd82eb5e
|
@ -29,6 +29,7 @@ import java.util.zip.ZipException;
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.component.Destroyable;
|
import org.eclipse.jetty.util.component.Destroyable;
|
||||||
|
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Decoder for the "gzip" content encoding.</p>
|
* <p>Decoder for the "gzip" content encoding.</p>
|
||||||
|
@ -41,9 +42,10 @@ public class GZIPContentDecoder implements Destroyable
|
||||||
private static final long UINT_MAX = 0xFFFFFFFFL;
|
private static final long UINT_MAX = 0xFFFFFFFFL;
|
||||||
|
|
||||||
private final List<ByteBuffer> _inflateds = new ArrayList<>();
|
private final List<ByteBuffer> _inflateds = new ArrayList<>();
|
||||||
private final Inflater _inflater = new Inflater(true);
|
private final InflaterPool _inflaterPool;
|
||||||
private final ByteBufferPool _pool;
|
private final ByteBufferPool _pool;
|
||||||
private final int _bufferSize;
|
private final int _bufferSize;
|
||||||
|
private Inflater _inflater;
|
||||||
private State _state;
|
private State _state;
|
||||||
private int _size;
|
private int _size;
|
||||||
private long _value;
|
private long _value;
|
||||||
|
@ -62,6 +64,13 @@ public class GZIPContentDecoder implements Destroyable
|
||||||
|
|
||||||
public GZIPContentDecoder(ByteBufferPool pool, int bufferSize)
|
public GZIPContentDecoder(ByteBufferPool pool, int bufferSize)
|
||||||
{
|
{
|
||||||
|
this(null, pool, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GZIPContentDecoder(InflaterPool inflaterPool, ByteBufferPool pool, int bufferSize)
|
||||||
|
{
|
||||||
|
_inflaterPool = inflaterPool;
|
||||||
|
_inflater = (inflaterPool == null) ? new Inflater(true) : inflaterPool.acquire();
|
||||||
_bufferSize = bufferSize;
|
_bufferSize = bufferSize;
|
||||||
_pool = pool;
|
_pool = pool;
|
||||||
reset();
|
reset();
|
||||||
|
@ -420,7 +429,12 @@ public class GZIPContentDecoder implements Destroyable
|
||||||
@Override
|
@Override
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
|
if (_inflaterPool == null)
|
||||||
_inflater.end();
|
_inflater.end();
|
||||||
|
else
|
||||||
|
_inflaterPool.release(_inflater);
|
||||||
|
|
||||||
|
_inflater = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFinished()
|
public boolean isFinished()
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
<Set name="checkGzExists" property="jetty.gzip.checkGzExists"/>
|
<Set name="checkGzExists" property="jetty.gzip.checkGzExists"/>
|
||||||
<Set name="compressionLevel" property="jetty.gzip.compressionLevel"/>
|
<Set name="compressionLevel" property="jetty.gzip.compressionLevel"/>
|
||||||
<Set name="inflateBufferSize" property="jetty.gzip.inflateBufferSize"/>
|
<Set name="inflateBufferSize" property="jetty.gzip.inflateBufferSize"/>
|
||||||
|
<Set name="inflaterPoolCapacity" property="jetty.gzip.inflaterPoolCapacity"/>
|
||||||
<Set name="deflaterPoolCapacity" property="jetty.gzip.deflaterPoolCapacity"/>
|
<Set name="deflaterPoolCapacity" property="jetty.gzip.deflaterPoolCapacity"/>
|
||||||
<Set name="syncFlush" property="jetty.gzip.syncFlush"/>
|
<Set name="syncFlush" property="jetty.gzip.syncFlush"/>
|
||||||
<Set name="dispatcherTypes" property="jetty.gzip.dispatcherTypes"/>
|
<Set name="dispatcherTypes" property="jetty.gzip.dispatcherTypes"/>
|
||||||
|
|
|
@ -26,9 +26,12 @@ etc/jetty-gzip.xml
|
||||||
## Inflate request buffer size, or 0 for no request inflation
|
## Inflate request buffer size, or 0 for no request inflation
|
||||||
# jetty.gzip.inflateBufferSize=0
|
# jetty.gzip.inflateBufferSize=0
|
||||||
|
|
||||||
## Deflater pool max size (-1 for unlimited, 0 for no pool)
|
## Deflater pool max size (-1 for unlimited, 0 for no pooling)
|
||||||
# jetty.gzip.deflaterPoolCapacity=-1
|
# jetty.gzip.deflaterPoolCapacity=-1
|
||||||
|
|
||||||
|
## Inflater pool max size (-1 for unlimited, 0 for no pooling)
|
||||||
|
# jetty.gzip.inflaterPoolCapacity=-1
|
||||||
|
|
||||||
## Set the {@link Deflater} flush mode to use.
|
## Set the {@link Deflater} flush mode to use.
|
||||||
# jetty.gzip.syncFlush=false
|
# jetty.gzip.syncFlush=false
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,9 @@ import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||||
import org.eclipse.jetty.util.IncludeExclude;
|
import org.eclipse.jetty.util.IncludeExclude;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.util.compression.CompressionPool;
|
||||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||||
|
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -160,8 +162,8 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString());
|
private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString());
|
||||||
private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");
|
private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");
|
||||||
|
|
||||||
private int poolCapacity = -1;
|
private final InflaterPool _inflaterPool;
|
||||||
private DeflaterPool _deflaterPool = null;
|
private final DeflaterPool _deflaterPool;
|
||||||
|
|
||||||
private int _minGzipSize = DEFAULT_MIN_GZIP_SIZE;
|
private int _minGzipSize = DEFAULT_MIN_GZIP_SIZE;
|
||||||
private boolean _syncFlush = false;
|
private boolean _syncFlush = false;
|
||||||
|
@ -199,6 +201,11 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("{} mime types {}", this, _mimeTypes);
|
LOG.debug("{} mime types {}", this, _mimeTypes);
|
||||||
|
|
||||||
|
_deflaterPool = newDeflaterPool();
|
||||||
|
_inflaterPool = newInflaterPool();
|
||||||
|
addBean(_deflaterPool);
|
||||||
|
addBean(_inflaterPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -409,13 +416,6 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStart() throws Exception
|
|
||||||
{
|
|
||||||
_deflaterPool = newDeflaterPool(poolCapacity);
|
|
||||||
super.doStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Deflater getDeflater(Request request, long contentLength)
|
public Deflater getDeflater(Request request, long contentLength)
|
||||||
{
|
{
|
||||||
|
@ -566,7 +566,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("{} inflate {}", this, request);
|
LOG.debug("{} inflate {}", this, request);
|
||||||
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
|
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(_inflaterPool, baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we already being gzipped?
|
// Are we already being gzipped?
|
||||||
|
@ -891,7 +891,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
*/
|
*/
|
||||||
public int getDeflaterPoolCapacity()
|
public int getDeflaterPoolCapacity()
|
||||||
{
|
{
|
||||||
return poolCapacity;
|
return _deflaterPool.getCapacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -902,12 +902,38 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
||||||
if (isStarted())
|
if (isStarted())
|
||||||
throw new IllegalStateException(getState());
|
throw new IllegalStateException(getState());
|
||||||
|
|
||||||
poolCapacity = capacity;
|
_deflaterPool.setCapacity(capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected DeflaterPool newDeflaterPool(int capacity)
|
/**
|
||||||
|
* Gets the maximum number of Inflators that the DeflaterPool can hold.
|
||||||
|
*
|
||||||
|
* @return the Deflater pool capacity
|
||||||
|
*/
|
||||||
|
public int getInflaterPoolCapacity()
|
||||||
{
|
{
|
||||||
return new DeflaterPool(capacity, Deflater.DEFAULT_COMPRESSION, true);
|
return _inflaterPool.getCapacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum number of Inflators that the DeflaterPool can hold.
|
||||||
|
*/
|
||||||
|
public void setInflaterPoolCapacity(int capacity)
|
||||||
|
{
|
||||||
|
if (isStarted())
|
||||||
|
throw new IllegalStateException(getState());
|
||||||
|
|
||||||
|
_inflaterPool.setCapacity(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InflaterPool newInflaterPool()
|
||||||
|
{
|
||||||
|
return new InflaterPool(CompressionPool.INFINITE_CAPACITY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DeflaterPool newDeflaterPool()
|
||||||
|
{
|
||||||
|
return new DeflaterPool(CompressionPool.INFINITE_CAPACITY, Deflater.DEFAULT_COMPRESSION, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
import org.eclipse.jetty.server.HttpInput;
|
import org.eclipse.jetty.server.HttpInput;
|
||||||
import org.eclipse.jetty.server.HttpInput.Content;
|
import org.eclipse.jetty.server.HttpInput.Content;
|
||||||
import org.eclipse.jetty.util.component.Destroyable;
|
import org.eclipse.jetty.util.component.Destroyable;
|
||||||
|
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An HttpInput Interceptor that inflates GZIP encoded request content.
|
* An HttpInput Interceptor that inflates GZIP encoded request content.
|
||||||
|
@ -34,9 +35,9 @@ public class GzipHttpInputInterceptor implements HttpInput.Interceptor, Destroya
|
||||||
private final Decoder _decoder;
|
private final Decoder _decoder;
|
||||||
private ByteBuffer _chunk;
|
private ByteBuffer _chunk;
|
||||||
|
|
||||||
public GzipHttpInputInterceptor(ByteBufferPool pool, int bufferSize)
|
public GzipHttpInputInterceptor(InflaterPool inflaterPool, ByteBufferPool pool, int bufferSize)
|
||||||
{
|
{
|
||||||
_decoder = new Decoder(pool, bufferSize);
|
_decoder = new Decoder(inflaterPool, pool, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,9 +67,9 @@ public class GzipHttpInputInterceptor implements HttpInput.Interceptor, Destroya
|
||||||
|
|
||||||
private class Decoder extends GZIPContentDecoder
|
private class Decoder extends GZIPContentDecoder
|
||||||
{
|
{
|
||||||
private Decoder(ByteBufferPool pool, int bufferSize)
|
private Decoder(InflaterPool inflaterPool, ByteBufferPool bufferPool, int bufferSize)
|
||||||
{
|
{
|
||||||
super(pool, bufferSize);
|
super(inflaterPool, bufferPool, bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,7 +30,7 @@ public abstract class CompressionPool<T> extends AbstractLifeCycle
|
||||||
|
|
||||||
private final Queue<T> _pool;
|
private final Queue<T> _pool;
|
||||||
private final AtomicInteger _numObjects = new AtomicInteger(0);
|
private final AtomicInteger _numObjects = new AtomicInteger(0);
|
||||||
private final int _capacity;
|
private int _capacity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Pool of {@link T} instances.
|
* Create a Pool of {@link T} instances.
|
||||||
|
@ -44,7 +44,17 @@ public abstract class CompressionPool<T> extends AbstractLifeCycle
|
||||||
public CompressionPool(int capacity)
|
public CompressionPool(int capacity)
|
||||||
{
|
{
|
||||||
_capacity = capacity;
|
_capacity = capacity;
|
||||||
_pool = (_capacity == 0) ? null : new ConcurrentLinkedQueue<>();
|
_pool = new ConcurrentLinkedQueue<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCapacity()
|
||||||
|
{
|
||||||
|
return _capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCapacity(int capacity)
|
||||||
|
{
|
||||||
|
_capacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T newObject();
|
protected abstract T newObject();
|
||||||
|
@ -85,7 +95,6 @@ public abstract class CompressionPool<T> extends AbstractLifeCycle
|
||||||
if (_capacity == 0 || !isRunning())
|
if (_capacity == 0 || !isRunning())
|
||||||
{
|
{
|
||||||
end(object);
|
end(object);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (_capacity < 0)
|
else if (_capacity < 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue