Skip to content

Commit

Permalink
Grow the histogram buffer if it is too small
Browse files Browse the repository at this point in the history
When we serialize a histogram to a byte array, the intermediate
ByteBuffer that we pass may be too small which may result in silent
truncation of the encoded histogram.

This will manifest on the driver side as a decoding failure.

This change detects this case and grows the buffer by a
factor of 2 until it fits.

Fixes #369.
  • Loading branch information
travisdowns committed Dec 6, 2023
1 parent d0c0277 commit d2b1059
Showing 1 changed file with 32 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.google.common.base.Preconditions;

import java.io.IOException;
import java.nio.ByteBuffer;
import org.HdrHistogram.Histogram;
Expand All @@ -30,16 +32,40 @@ public HistogramSerializer() {
super(Histogram.class);
}

static byte[] toByteArray(ByteBuffer buffer) {
byte[] encodedBuffer = new byte[buffer.remaining()];
buffer.get(encodedBuffer);
return encodedBuffer;
}

static ByteBuffer serializeHistogram(Histogram histo, ByteBuffer buffer) {
buffer.clear();
while (true) {
final int outBytes = histo.encodeIntoCompressedByteBuffer(buffer);
Preconditions.checkState(outBytes == buffer.position());
final int capacity = buffer.capacity();
if (outBytes < capacity) {
// encoding succesful
break;
}
// We filled the entire buffer, an indication that the buffer was not
// large enough, so we double the buffer and try again.
// See: https://github.com/HdrHistogram/HdrHistogram/issues/201
buffer = ByteBuffer.allocate(capacity * 2);
}
buffer.flip();
return buffer;
}

@Override
public void serialize(
Histogram histogram, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
ByteBuffer buffer = threadBuffer.get();
buffer.clear();
histogram.encodeIntoCompressedByteBuffer(buffer);
byte[] arr = new byte[buffer.position()];
buffer.flip();
buffer.get(arr);
jsonGenerator.writeBinary(arr);
ByteBuffer newBuffer = serializeHistogram(histogram, buffer);
if (newBuffer != buffer) {
threadBuffer.set(newBuffer);
}
jsonGenerator.writeBinary(toByteArray(newBuffer));
}
}

0 comments on commit d2b1059

Please sign in to comment.