private void compress(FrameEntry entry, boolean first)
{
// Get a chunk of the payload to avoid to blow
// the heap if the payload is a huge mapped file.
Frame frame = entry.frame;
ByteBuffer data = frame.getPayload();
int remaining = data.remaining();
int inputLength = Math.min(remaining, INPUT_BUFSIZE);
if (LOG.isDebugEnabled())
LOG.debug("Compressing {}: {} bytes in {} bytes chunk", entry, remaining, inputLength);
// Avoid to copy the bytes if the ByteBuffer
// is backed by an array.
int inputOffset;
byte[] input;
if (data.hasArray())
{
input = data.array();
int position = data.position();
inputOffset = position + data.arrayOffset();
data.position(position + inputLength);
}
else
{
input = new byte[inputLength];
inputOffset = 0;
data.get(input, 0, inputLength);
}
finished = inputLength == remaining;
compressor.setInput(input, inputOffset, inputLength);
// Use an additional space in case the content is not compressible.
byte[] output = new byte[inputLength + 64];
int outputOffset = 0;
int outputLength = 0;
while (true)
{
int space = output.length - outputOffset;
int compressed = compressor.deflate(output, outputOffset, space, Deflater.SYNC_FLUSH);
outputLength += compressed;
if (compressed < space)
{
// Everything was compressed.
break;
}
else
{
// The compressed output is bigger than the uncompressed input.
byte[] newOutput = new byte[output.length * 2];
System.arraycopy(output, 0, newOutput, 0, output.length);
outputOffset += output.length;
output = newOutput;
}
}
boolean fin = frame.isFin() && finished;
// Handle tail bytes generated by SYNC_FLUSH.
if(tailDrop == TAIL_DROP_ALWAYS) {
payload = ByteBuffer.wrap(output, 0, outputLength - TAIL_BYTES.length);
} else if(tailDrop == TAIL_DROP_FIN_ONLY) {
payload = ByteBuffer.wrap(output, 0, outputLength - (fin?TAIL_BYTES.length:0));
} else {
// always include
payload = ByteBuffer.wrap(output, 0, outputLength);
}
if (LOG.isDebugEnabled())
{
LOG.debug("Compressed {}: {}->{} chunk bytes",entry,inputLength,outputLength);
}
boolean continuation = frame.getType().isContinuation() || !first;
DataFrame chunk = new DataFrame(frame, continuation);
if(rsvUse == RSV_USE_ONLY_FIRST) {
chunk.setRsv1(!continuation);
} else {
// always set