This is an automated email from the ASF dual-hosted git repository.
lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git
The following commit(s) were added to refs/heads/main by this push:
new b0e51af85 GH-1116: [Java] Fix compressed buffer prefix write and ZSTD
dstCapacity (#1119)
b0e51af85 is described below
commit b0e51af855ef5befac903b1a6de3f535258ccd1b
Author: YangJie <[email protected]>
AuthorDate: Tue Jun 30 12:40:01 2026 +0800
GH-1116: [Java] Fix compressed buffer prefix write and ZSTD dstCapacity
(#1119)
## What
Two fixes in the compression codec:
1. **`AbstractCompressionCodec.compress()`: capture `writerIndex()`
once**
The previous code read `uncompressedBuffer.writerIndex()` at multiple
sites — for the size comparison and again after `doCompress()` to
populate the 8-byte uncompressed-length prefix. Capture the value once
at the top of `compress()` and reuse it for the empty-buffer check, the
size comparison, and the prefix, so all three consumers see the same
value.
2. **`ZstdCompressionCodec.doCompress()`: `dstCapacity` overstated by 8
bytes**
`Zstd.compressUnsafe(dst, dstSize, ...)` expects `dstSize` to be the
available space from `dst`. The code offsets `dst` by 8 bytes past the
prefix but passed `8 + maxSize` instead of `maxSize`. The
`compressBound()` headroom hides this in practice, but the parameter was
semantically wrong. Pass `maxSize`.
## Tests
Covered by the existing round-trip tests (`testEmptyBuffer`,
`testReadWriteStream`, `testReadWriteFile`, etc.). I was not able to
construct a minimal reproducer for the original `declaredUncompressed=0`
symptom on the unfixed code, so both fixes are conservative correctness
improvements derived from code inspection rather than failing-then-green
regression tests.
---
.../java/org/apache/arrow/compression/ZstdCompressionCodec.java | 2 +-
.../apache/arrow/vector/compression/AbstractCompressionCodec.java | 7 +++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git
a/compression/src/main/java/org/apache/arrow/compression/ZstdCompressionCodec.java
b/compression/src/main/java/org/apache/arrow/compression/ZstdCompressionCodec.java
index 290723608..ed46fe81b 100644
---
a/compression/src/main/java/org/apache/arrow/compression/ZstdCompressionCodec.java
+++
b/compression/src/main/java/org/apache/arrow/compression/ZstdCompressionCodec.java
@@ -44,7 +44,7 @@ public class ZstdCompressionCodec extends
AbstractCompressionCodec {
long bytesWritten =
Zstd.compressUnsafe(
compressedBuffer.memoryAddress() +
CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH,
- dstSize,
+ maxSize,
/*src*/ uncompressedBuffer.memoryAddress(),
/* srcSize= */ uncompressedBuffer.writerIndex(),
/* level= */ this.compressionLevel);
diff --git
a/vector/src/main/java/org/apache/arrow/vector/compression/AbstractCompressionCodec.java
b/vector/src/main/java/org/apache/arrow/vector/compression/AbstractCompressionCodec.java
index 58d9e4db9..b108173c8 100644
---
a/vector/src/main/java/org/apache/arrow/vector/compression/AbstractCompressionCodec.java
+++
b/vector/src/main/java/org/apache/arrow/vector/compression/AbstractCompressionCodec.java
@@ -29,7 +29,11 @@ public abstract class AbstractCompressionCodec implements
CompressionCodec {
@Override
public ArrowBuf compress(BufferAllocator allocator, ArrowBuf
uncompressedBuffer) {
- if (uncompressedBuffer.writerIndex() == 0L) {
+ // GH-1116: capture writerIndex() once so the empty-buffer check, size
+ // comparison, and uncompressed-length prefix all see the same value.
+ long uncompressedLength = uncompressedBuffer.writerIndex();
+
+ if (uncompressedLength == 0L) {
// shortcut for empty buffer
ArrowBuf compressedBuffer =
allocator.buffer(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH);
compressedBuffer.setLong(0, 0);
@@ -41,7 +45,6 @@ public abstract class AbstractCompressionCodec implements
CompressionCodec {
ArrowBuf compressedBuffer = doCompress(allocator, uncompressedBuffer);
long compressedLength =
compressedBuffer.writerIndex() -
CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH;
- long uncompressedLength = uncompressedBuffer.writerIndex();
if (compressedLength > uncompressedLength) {
// compressed buffer is larger, send the raw buffer