From 0902d0e6e7918c91991f2d3bb3a9c72be00f4add Mon Sep 17 00:00:00 2001 From: Gian Merlino Date: Mon, 12 Apr 2021 15:21:51 -0700 Subject: [PATCH] LongsLongEncodingReader: Implement "duplicate", fixing concurrency bug. Regression introduced in #11004 due to overzealous optimization. Even though we replaced stateful usage of ByteBuffer with stateless usage of Memory, we still need to create a new object on "duplicate" due to semantics of setBuffer. --- .../org/apache/druid/segment/data/CompressionFactory.java | 5 +++++ .../apache/druid/segment/data/LongsLongEncodingReader.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/processing/src/main/java/org/apache/druid/segment/data/CompressionFactory.java b/processing/src/main/java/org/apache/druid/segment/data/CompressionFactory.java index 0b45cdb8d5cf..10943316b707 100644 --- a/processing/src/main/java/org/apache/druid/segment/data/CompressionFactory.java +++ b/processing/src/main/java/org/apache/druid/segment/data/CompressionFactory.java @@ -287,6 +287,11 @@ public interface LongEncodingReader int read(long[] out, int outPosition, int[] indexes, int length, int indexOffset, int limit); + /** + * Duplicates this reader, creating a new reader that does not share any state. Important to achieve thread-safety, + * because a common pattern is to duplicate a reader multiple times and then call {@link #setBuffer} on the + * various duplicates. + */ LongEncodingReader duplicate(); } diff --git a/processing/src/main/java/org/apache/druid/segment/data/LongsLongEncodingReader.java b/processing/src/main/java/org/apache/druid/segment/data/LongsLongEncodingReader.java index 7fd1aef58b42..2ed0459121af 100644 --- a/processing/src/main/java/org/apache/druid/segment/data/LongsLongEncodingReader.java +++ b/processing/src/main/java/org/apache/druid/segment/data/LongsLongEncodingReader.java @@ -69,6 +69,6 @@ public int read(long[] out, int outPosition, int[] indexes, int length, int inde @Override public CompressionFactory.LongEncodingReader duplicate() { - return this; + return new LongsLongEncodingReader(buffer.getByteBuffer(), buffer.getTypeByteOrder()); } }