- Replace ByteBufferPool + size + directness with ByteBufferPool.Sized in HttpContent-related code
- Cleanup and javadoc HttpContent - Align and cleanup offset/length default values Signed-off-by: Ludovic Orban <lorban@bitronix.be>
This commit is contained in:
parent
bcd73c6a7b
commit
347dee0ba5
|
@ -222,7 +222,7 @@ public class MultiPartByteRanges
|
|||
{
|
||||
private final Resource resource;
|
||||
private final ByteRange byteRange;
|
||||
private final ByteBufferPool bufferPool;
|
||||
private final ByteBufferPool.Sized bufferPool;
|
||||
|
||||
public Part(String contentType, Resource resource, ByteRange byteRange, long contentLength)
|
||||
{
|
||||
|
@ -233,7 +233,7 @@ public class MultiPartByteRanges
|
|||
public Part(String contentType, Resource resource, ByteRange byteRange, long contentLength, ByteBufferPool bufferPool)
|
||||
{
|
||||
this(HttpFields.build().put(HttpHeader.CONTENT_TYPE, contentType)
|
||||
.put(HttpHeader.CONTENT_RANGE, byteRange.toHeaderValue(contentLength)), resource, byteRange, bufferPool);
|
||||
.put(HttpHeader.CONTENT_RANGE, byteRange.toHeaderValue(contentLength)), resource, byteRange, new ByteBufferPool.Sized(bufferPool));
|
||||
}
|
||||
|
||||
public Part(HttpFields headers, Resource resource, ByteRange byteRange)
|
||||
|
@ -241,18 +241,18 @@ public class MultiPartByteRanges
|
|||
this(headers, resource, byteRange, null);
|
||||
}
|
||||
|
||||
public Part(HttpFields headers, Resource resource, ByteRange byteRange, ByteBufferPool bufferPool)
|
||||
public Part(HttpFields headers, Resource resource, ByteRange byteRange, ByteBufferPool.Sized bufferPool)
|
||||
{
|
||||
super(null, null, headers);
|
||||
this.resource = resource;
|
||||
this.byteRange = byteRange;
|
||||
this.bufferPool = bufferPool == null ? ByteBufferPool.NON_POOLING : bufferPool;
|
||||
this.bufferPool = bufferPool == null ? ByteBufferPool.SIZED_NON_POOLING : bufferPool;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Content.Source newContentSource()
|
||||
{
|
||||
return IOResources.asContentSource(resource, bufferPool, 0, false, byteRange.first(), byteRange.getLength());
|
||||
return IOResources.asContentSource(resource, bufferPool, byteRange.first(), byteRange.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,16 +69,15 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
private final HttpContent.Factory _authority;
|
||||
private final ConcurrentHashMap<String, CachingHttpContent> _cache = new ConcurrentHashMap<>();
|
||||
private final AtomicLong _cachedSize = new AtomicLong();
|
||||
private final ByteBufferPool _bufferPool;
|
||||
private final ByteBufferPool.Sized _bufferPool;
|
||||
private int _maxCachedFileSize = DEFAULT_MAX_CACHED_FILE_SIZE;
|
||||
private int _maxCachedFiles = DEFAULT_MAX_CACHED_FILES;
|
||||
private long _maxCacheSize = DEFAULT_MAX_CACHE_SIZE;
|
||||
private boolean _useDirectByteBuffers = true;
|
||||
|
||||
public CachingHttpContentFactory(HttpContent.Factory authority, ByteBufferPool bufferPool)
|
||||
public CachingHttpContentFactory(HttpContent.Factory authority, ByteBufferPool.Sized bufferPool)
|
||||
{
|
||||
_authority = authority;
|
||||
_bufferPool = bufferPool != null ? bufferPool : ByteBufferPool.NON_POOLING;
|
||||
_bufferPool = bufferPool != null ? bufferPool : ByteBufferPool.SIZED_NON_POOLING;
|
||||
}
|
||||
|
||||
protected ConcurrentMap<String, CachingHttpContent> getCache()
|
||||
|
@ -137,16 +136,6 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
shrinkCache();
|
||||
}
|
||||
|
||||
public boolean isUseDirectByteBuffers()
|
||||
{
|
||||
return _useDirectByteBuffers;
|
||||
}
|
||||
|
||||
public void setUseDirectByteBuffers(boolean useDirectByteBuffers)
|
||||
{
|
||||
_useDirectByteBuffers = useDirectByteBuffers;
|
||||
}
|
||||
|
||||
private void shrinkCache()
|
||||
{
|
||||
// While we need to shrink
|
||||
|
@ -334,7 +323,7 @@ public class CachingHttpContentFactory implements HttpContent.Factory
|
|||
throw new IllegalArgumentException("Resource is too large: length " + contentLengthValue + " > " + _maxCachedFileSize);
|
||||
|
||||
// Read the content into memory
|
||||
_buffer = IOResources.toRetainableByteBuffer(httpContent.getResource(), _bufferPool, _useDirectByteBuffers);
|
||||
_buffer = IOResources.toRetainableByteBuffer(httpContent.getResource(), _bufferPool);
|
||||
|
||||
_characterEncoding = httpContent.getCharacterEncoding();
|
||||
_compressedFormats = httpContent.getPreCompressedContentFormats();
|
||||
|
|
|
@ -121,7 +121,7 @@ public class ResourceHttpContent implements HttpContent
|
|||
@Override
|
||||
public void writeTo(Content.Sink sink, long offset, long length, Callback callback)
|
||||
{
|
||||
IOResources.copy(_resource, sink, _sizedBufferPool, _sizedBufferPool.getSize(), _sizedBufferPool.isDirect(), offset, length, callback);
|
||||
IOResources.copy(_resource, sink, _sizedBufferPool, offset, length, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ValidatingCachingHttpContentFactory extends CachingHttpContentFacto
|
|||
*/
|
||||
public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority,
|
||||
@Name("validationPeriod") long validationPeriod,
|
||||
@Name("bufferPool") ByteBufferPool bufferPool)
|
||||
@Name("bufferPool") ByteBufferPool.Sized bufferPool)
|
||||
{
|
||||
this(authority, validationPeriod, bufferPool, null, -1, -1);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public class ValidatingCachingHttpContentFactory extends CachingHttpContentFacto
|
|||
*/
|
||||
public ValidatingCachingHttpContentFactory(@Name("authority") HttpContent.Factory authority,
|
||||
@Name("validationPeriod") long validationPeriod,
|
||||
@Name("byteBufferPool") ByteBufferPool bufferPool,
|
||||
@Name("byteBufferPool") ByteBufferPool.Sized bufferPool,
|
||||
@Name("scheduler") Scheduler scheduler,
|
||||
@Name("sweepPeriod") long sweepPeriod,
|
||||
@Name("idleTimeout") long idleTimeout)
|
||||
|
|
|
@ -150,12 +150,30 @@ public interface ByteBufferPool
|
|||
}
|
||||
|
||||
/**
|
||||
* @return A {@link RetainableByteBuffer} suitable for the specified preconfigured size and type.
|
||||
* @return A {@link RetainableByteBuffer.Mutable} suitable for the specified preconfigured size and type.
|
||||
*/
|
||||
public RetainableByteBuffer acquire()
|
||||
public RetainableByteBuffer.Mutable acquire()
|
||||
{
|
||||
return getWrapped().acquire(_size, _direct);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link RetainableByteBuffer.Mutable} suitable for the specified preconfigured type.
|
||||
* @param size The specified size in bytes of the buffer
|
||||
*/
|
||||
public RetainableByteBuffer.Mutable acquire(int size)
|
||||
{
|
||||
return getWrapped().acquire(size, _direct);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A {@link RetainableByteBuffer.Mutable} suitable for the specified preconfigured type.
|
||||
* @param direct true for a direct byte buffer, false otherwise
|
||||
*/
|
||||
public RetainableByteBuffer.Mutable acquire(boolean direct)
|
||||
{
|
||||
return getWrapped().acquire(_size, direct);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -209,7 +209,7 @@ public class Content
|
|||
* @param byteBufferPool The {@link org.eclipse.jetty.io.ByteBufferPool.Sized} to use for any internal buffers.
|
||||
* @param path The {@link Path}s to use as the source.
|
||||
* @param offset The offset in bytes from which to start the source
|
||||
* @param length The length in bytes of the source.
|
||||
* @param length The length in bytes of the source, -1 for the full length.
|
||||
* @return A {@code Content.Source}
|
||||
*/
|
||||
static Content.Source from(ByteBufferPool.Sized byteBufferPool, Path path, long offset, long length)
|
||||
|
@ -247,7 +247,7 @@ public class Content
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Content.Source} from a {@link Path}.
|
||||
* Create a {@code Content.Source} from an {@link InputStream}.
|
||||
* @param byteBufferPool The {@link org.eclipse.jetty.io.ByteBufferPool.Sized} to use for any internal buffers.
|
||||
* @param inputStream The {@link InputStream}s to use as the source.
|
||||
* @return A {@code Content.Source}
|
||||
|
@ -258,7 +258,7 @@ public class Content
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Content.Source} from a {@link Path}.
|
||||
* Create a {@code Content.Source} from an {@link InputStream}.
|
||||
* @param byteBufferPool The {@link org.eclipse.jetty.io.ByteBufferPool.Sized} to use for any internal buffers.
|
||||
* @param inputStream The {@link InputStream}s to use as the source.
|
||||
* @param offset The offset in bytes from which to start the source
|
||||
|
|
|
@ -20,8 +20,6 @@ import java.nio.channels.SeekableByteChannel;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.eclipse.jetty.io.content.ByteBufferContentSource;
|
||||
import org.eclipse.jetty.io.content.InputStreamContentSource;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -31,7 +29,6 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
|
||||
/**
|
||||
* Common IO operations for {@link Resource} content.
|
||||
* // TODO use ByteBufferPool.Sized instead of ByteBufferPool in all signatures.
|
||||
*/
|
||||
public class IOResources
|
||||
{
|
||||
|
@ -43,12 +40,11 @@ public class IOResources
|
|||
* {@link Resource#newInputStream()} is used as a fallback.</p>
|
||||
*
|
||||
* @param resource the resource to be read.
|
||||
* @param bufferPool the {@link ByteBufferPool} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param direct the directness of the buffers.
|
||||
* @param bufferPool the {@link ByteBufferPool.Sized} to get buffers from. null means allocate new buffers as needed.
|
||||
* @return a {@link RetainableByteBuffer} containing the resource's contents.
|
||||
* @throws IllegalArgumentException if the resource is a directory or does not exist or there is no way to access its contents.
|
||||
*/
|
||||
public static RetainableByteBuffer toRetainableByteBuffer(Resource resource, ByteBufferPool bufferPool, boolean direct) throws IllegalArgumentException
|
||||
public static RetainableByteBuffer toRetainableByteBuffer(Resource resource, ByteBufferPool.Sized bufferPool) throws IllegalArgumentException
|
||||
{
|
||||
if (resource.isDirectory() || !resource.exists())
|
||||
throw new IllegalArgumentException("Resource must exist and cannot be a directory: " + resource);
|
||||
|
@ -59,14 +55,14 @@ public class IOResources
|
|||
|
||||
long longLength = resource.length();
|
||||
|
||||
bufferPool = bufferPool == null ? ByteBufferPool.NON_POOLING : bufferPool;
|
||||
bufferPool = bufferPool == null ? ByteBufferPool.SIZED_NON_POOLING : bufferPool;
|
||||
|
||||
// Optimize for PathResource.
|
||||
Path path = resource.getPath();
|
||||
if (path != null && longLength < Integer.MAX_VALUE)
|
||||
{
|
||||
// TODO convert to a Dynamic once HttpContent uses writeTo semantics
|
||||
RetainableByteBuffer retainableByteBuffer = bufferPool.acquire((int)longLength, direct);
|
||||
RetainableByteBuffer retainableByteBuffer = bufferPool.acquire((int)longLength);
|
||||
try (SeekableByteChannel seekableByteChannel = Files.newByteChannel(path))
|
||||
{
|
||||
long totalRead = 0L;
|
||||
|
@ -96,11 +92,11 @@ public class IOResources
|
|||
if (inputStream == null)
|
||||
throw new IllegalArgumentException("Resource does not support InputStream: " + resource);
|
||||
|
||||
RetainableByteBuffer.DynamicCapacity retainableByteBuffer = new RetainableByteBuffer.DynamicCapacity(bufferPool, direct, longLength);
|
||||
RetainableByteBuffer.DynamicCapacity retainableByteBuffer = new RetainableByteBuffer.DynamicCapacity(bufferPool, bufferPool.isDirect(), longLength);
|
||||
while (true)
|
||||
{
|
||||
if (buffer == null)
|
||||
buffer = bufferPool.acquire(8192, false);
|
||||
buffer = bufferPool.acquire(false);
|
||||
int read = inputStream.read(buffer.getByteBuffer().array());
|
||||
if (read == -1)
|
||||
break;
|
||||
|
@ -125,48 +121,6 @@ public class IOResources
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Gets a {@link Content.Source} with the contents of a resource.</p>
|
||||
* <p>The resource must not be a directory, must exists and there must be
|
||||
* a way to access its contents.</p>
|
||||
* <p>Multiple optimized methods are used to access the resource's contents but if they all fail,
|
||||
* {@link Resource#newInputStream()} is used as a fallback.</p>
|
||||
*
|
||||
* @param resource the resource from which to get a {@link Content.Source}.
|
||||
* @param bufferPool the {@link ByteBufferPool} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param bufferSize the size of the buffer to be used for the copy. Any value < 1 means use a default value.
|
||||
* @param direct the directness of the buffers, this parameter is ignored if {@code bufferSize} is < 1.
|
||||
* @return the {@link Content.Source}.
|
||||
* @throws IllegalArgumentException if the resource is a directory or does not exist or there is no way to access its contents.
|
||||
*/
|
||||
public static Content.Source asContentSource(Resource resource, ByteBufferPool bufferPool, int bufferSize, boolean direct) throws IllegalArgumentException
|
||||
{
|
||||
if (resource.isDirectory() || !resource.exists())
|
||||
throw new IllegalArgumentException("Resource must exist and cannot be a directory: " + resource);
|
||||
|
||||
// Try to find an optimized content source.
|
||||
Path path = resource.getPath();
|
||||
if (path != null)
|
||||
{
|
||||
return Content.Source.from(new ByteBufferPool.Sized(bufferPool, direct, bufferSize), path, 0, -1);
|
||||
}
|
||||
if (resource instanceof MemoryResource memoryResource)
|
||||
{
|
||||
byte[] bytes = memoryResource.getBytes();
|
||||
return new ByteBufferContentSource(ByteBuffer.wrap(bytes));
|
||||
}
|
||||
|
||||
// Fallback to wrapping InputStream.
|
||||
try
|
||||
{
|
||||
return new InputStreamContentSource(resource.newInputStream());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Gets a {@link Content.Source} with a range of the contents of a resource.</p>
|
||||
* <p>The resource must not be a directory, must exists and there must be
|
||||
|
@ -175,15 +129,13 @@ public class IOResources
|
|||
* {@link Resource#newInputStream()} is used as a fallback.</p>
|
||||
*
|
||||
* @param resource the resource from which to get a {@link Content.Source}.
|
||||
* @param bufferPool the {@link ByteBufferPool} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param bufferSize the size of the buffer to be used for the copy. Any value < 1 means use a default value.
|
||||
* @param direct the directness of the buffers, this parameter is ignored if {@code bufferSize} is < 1.
|
||||
* @param offset the first byte from which to read from.
|
||||
* @param length the length of the content to read.
|
||||
* @param bufferPool the {@link ByteBufferPool.Sized} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param offset the offset byte from which to read from.
|
||||
* @param length the length of the content to read, -1 for the full length.
|
||||
* @return the {@link Content.Source}.
|
||||
* @throws IllegalArgumentException if the resource is a directory or does not exist or there is no way to access its contents.
|
||||
*/
|
||||
public static Content.Source asContentSource(Resource resource, ByteBufferPool bufferPool, int bufferSize, boolean direct, long offset, long length) throws IllegalArgumentException
|
||||
public static Content.Source asContentSource(Resource resource, ByteBufferPool.Sized bufferPool, long offset, long length) throws IllegalArgumentException
|
||||
{
|
||||
if (resource.isDirectory() || !resource.exists())
|
||||
throw new IllegalArgumentException("Resource must exist and cannot be a directory: " + resource);
|
||||
|
@ -191,11 +143,11 @@ public class IOResources
|
|||
// Try using the resource's path if possible, as the nio API is async and helps to avoid buffer copies.
|
||||
Path path = resource.getPath();
|
||||
if (path != null)
|
||||
return Content.Source.from(new ByteBufferPool.Sized(bufferPool, direct, bufferSize), path, offset, length);
|
||||
return Content.Source.from(bufferPool, path, offset, length);
|
||||
|
||||
// Try an optimization for MemoryResource.
|
||||
if (resource instanceof MemoryResource memoryResource)
|
||||
return Content.Source.from(ByteBuffer.wrap(memoryResource.getBytes()));
|
||||
return Content.Source.from(BufferUtil.slice(ByteBuffer.wrap(memoryResource.getBytes()), (int)offset, (int)length));
|
||||
|
||||
// Fallback to InputStream.
|
||||
try
|
||||
|
@ -203,7 +155,7 @@ public class IOResources
|
|||
InputStream inputStream = resource.newInputStream();
|
||||
if (inputStream == null)
|
||||
throw new IllegalArgumentException("Resource does not support InputStream: " + resource);
|
||||
return Content.Source.from(new ByteBufferPool.Sized(bufferPool, direct, bufferSize), inputStream, offset, length);
|
||||
return Content.Source.from(bufferPool, inputStream, offset, length);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
|
@ -236,72 +188,22 @@ public class IOResources
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Performs an asynchronous copy of the contents of a resource to a sink, using the given buffer pool and buffer characteristics.</p>
|
||||
* <p>The resource must not be a directory, must exist and there must be a way to access its contents.</p>
|
||||
* <p>Multiple optimized methods are used to access the resource's contents but if they all fail,
|
||||
* {@link #asContentSource(Resource, ByteBufferPool, int, boolean)} is used as a fallback to perform the
|
||||
* {@link Content#copy(Content.Source, Content.Sink, Callback) copy}.</p>
|
||||
*
|
||||
* @param resource the resource to copy from.
|
||||
* @param sink the sink to copy to.
|
||||
* @param bufferPool the {@link ByteBufferPool} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param bufferSize the size of the buffer to be used for the copy. Any value < 1 means use a default value.
|
||||
* @param direct the directness of the buffers, this parameter is ignored if {@code bufferSize} is < 1.
|
||||
* @param callback the callback to notify when the copy is done.
|
||||
* @throws IllegalArgumentException if the resource is a directory or does not exist or there is no way to access its contents.
|
||||
*/
|
||||
public static void copy(Resource resource, Content.Sink sink, ByteBufferPool bufferPool, int bufferSize, boolean direct, Callback callback) throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resource.isDirectory() || !resource.exists())
|
||||
throw new IllegalArgumentException("Resource must exist and cannot be a directory: " + resource);
|
||||
|
||||
// Save a Content.Source allocation for resources with a Path.
|
||||
Path path = resource.getPath();
|
||||
if (path != null)
|
||||
{
|
||||
new PathToSinkCopier(path, sink, bufferPool, bufferSize, direct, callback).iterate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Directly write the byte array if the resource is a MemoryResource.
|
||||
if (resource instanceof MemoryResource memoryResource)
|
||||
{
|
||||
byte[] bytes = memoryResource.getBytes();
|
||||
sink.write(true, ByteBuffer.wrap(bytes), callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to Content.Source.
|
||||
Content.Source source = asContentSource(resource, bufferPool, bufferSize, direct);
|
||||
Content.copy(source, sink, callback);
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
callback.failed(x);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Performs an asynchronous copy of a subset of the contents of a resource to a sink, using the given buffer pool and buffer characteristics.</p>
|
||||
* <p>The resource must not be a directory, must exist and there must be a way to access its contents.</p>
|
||||
* <p>Multiple optimized methods are used to access the resource's contents but if they all fail,
|
||||
* {@link #asContentSource(Resource, ByteBufferPool, int, boolean, long, long)} is used as a fallback to perform the
|
||||
* {@link #asContentSource(Resource, ByteBufferPool.Sized, long, long)} is used as a fallback to perform the
|
||||
* {@link Content#copy(Content.Source, Content.Sink, Callback) copy}.</p>
|
||||
*
|
||||
* @param resource the resource to copy from.
|
||||
* @param sink the sink to copy to.
|
||||
* @param bufferPool the {@link ByteBufferPool} to get buffers from. null means allocate new buffers as needed.
|
||||
* @param bufferSize the size of the buffer to be used for the copy. Any value < 1 means use a default value.
|
||||
* @param direct the directness of the buffers, this parameter is ignored if {@code bufferSize} is < 1.
|
||||
* @param first the first byte of the resource to start from.
|
||||
* @param length the length of the resource's contents to copy.
|
||||
* @param offset the offset byte of the resource to start from.
|
||||
* @param length the length of the resource's contents to copy, -1 for the full length.
|
||||
* @param callback the callback to notify when the copy is done.
|
||||
* @throws IllegalArgumentException if the resource is a directory or does not exist or there is no way to access its contents.
|
||||
*/
|
||||
public static void copy(Resource resource, Content.Sink sink, ByteBufferPool bufferPool, int bufferSize, boolean direct, long first, long length, Callback callback) throws IllegalArgumentException
|
||||
public static void copy(Resource resource, Content.Sink sink, ByteBufferPool.Sized bufferPool, long offset, long length, Callback callback) throws IllegalArgumentException
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -312,20 +214,20 @@ public class IOResources
|
|||
Path path = resource.getPath();
|
||||
if (path != null)
|
||||
{
|
||||
new PathToSinkCopier(path, sink, bufferPool, bufferSize, direct, first, length, callback).iterate();
|
||||
new PathToSinkCopier(path, sink, bufferPool, offset, length, callback).iterate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Directly write the byte array if the resource is a MemoryResource.
|
||||
if (resource instanceof MemoryResource memoryResource)
|
||||
{
|
||||
ByteBuffer byteBuffer = BufferUtil.slice(ByteBuffer.wrap(memoryResource.getBytes()), Math.toIntExact(first), Math.toIntExact(length));
|
||||
ByteBuffer byteBuffer = BufferUtil.slice(ByteBuffer.wrap(memoryResource.getBytes()), Math.toIntExact(offset), Math.toIntExact(length));
|
||||
sink.write(true, byteBuffer, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to Content.Source.
|
||||
Content.Source source = asContentSource(resource, bufferPool, bufferSize, direct, first, length);
|
||||
Content.Source source = asContentSource(resource, bufferPool, offset, length);
|
||||
Content.copy(source, sink, callback);
|
||||
}
|
||||
catch (Throwable x)
|
||||
|
@ -338,35 +240,44 @@ public class IOResources
|
|||
{
|
||||
private final SeekableByteChannel channel;
|
||||
private final Content.Sink sink;
|
||||
private final ByteBufferPool pool;
|
||||
private final int bufferSize;
|
||||
private final boolean direct;
|
||||
private final ByteBufferPool.Sized pool;
|
||||
private long remainingLength;
|
||||
private RetainableByteBuffer retainableByteBuffer;
|
||||
private boolean terminated;
|
||||
|
||||
public PathToSinkCopier(Path path, Content.Sink sink, ByteBufferPool pool, int bufferSize, boolean direct, Callback callback) throws IOException
|
||||
{
|
||||
this(path, sink, pool, bufferSize, direct, -1L, -1L, callback);
|
||||
}
|
||||
|
||||
public PathToSinkCopier(Path path, Content.Sink sink, ByteBufferPool pool, int bufferSize, boolean direct, long offset, long length, Callback callback) throws IOException
|
||||
public PathToSinkCopier(Path path, Content.Sink sink, ByteBufferPool.Sized pool, long offset, long length, Callback callback) throws IOException
|
||||
{
|
||||
super(callback);
|
||||
this.channel = Files.newByteChannel(path);
|
||||
if (offset > -1)
|
||||
{
|
||||
if (offset > channel.size() && length != 0)
|
||||
throw new IllegalArgumentException("Offset outside of Path range");
|
||||
channel.position(offset);
|
||||
}
|
||||
this.sink = sink;
|
||||
this.pool = pool == null ? ByteBufferPool.NON_POOLING : pool;
|
||||
this.bufferSize = bufferSize <= 0 ? 4096 : bufferSize;
|
||||
this.direct = direct;
|
||||
this.pool = pool == null ? ByteBufferPool.SIZED_NON_POOLING : pool;
|
||||
this.remainingLength = length;
|
||||
this.channel = Files.newByteChannel(path);
|
||||
skipToOffset(channel, offset, length, this.pool);
|
||||
}
|
||||
|
||||
private static void skipToOffset(SeekableByteChannel channel, long offset, long length, ByteBufferPool.Sized pool)
|
||||
{
|
||||
if (offset > 0L && length != 0L)
|
||||
{
|
||||
RetainableByteBuffer.Mutable byteBuffer = pool.acquire(1);
|
||||
try
|
||||
{
|
||||
channel.position(offset - 1);
|
||||
if (channel.read(byteBuffer.getByteBuffer().limit(1)) == -1)
|
||||
throw new IllegalArgumentException("Offset out of range");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeIOException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
byteBuffer.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InvocationType getInvocationType()
|
||||
{
|
||||
|
@ -380,7 +291,7 @@ public class IOResources
|
|||
return Action.SUCCEEDED;
|
||||
|
||||
if (retainableByteBuffer == null)
|
||||
retainableByteBuffer = pool.acquire(bufferSize, direct);
|
||||
retainableByteBuffer = pool.acquire();
|
||||
|
||||
ByteBuffer byteBuffer = retainableByteBuffer.getByteBuffer();
|
||||
BufferUtil.clearToFill(byteBuffer);
|
||||
|
|
|
@ -73,12 +73,12 @@ public class ByteChannelContentSource implements Content.Source
|
|||
|
||||
public ByteChannelContentSource(ByteChannel byteChannel)
|
||||
{
|
||||
this(null, byteChannel, -1L, -1L);
|
||||
this(null, byteChannel, 0L, -1L);
|
||||
}
|
||||
|
||||
public ByteChannelContentSource(ByteBufferPool.Sized byteBufferPool, ByteChannel byteChannel)
|
||||
{
|
||||
this(byteBufferPool, byteChannel, -1L, -1L);
|
||||
this(byteBufferPool, byteChannel, 0L, -1L);
|
||||
}
|
||||
|
||||
private ByteChannelContentSource(ByteBufferPool.Sized byteBufferPool, ByteChannel byteChannel, long offset, long length)
|
||||
|
@ -253,17 +253,17 @@ public class ByteChannelContentSource implements Content.Source
|
|||
|
||||
public PathContentSource(Path path)
|
||||
{
|
||||
this(null, path, 0, -1);
|
||||
this(null, path, 0L, -1L);
|
||||
}
|
||||
|
||||
public PathContentSource(ByteBufferPool.Sized byteBufferPool, Path path)
|
||||
{
|
||||
this(byteBufferPool, path, 0, -1);
|
||||
this(byteBufferPool, path, 0L, -1L);
|
||||
}
|
||||
|
||||
public PathContentSource(ByteBufferPool.Sized byteBufferPool, Path path, long offset, long length)
|
||||
{
|
||||
super(byteBufferPool, null, offset, length < 0 ? size(path) : length);
|
||||
super(byteBufferPool, null, offset, length < 0L ? size(path) : length);
|
||||
_path = path;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,25 +34,28 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
|
||||
public class IOResourcesTest
|
||||
{
|
||||
private ArrayByteBufferPool.Tracking bufferPool;
|
||||
private ArrayByteBufferPool.Tracking trackingPool;
|
||||
private ByteBufferPool.Sized bufferPool;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp()
|
||||
{
|
||||
bufferPool = new ArrayByteBufferPool.Tracking();
|
||||
trackingPool = new ArrayByteBufferPool.Tracking();
|
||||
bufferPool = new ByteBufferPool.Sized(trackingPool, false, 1);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown()
|
||||
{
|
||||
assertThat("Leaks: " + bufferPool.dumpLeaks(), bufferPool.getLeaks().size(), is(0));
|
||||
assertThat("Leaks: " + trackingPool.dumpLeaks(), trackingPool.getLeaks().size(), is(0));
|
||||
}
|
||||
|
||||
public static Stream<Resource> all()
|
||||
public static Stream<Resource> all() throws Exception
|
||||
{
|
||||
URI resourceUri = MavenTestingUtils.getTestResourcePath("keystore.p12").toUri();
|
||||
return Stream.of(
|
||||
ResourceFactory.root().newResource(resourceUri),
|
||||
ResourceFactory.root().newMemoryResource(resourceUri.toURL()),
|
||||
new URLResourceFactory().newResource(resourceUri)
|
||||
);
|
||||
}
|
||||
|
@ -61,7 +64,7 @@ public class IOResourcesTest
|
|||
@MethodSource("all")
|
||||
public void testToRetainableByteBuffer(Resource resource)
|
||||
{
|
||||
RetainableByteBuffer retainableByteBuffer = IOResources.toRetainableByteBuffer(resource, bufferPool, false);
|
||||
RetainableByteBuffer retainableByteBuffer = IOResources.toRetainableByteBuffer(resource, bufferPool);
|
||||
assertThat(retainableByteBuffer.remaining(), is((int)resource.length()));
|
||||
retainableByteBuffer.release();
|
||||
}
|
||||
|
@ -72,7 +75,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 1, false);
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 0L, -1L);
|
||||
Content.copy(contentSource, sink, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
|
@ -87,7 +90,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 1, false, 100, -1);
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 100, -1);
|
||||
Content.copy(contentSource, sink, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
|
@ -102,7 +105,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 1, false, -1, 500);
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, -1, 500);
|
||||
Content.copy(contentSource, sink, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
|
@ -117,7 +120,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 1, false, 100, 500);
|
||||
Content.Source contentSource = IOResources.asContentSource(resource, bufferPool, 100, 500);
|
||||
Content.copy(contentSource, sink, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
|
@ -132,7 +135,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, 0L, -1L, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
|
||||
|
@ -146,7 +149,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, 100, -1, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, 100, -1, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
|
||||
|
@ -160,7 +163,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, -1, 500, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, -1, 500, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
|
||||
|
@ -174,7 +177,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, 100, 500, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, 100, 500, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
|
||||
|
@ -188,7 +191,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Blocker.Callback callback = Blocker.callback();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, Integer.MAX_VALUE, 1, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, Integer.MAX_VALUE, 1, callback);
|
||||
assertThrows(IllegalArgumentException.class, callback::block);
|
||||
}
|
||||
|
||||
|
@ -198,7 +201,7 @@ public class IOResourcesTest
|
|||
{
|
||||
TestSink sink = new TestSink();
|
||||
Callback.Completable callback = new Callback.Completable();
|
||||
IOResources.copy(resource, sink, bufferPool, 1, false, Integer.MAX_VALUE, 0, callback);
|
||||
IOResources.copy(resource, sink, bufferPool, Integer.MAX_VALUE, 0, callback);
|
||||
callback.get();
|
||||
List<Content.Chunk> chunks = sink.takeAccumulatedChunks();
|
||||
long sum = chunks.stream().mapToLong(Content.Chunk::remaining).sum();
|
||||
|
|
|
@ -298,7 +298,13 @@ public class BufferUtil
|
|||
{
|
||||
ByteBuffer slice = buffer.slice();
|
||||
if (offset > 0)
|
||||
slice.position(slice.position() + offset);
|
||||
{
|
||||
int newPosition = slice.position() + offset;
|
||||
if (newPosition > slice.limit() && length == 0)
|
||||
slice.position(slice.limit());
|
||||
else
|
||||
slice.position(newPosition);
|
||||
}
|
||||
if (length > -1)
|
||||
slice.limit(slice.position() + length);
|
||||
return slice;
|
||||
|
|
|
@ -68,6 +68,7 @@ public class BufferUtilTest
|
|||
assertEquals("5678", BufferUtil.toString(BufferUtil.slice(byteBuffer, 5, 4)));
|
||||
assertEquals("", BufferUtil.toString(BufferUtil.slice(byteBuffer, 1, 0)));
|
||||
assertEquals("", BufferUtil.toString(BufferUtil.slice(byteBuffer, 10, -1)));
|
||||
assertEquals("", BufferUtil.toString(BufferUtil.slice(byteBuffer, 1000, 0)));
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () -> BufferUtil.slice(byteBuffer, 0, 11));
|
||||
assertThrows(IllegalArgumentException.class, () -> BufferUtil.slice(byteBuffer, 11, -1));
|
||||
|
|
|
@ -134,7 +134,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
private long _written;
|
||||
private long _flushed;
|
||||
private long _firstByteNanoTime = -1;
|
||||
private ByteBufferPool _pool;
|
||||
private ByteBufferPool.Sized _pool;
|
||||
private RetainableByteBuffer _aggregate;
|
||||
private int _bufferSize;
|
||||
private int _commitSize;
|
||||
|
@ -580,17 +580,21 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
}
|
||||
|
||||
private ByteBufferPool.Sized getSizedByteBufferPool()
|
||||
{
|
||||
int bufferSize = getBufferSize();
|
||||
boolean useOutputDirectByteBuffers = _servletChannel.getConnectionMetaData().getHttpConfiguration().isUseOutputDirectByteBuffers();
|
||||
if (_pool == null || _pool.getSize() != bufferSize || _pool.isDirect() != useOutputDirectByteBuffers)
|
||||
_pool = new ByteBufferPool.Sized(_servletChannel.getRequest().getComponents().getByteBufferPool(), useOutputDirectByteBuffers, bufferSize);
|
||||
return _pool;
|
||||
}
|
||||
|
||||
private RetainableByteBuffer lockedAcquireBuffer()
|
||||
{
|
||||
assert _channelState.isLockHeldByCurrentThread();
|
||||
|
||||
boolean useOutputDirectByteBuffers = _servletChannel.getConnectionMetaData().getHttpConfiguration().isUseOutputDirectByteBuffers();
|
||||
|
||||
if (_aggregate == null)
|
||||
{
|
||||
_pool = _servletChannel.getRequest().getComponents().getByteBufferPool();
|
||||
_aggregate = _pool.acquire(getBufferSize(), useOutputDirectByteBuffers);
|
||||
}
|
||||
_aggregate = getSizedByteBufferPool().acquire();
|
||||
return _aggregate;
|
||||
}
|
||||
|
||||
|
|
|
@ -185,6 +185,7 @@ public class ResourceServlet extends HttpServlet
|
|||
private ServletResourceService _resourceService;
|
||||
private WelcomeServletMode _welcomeServletMode;
|
||||
private boolean _pathInfoOnly;
|
||||
private ByteBufferPool.Sized _bufferPool;
|
||||
|
||||
public ResourceService getResourceService()
|
||||
{
|
||||
|
@ -225,9 +226,8 @@ public class ResourceServlet extends HttpServlet
|
|||
if (contentFactory == null)
|
||||
{
|
||||
MimeTypes mimeTypes = contextHandler.getMimeTypes();
|
||||
ByteBufferPool bufferPool = getByteBufferPool(contextHandler);
|
||||
ByteBufferPool.Sized sizedBufferPool = new ByteBufferPool.Sized(bufferPool, getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
contentFactory = new ResourceHttpContentFactory(baseResource, mimeTypes, sizedBufferPool);
|
||||
ByteBufferPool.Sized bufferPool = getByteBufferPool(contextHandler);
|
||||
contentFactory = new ResourceHttpContentFactory(baseResource, mimeTypes, bufferPool);
|
||||
|
||||
// Use the servers default stylesheet unless there is one explicitly set by an init param.
|
||||
Resource styleSheet = contextHandler.getServer().getDefaultStyleSheet();
|
||||
|
@ -255,7 +255,7 @@ public class ResourceServlet extends HttpServlet
|
|||
if (getInitBoolean("useFileMappedBuffer", false))
|
||||
contentFactory = new FileMappingHttpContentFactory(contentFactory);
|
||||
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, styleSheet, "text/css", sizedBufferPool);
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, styleSheet, "text/css", bufferPool);
|
||||
contentFactory = new PreCompressedHttpContentFactory(contentFactory, precompressedFormats);
|
||||
|
||||
int maxCacheSize = getInitInt("maxCacheSize", -2);
|
||||
|
@ -337,14 +337,17 @@ public class ResourceServlet extends HttpServlet
|
|||
}
|
||||
}
|
||||
|
||||
private static ByteBufferPool getByteBufferPool(ContextHandler contextHandler)
|
||||
private ByteBufferPool.Sized getByteBufferPool(ContextHandler contextHandler)
|
||||
{
|
||||
if (_bufferPool != null)
|
||||
return _bufferPool;
|
||||
if (contextHandler == null)
|
||||
return ByteBufferPool.NON_POOLING;
|
||||
return ByteBufferPool.SIZED_NON_POOLING;
|
||||
Server server = contextHandler.getServer();
|
||||
if (server == null)
|
||||
return ByteBufferPool.NON_POOLING;
|
||||
return server.getByteBufferPool();
|
||||
return ByteBufferPool.SIZED_NON_POOLING;
|
||||
_bufferPool = new ByteBufferPool.Sized(server.getByteBufferPool(), getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
return _bufferPool;
|
||||
}
|
||||
|
||||
private String getInitParameter(String name, String... deprecated)
|
||||
|
|
|
@ -134,6 +134,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
private long _written;
|
||||
private long _flushed;
|
||||
private long _firstByteNanoTime = -1;
|
||||
private ByteBufferPool.Sized _pool;
|
||||
private RetainableByteBuffer _aggregate;
|
||||
private int _bufferSize;
|
||||
private int _commitSize;
|
||||
|
@ -221,7 +222,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
_state = State.CLOSED;
|
||||
closedCallback = _closedCallback;
|
||||
_closedCallback = null;
|
||||
releaseBuffer();
|
||||
lockedReleaseBuffer(failure != null);
|
||||
wake = updateApiState(failure);
|
||||
}
|
||||
else if (_state == State.CLOSE)
|
||||
|
@ -327,7 +328,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
// TODO avoid this copy.
|
||||
ByteBuffer content = _aggregate != null && _aggregate.hasRemaining() ? BufferUtil.copy(_aggregate.getByteBuffer()) : BufferUtil.EMPTY_BUFFER;
|
||||
_state = State.CLOSED;
|
||||
releaseBuffer();
|
||||
lockedReleaseBuffer(false);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
@ -457,7 +458,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
try (AutoLock ignored = _channelState.lock())
|
||||
{
|
||||
_state = State.CLOSED;
|
||||
releaseBuffer();
|
||||
lockedReleaseBuffer(failure != null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,25 +590,40 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
try (AutoLock ignored = _channelState.lock())
|
||||
{
|
||||
return acquireBuffer().getByteBuffer();
|
||||
return lockedAcquireBuffer().getByteBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
private RetainableByteBuffer acquireBuffer()
|
||||
private ByteBufferPool.Sized getSizedByteBufferPool()
|
||||
{
|
||||
int bufferSize = getBufferSize();
|
||||
boolean useOutputDirectByteBuffers = _servletChannel.getConnectionMetaData().getHttpConfiguration().isUseOutputDirectByteBuffers();
|
||||
ByteBufferPool pool = _servletChannel.getRequest().getComponents().getByteBufferPool();
|
||||
if (_pool == null || _pool.getSize() != bufferSize || _pool.isDirect() != useOutputDirectByteBuffers)
|
||||
_pool = new ByteBufferPool.Sized(_servletChannel.getRequest().getComponents().getByteBufferPool(), useOutputDirectByteBuffers, bufferSize);
|
||||
return _pool;
|
||||
}
|
||||
|
||||
private RetainableByteBuffer lockedAcquireBuffer()
|
||||
{
|
||||
assert _channelState.isLockHeldByCurrentThread();
|
||||
|
||||
if (_aggregate == null)
|
||||
_aggregate = pool.acquire(getBufferSize(), useOutputDirectByteBuffers);
|
||||
_aggregate = getSizedByteBufferPool().acquire();
|
||||
return _aggregate;
|
||||
}
|
||||
|
||||
private void releaseBuffer()
|
||||
private void lockedReleaseBuffer(boolean failure)
|
||||
{
|
||||
assert _channelState.isLockHeldByCurrentThread();
|
||||
|
||||
if (_aggregate != null)
|
||||
{
|
||||
_aggregate.release();
|
||||
if (failure && _pool != null)
|
||||
_pool.removeAndRelease(_aggregate);
|
||||
else
|
||||
_aggregate.release();
|
||||
_aggregate = null;
|
||||
_pool = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,7 +781,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
// Should we aggregate?
|
||||
if (aggregate)
|
||||
{
|
||||
acquireBuffer();
|
||||
lockedAcquireBuffer();
|
||||
int filled = BufferUtil.fill(_aggregate.getByteBuffer(), b, off, len);
|
||||
|
||||
// return if we are not complete, not full and filled all the content
|
||||
|
@ -970,7 +986,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
_written = written;
|
||||
|
||||
acquireBuffer();
|
||||
lockedAcquireBuffer();
|
||||
BufferUtil.append(_aggregate.getByteBuffer(), (byte)b);
|
||||
}
|
||||
|
||||
|
@ -1249,6 +1265,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
try (AutoLock ignored = _channelState.lock())
|
||||
{
|
||||
lockedReleaseBuffer(_state != State.CLOSED);
|
||||
_state = State.OPEN;
|
||||
_apiState = ApiState.BLOCKING;
|
||||
_softClose = true; // Stay closed until next request
|
||||
|
@ -1257,7 +1274,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
_commitSize = config.getOutputAggregationSize();
|
||||
if (_commitSize > _bufferSize)
|
||||
_commitSize = _bufferSize;
|
||||
releaseBuffer();
|
||||
_written = 0;
|
||||
_writeListener = null;
|
||||
_onError = null;
|
||||
|
|
|
@ -185,6 +185,7 @@ public class ResourceServlet extends HttpServlet
|
|||
private ServletResourceService _resourceService;
|
||||
private WelcomeServletMode _welcomeServletMode;
|
||||
private boolean _pathInfoOnly;
|
||||
private ByteBufferPool.Sized _bufferPool;
|
||||
|
||||
public ResourceService getResourceService()
|
||||
{
|
||||
|
@ -225,9 +226,8 @@ public class ResourceServlet extends HttpServlet
|
|||
if (contentFactory == null)
|
||||
{
|
||||
MimeTypes mimeTypes = contextHandler.getMimeTypes();
|
||||
ByteBufferPool bufferPool = getByteBufferPool(contextHandler);
|
||||
ByteBufferPool.Sized sizedBufferPool = new ByteBufferPool.Sized(bufferPool, getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
contentFactory = new ResourceHttpContentFactory(baseResource, mimeTypes, sizedBufferPool);
|
||||
ByteBufferPool.Sized bufferPool = new ByteBufferPool.Sized(getByteBufferPool(contextHandler), getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
contentFactory = new ResourceHttpContentFactory(baseResource, mimeTypes, bufferPool);
|
||||
|
||||
// Use the servers default stylesheet unless there is one explicitly set by an init param.
|
||||
Resource styleSheet = contextHandler.getServer().getDefaultStyleSheet();
|
||||
|
@ -255,7 +255,7 @@ public class ResourceServlet extends HttpServlet
|
|||
if (getInitBoolean("useFileMappedBuffer", false))
|
||||
contentFactory = new FileMappingHttpContentFactory(contentFactory);
|
||||
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, styleSheet, "text/css", sizedBufferPool);
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, styleSheet, "text/css", bufferPool);
|
||||
contentFactory = new PreCompressedHttpContentFactory(contentFactory, precompressedFormats);
|
||||
|
||||
int maxCacheSize = getInitInt("maxCacheSize", -2);
|
||||
|
@ -337,14 +337,17 @@ public class ResourceServlet extends HttpServlet
|
|||
}
|
||||
}
|
||||
|
||||
private static ByteBufferPool getByteBufferPool(ContextHandler contextHandler)
|
||||
private ByteBufferPool.Sized getByteBufferPool(ContextHandler contextHandler)
|
||||
{
|
||||
if (_bufferPool != null)
|
||||
return _bufferPool;
|
||||
if (contextHandler == null)
|
||||
return ByteBufferPool.NON_POOLING;
|
||||
return ByteBufferPool.SIZED_NON_POOLING;
|
||||
Server server = contextHandler.getServer();
|
||||
if (server == null)
|
||||
return ByteBufferPool.NON_POOLING;
|
||||
return server.getByteBufferPool();
|
||||
return ByteBufferPool.SIZED_NON_POOLING;
|
||||
_bufferPool = new ByteBufferPool.Sized(server.getByteBufferPool(), getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
return _bufferPool;
|
||||
}
|
||||
|
||||
private String getInitParameter(String name, String... deprecated)
|
||||
|
|
|
@ -224,6 +224,11 @@ public class ServletChannelState
|
|||
return _lock.lock();
|
||||
}
|
||||
|
||||
boolean isLockHeldByCurrentThread()
|
||||
{
|
||||
return _lock.isHeldByCurrentThread();
|
||||
}
|
||||
|
||||
public State getState()
|
||||
{
|
||||
try (AutoLock ignored = lock())
|
||||
|
|
|
@ -198,7 +198,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
private long _written;
|
||||
private long _flushed;
|
||||
private long _firstByteNanoTime = -1;
|
||||
private ByteBufferPool _pool;
|
||||
private ByteBufferPool.Sized _pool;
|
||||
private RetainableByteBuffer _aggregate;
|
||||
private int _bufferSize;
|
||||
private int _commitSize;
|
||||
|
@ -654,15 +654,21 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
}
|
||||
|
||||
private ByteBufferPool.Sized getSizedByteBufferPool()
|
||||
{
|
||||
int bufferSize = getBufferSize();
|
||||
boolean useOutputDirectByteBuffers = _channel.isUseOutputDirectByteBuffers();
|
||||
if (_pool == null || _pool.getSize() != bufferSize || _pool.isDirect() != useOutputDirectByteBuffers)
|
||||
_pool = new ByteBufferPool.Sized(_channel.getByteBufferPool(), useOutputDirectByteBuffers, bufferSize);
|
||||
return _pool;
|
||||
}
|
||||
|
||||
private RetainableByteBuffer lockedAcquireBuffer()
|
||||
{
|
||||
assert _channelState.isLockHeldByCurrentThread();
|
||||
|
||||
if (_aggregate == null)
|
||||
{
|
||||
_pool = _channel.getByteBufferPool();
|
||||
_aggregate = _pool.acquire(getBufferSize(), _channel.isUseOutputDirectByteBuffers());
|
||||
}
|
||||
_aggregate = getSizedByteBufferPool().acquire();
|
||||
return _aggregate;
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1325,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
_written += byteBuffer.remaining();
|
||||
channelWrite(byteBuffer, last, cb);
|
||||
}, _channel.getByteBufferPool(), getBufferSize(), _channel.isUseOutputDirectByteBuffers(), new Callback.Nested(callback)
|
||||
}, getSizedByteBufferPool(), 0L, -1L, new Callback.Nested(callback)
|
||||
{
|
||||
@Override
|
||||
public void succeeded()
|
||||
|
|
|
@ -32,6 +32,7 @@ import jakarta.servlet.ServletException;
|
|||
import jakarta.servlet.WriteListener;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.IOResources;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
|
@ -235,7 +236,7 @@ public class HttpOutputTest
|
|||
public void testSendBigDirect() throws Exception
|
||||
{
|
||||
Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, true).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("Content-Length"));
|
||||
|
@ -246,7 +247,7 @@ public class HttpOutputTest
|
|||
public void testSendBigInDirect() throws Exception
|
||||
{
|
||||
Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, containsString("Content-Length"));
|
||||
|
@ -311,7 +312,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[1];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -325,7 +326,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -339,7 +340,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[4000];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -353,7 +354,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8192];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -367,7 +368,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[1];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -382,7 +383,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -397,7 +398,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[4000];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -412,7 +413,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8192];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -445,7 +446,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -460,7 +461,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(4000);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -475,7 +476,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8192);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -490,7 +491,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -505,7 +506,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(4000);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -520,7 +521,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8192);
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -535,7 +536,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[1];
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -551,7 +552,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8];
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -567,7 +568,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[4000];
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -583,7 +584,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[8192];
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -618,7 +619,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8);
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -634,7 +635,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(4000);
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -650,7 +651,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8192);
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -667,7 +668,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, true).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, new ByteBufferPool.Sized(ByteBufferPool.SIZED_NON_POOLING, true, ByteBufferPool.SIZED_NON_POOLING.getSize())).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocateDirect(8192);
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -683,7 +684,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._byteBuffer = BufferUtil.allocate(8192);
|
||||
_handler._async = true;
|
||||
|
||||
|
@ -703,7 +704,7 @@ public class HttpOutputTest
|
|||
|
||||
_handler._async = true;
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[4000];
|
||||
|
||||
String response = _connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
|
@ -720,7 +721,7 @@ public class HttpOutputTest
|
|||
|
||||
_handler._async = true;
|
||||
_handler._writeLengthIfKnown = true;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[4000];
|
||||
|
||||
int start = _handler._owp.get();
|
||||
|
@ -736,7 +737,7 @@ public class HttpOutputTest
|
|||
{
|
||||
final Resource big = ResourceFactory.of(_contextHandler).newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, null, false).getByteBuffer();
|
||||
_handler._content = IOResources.toRetainableByteBuffer(big, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer();
|
||||
_handler._arrayBuffer = new byte[1024];
|
||||
_handler._interceptor = new ChainedInterceptor()
|
||||
{
|
||||
|
@ -1194,7 +1195,7 @@ public class HttpOutputTest
|
|||
|
||||
private static String toUTF8String(Resource resource)
|
||||
{
|
||||
return BufferUtil.toUTF8String(IOResources.toRetainableByteBuffer(resource, null, false).getByteBuffer());
|
||||
return BufferUtil.toUTF8String(IOResources.toRetainableByteBuffer(resource, ByteBufferPool.SIZED_NON_POOLING).getByteBuffer());
|
||||
}
|
||||
|
||||
interface ChainedInterceptor extends HttpOutput.Interceptor
|
||||
|
|
|
@ -259,9 +259,8 @@ public class DefaultServlet extends HttpServlet implements WelcomeFactory
|
|||
HttpContent.Factory contentFactory = (HttpContent.Factory)getServletContext().getAttribute(HttpContent.Factory.class.getName());
|
||||
if (contentFactory == null)
|
||||
{
|
||||
ByteBufferPool bufferPool = getByteBufferPool(_contextHandler);
|
||||
ByteBufferPool.Sized sizedBufferPool = new ByteBufferPool.Sized(bufferPool, getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
contentFactory = new ResourceHttpContentFactory(_baseResource, _mimeTypes, sizedBufferPool)
|
||||
ByteBufferPool.Sized bufferPool = new ByteBufferPool.Sized(getByteBufferPool(_contextHandler), getInitBoolean("useDirectByteBuffers", true), getInitInt("byteBufferSize", 32768));
|
||||
contentFactory = new ResourceHttpContentFactory(_baseResource, _mimeTypes, bufferPool)
|
||||
{
|
||||
@Override
|
||||
protected Resource resolve(String pathInContext)
|
||||
|
@ -271,7 +270,7 @@ public class DefaultServlet extends HttpServlet implements WelcomeFactory
|
|||
};
|
||||
if (_useFileMappedBuffer)
|
||||
contentFactory = new FileMappingHttpContentFactory(contentFactory);
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, _styleSheet, "text/css", sizedBufferPool);
|
||||
contentFactory = new VirtualHttpContentFactory(contentFactory, _styleSheet, "text/css", bufferPool);
|
||||
contentFactory = new PreCompressedHttpContentFactory(contentFactory, _resourceService.getPrecompressedFormats());
|
||||
|
||||
int maxCacheSize = getInitInt("maxCacheSize", -2);
|
||||
|
|
Loading…
Reference in New Issue