in src/main/java/org/mariadb/jdbc/internal/io/output/CompressPacketOutputStream.java [147:442]
protected void flushBuffer(boolean commandEnd) throws IOException {
if (pos > 0) {
if (pos + remainingData.length > MIN_COMPRESSION_SIZE) {
byte[] compressedBytes;
int uncompressSize = Math.min(MAX_PACKET_LENGTH, remainingData.length + 4 + pos);
checkMaxAllowedLength(uncompressSize);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (DeflaterOutputStream deflater = new DeflaterOutputStream(baos)) {
if (remainingData.length != 0) {
deflater.write(remainingData);
}
subHeader[0] = (byte) pos;
subHeader[1] = (byte) (pos >>> 8);
subHeader[2] = (byte) (pos >>> 16);
subHeader[3] = (byte) this.seqNo++;
deflater.write(subHeader, 0, 4);
deflater.write(buf, 0, uncompressSize - (remainingData.length + 4));
deflater.finish();
}
compressedBytes = baos.toByteArray();
if (compressedBytes.length < (int) (MIN_COMPRESSION_RATIO * pos)) {
int compressedLength = compressedBytes.length;
header[0] = (byte) compressedLength;
header[1] = (byte) (compressedLength >>> 8);
header[2] = (byte) (compressedLength >>> 16);
header[3] = (byte) this.compressSeqNo++;
header[4] = (byte) uncompressSize;
header[5] = (byte) (uncompressSize >>> 8);
header[6] = (byte) (uncompressSize >>> 16);
out.write(header, 0, 7);
out.write(compressedBytes, 0, compressedLength);
cmdLength += uncompressSize;
if (traceCache != null) {
// trace last packets
if (remainingData.length != 0) {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(remainingData, 0, remainingData.length),
Arrays.copyOfRange(subHeader, 0, 4),
Arrays.copyOfRange(
buf,
0,
(uncompressSize > 1000 ? 1000 : uncompressSize)
- (remainingData.length + 4))));
} else {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(subHeader, 0, 4),
Arrays.copyOfRange(
buf,
0,
(uncompressSize > 1000 ? 1000 : uncompressSize)
- (remainingData.length + 4))));
}
}
if (logger.isTraceEnabled()) {
if (remainingData.length != 0) {
logger.trace(
"send compress: {}{}",
serverThreadLog,
Utils.hexdump(
maxQuerySizeToLog - (remainingData.length + 11),
0,
compressedLength,
header,
remainingData,
subHeader,
buf));
} else {
logger.trace(
"send compress: {}{}",
serverThreadLog,
Utils.hexdump(
maxQuerySizeToLog - 11, 0, compressedLength, header, subHeader, buf));
}
}
if (pos + remainingData.length + 4 - uncompressSize > 0) {
remainingData =
Arrays.copyOfRange(buf, uncompressSize - (remainingData.length + 4), pos);
} else {
remainingData = EMPTY_ARRAY;
}
// if last packet fill the max size, must send an empty packet to indicate command end.
lastPacketExactMaxPacketLength = pos == MAX_PACKET_LENGTH;
if (commandEnd && lastPacketExactMaxPacketLength) {
writeEmptyPacket();
}
pos = 0;
return;
}
}
}
int uncompressSize = Math.min(MAX_PACKET_LENGTH, remainingData.length + 4 + pos);
checkMaxAllowedLength(uncompressSize);
cmdLength += uncompressSize;
// send packet without compression
header[0] = (byte) uncompressSize;
header[1] = (byte) (uncompressSize >>> 8);
header[2] = (byte) (uncompressSize >>> 16);
header[3] = (byte) this.compressSeqNo++;
header[4] = (byte) 0x00;
header[5] = (byte) 0x00;
header[6] = (byte) 0x00;
out.write(header, 0, 7);
cmdLength += uncompressSize;
if (remainingData.length != 0) {
out.write(remainingData);
}
subHeader[0] = (byte) pos;
subHeader[1] = (byte) (pos >>> 8);
subHeader[2] = (byte) (pos >>> 16);
subHeader[3] = (byte) this.seqNo++;
out.write(subHeader, 0, 4);
out.write(buf, 0, uncompressSize - (remainingData.length + 4));
cmdLength += remainingData.length;
if (traceCache != null) {
// trace last packets
if (remainingData.length != 0) {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_NOT_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(remainingData, 0, remainingData.length),
Arrays.copyOfRange(subHeader, 0, 4),
Arrays.copyOfRange(
buf,
0,
(uncompressSize > 1000 ? 1000 : uncompressSize)
- (remainingData.length + 4))));
} else {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_NOT_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(subHeader, 0, 4),
Arrays.copyOfRange(
buf,
0,
(uncompressSize > 1000 ? 1000 : uncompressSize)
- (remainingData.length + 4))));
}
}
if (logger.isTraceEnabled()) {
if (remainingData.length != 0) {
logger.trace(
"send uncompress: {}{}",
serverThreadLog,
Utils.hexdump(
maxQuerySizeToLog - (remainingData.length + 11),
0,
pos,
header,
remainingData,
subHeader,
buf));
} else {
logger.trace(
"send uncompress: {}{}",
serverThreadLog,
Utils.hexdump(maxQuerySizeToLog - 11, 0, pos, header, subHeader, buf));
}
}
if (pos + remainingData.length + 4 - uncompressSize > 0) {
remainingData = Arrays.copyOfRange(buf, uncompressSize - (remainingData.length + 4), pos);
} else {
remainingData = EMPTY_ARRAY;
}
// if last packet fill the max size, must send an empty packet to indicate command end.
lastPacketExactMaxPacketLength = pos == MAX_PACKET_LENGTH;
pos = 0;
}
if (remainingData.length > 0) {
if (remainingData.length > MIN_COMPRESSION_SIZE) {
byte[] compressedBytes;
int uncompressSize = Math.min(MAX_PACKET_LENGTH, remainingData.length);
checkMaxAllowedLength(uncompressSize);
cmdLength += uncompressSize;
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (DeflaterOutputStream deflater = new DeflaterOutputStream(baos)) {
deflater.write(remainingData);
deflater.finish();
}
compressedBytes = baos.toByteArray();
remainingData = EMPTY_ARRAY;
}
if (compressedBytes.length < (int) (MIN_COMPRESSION_RATIO * pos)) {
int compressedLength = compressedBytes.length;
header[0] = (byte) compressedLength;
header[1] = (byte) (compressedLength >>> 8);
header[2] = (byte) (compressedLength >>> 16);
header[3] = (byte) this.compressSeqNo++;
header[4] = (byte) uncompressSize;
header[5] = (byte) (uncompressSize >>> 8);
header[6] = (byte) (uncompressSize >>> 16);
out.write(header, 0, 7);
out.write(compressedBytes, 0, compressedLength);
if (traceCache != null) {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(
remainingData, 0, (uncompressSize > 1000 ? 1000 : uncompressSize))));
}
if (logger.isTraceEnabled()) {
logger.trace(
"send compress: {}{}",
serverThreadLog,
Utils.hexdump(maxQuerySizeToLog - 7, 0, uncompressSize, header, remainingData));
}
// if last packet fill the max size, must send an empty packet to indicate command end.
if (commandEnd && lastPacketExactMaxPacketLength) {
writeEmptyPacket();
}
return;
}
}
int uncompressSize = Math.min(MAX_PACKET_LENGTH, remainingData.length);
checkMaxAllowedLength(uncompressSize);
cmdLength += uncompressSize;
// send packet without compression
header[0] = (byte) uncompressSize;
header[1] = (byte) (uncompressSize >>> 8);
header[2] = (byte) (uncompressSize >>> 16);
header[3] = (byte) this.compressSeqNo++;
header[4] = (byte) 0x00;
header[5] = (byte) 0x00;
header[6] = (byte) 0x00;
out.write(header, 0, 7);
out.write(remainingData);
remainingData = EMPTY_ARRAY;
if (traceCache != null) {
traceCache.put(
new TraceObject(
true,
COMPRESSED_PROTOCOL_NOT_COMPRESSED_PACKET,
threadId,
Arrays.copyOfRange(header, 0, 7),
Arrays.copyOfRange(
remainingData,
0,
(remainingData.length > 1000 ? 1000 : remainingData.length))));
}
if (logger.isTraceEnabled()) {
logger.trace(
"send uncompress: {}{}",
serverThreadLog,
Utils.hexdump(maxQuerySizeToLog - 7, 0, remainingData.length, header, remainingData));
}
if (commandEnd && lastPacketExactMaxPacketLength) {
writeEmptyPacket();
}
}
}