|
25 | 25 |
|
26 | 26 | import org.apache.arrow.memory.ArrowBuf; |
27 | 27 | import org.apache.arrow.memory.BufferAllocator; |
28 | | -import org.apache.arrow.memory.util.MemoryUtil; |
29 | 28 | import org.apache.arrow.util.Preconditions; |
30 | | -import org.apache.arrow.vector.compression.CompressionCodec; |
| 29 | +import org.apache.arrow.vector.compression.AbstractCompressionCodec; |
31 | 30 | import org.apache.arrow.vector.compression.CompressionUtil; |
32 | 31 | import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorInputStream; |
33 | 32 | import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorOutputStream; |
|
38 | 37 | /** |
39 | 38 | * Compression codec for the LZ4 algorithm. |
40 | 39 | */ |
41 | | -public class Lz4CompressionCodec implements CompressionCodec { |
| 40 | +public class Lz4CompressionCodec extends AbstractCompressionCodec { |
42 | 41 |
|
43 | 42 | @Override |
44 | | - public ArrowBuf compress(BufferAllocator allocator, ArrowBuf uncompressedBuffer) { |
| 43 | + protected ArrowBuf doCompress(BufferAllocator allocator, ArrowBuf uncompressedBuffer) { |
45 | 44 | Preconditions.checkArgument(uncompressedBuffer.writerIndex() <= Integer.MAX_VALUE, |
46 | | - "The uncompressed buffer size exceeds the integer limit"); |
| 45 | + "The uncompressed buffer size exceeds the integer limit %s.", Integer.MAX_VALUE); |
47 | 46 |
|
48 | | - if (uncompressedBuffer.writerIndex() == 0L) { |
49 | | - // shortcut for empty buffer |
50 | | - ArrowBuf compressedBuffer = allocator.buffer(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH); |
51 | | - compressedBuffer.setLong(0, 0); |
52 | | - compressedBuffer.writerIndex(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH); |
53 | | - uncompressedBuffer.close(); |
54 | | - return compressedBuffer; |
55 | | - } |
56 | | - |
57 | | - try { |
58 | | - ArrowBuf compressedBuffer = doCompress(allocator, uncompressedBuffer); |
59 | | - long compressedLength = compressedBuffer.writerIndex() - CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH; |
60 | | - if (compressedLength > uncompressedBuffer.writerIndex()) { |
61 | | - // compressed buffer is larger, send the raw buffer |
62 | | - compressedBuffer.close(); |
63 | | - compressedBuffer = CompressionUtil.packageRawBuffer(allocator, uncompressedBuffer); |
64 | | - } |
65 | | - |
66 | | - uncompressedBuffer.close(); |
67 | | - return compressedBuffer; |
68 | | - } catch (IOException e) { |
69 | | - throw new RuntimeException(e); |
70 | | - } |
71 | | - } |
72 | | - |
73 | | - private ArrowBuf doCompress(BufferAllocator allocator, ArrowBuf uncompressedBuffer) throws IOException { |
74 | 47 | byte[] inBytes = new byte[(int) uncompressedBuffer.writerIndex()]; |
75 | 48 | PlatformDependent.copyMemory(uncompressedBuffer.memoryAddress(), inBytes, 0, uncompressedBuffer.writerIndex()); |
76 | 49 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
77 | 50 | try (InputStream in = new ByteArrayInputStream(inBytes); |
78 | 51 | OutputStream out = new FramedLZ4CompressorOutputStream(baos)) { |
79 | 52 | IOUtils.copy(in, out); |
| 53 | + } catch (IOException e) { |
| 54 | + throw new RuntimeException(e); |
80 | 55 | } |
81 | 56 |
|
82 | 57 | byte[] outBytes = baos.toByteArray(); |
83 | 58 |
|
84 | 59 | ArrowBuf compressedBuffer = allocator.buffer(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH + outBytes.length); |
85 | | - |
86 | | - long uncompressedLength = uncompressedBuffer.writerIndex(); |
87 | | - if (!MemoryUtil.LITTLE_ENDIAN) { |
88 | | - uncompressedLength = Long.reverseBytes(uncompressedLength); |
89 | | - } |
90 | | - // first 8 bytes reserved for uncompressed length, according to the specification |
91 | | - compressedBuffer.setLong(0, uncompressedLength); |
92 | | - |
93 | 60 | PlatformDependent.copyMemory( |
94 | 61 | outBytes, 0, compressedBuffer.memoryAddress() + CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH, outBytes.length); |
95 | 62 | compressedBuffer.writerIndex(CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH + outBytes.length); |
96 | 63 | return compressedBuffer; |
97 | 64 | } |
98 | 65 |
|
99 | 66 | @Override |
100 | | - public ArrowBuf decompress(BufferAllocator allocator, ArrowBuf compressedBuffer) { |
| 67 | + protected ArrowBuf doDecompress(BufferAllocator allocator, ArrowBuf compressedBuffer) { |
101 | 68 | Preconditions.checkArgument(compressedBuffer.writerIndex() <= Integer.MAX_VALUE, |
102 | | - "The compressed buffer size exceeds the integer limit"); |
103 | | - |
104 | | - Preconditions.checkArgument(compressedBuffer.writerIndex() >= CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH, |
105 | | - "Not enough data to decompress."); |
| 69 | + "The compressed buffer size exceeds the integer limit %s", Integer.MAX_VALUE); |
106 | 70 |
|
107 | | - long decompressedLength = compressedBuffer.getLong(0); |
108 | | - if (!MemoryUtil.LITTLE_ENDIAN) { |
109 | | - decompressedLength = Long.reverseBytes(decompressedLength); |
110 | | - } |
111 | | - |
112 | | - if (decompressedLength == 0L) { |
113 | | - // shortcut for empty buffer |
114 | | - compressedBuffer.close(); |
115 | | - return allocator.getEmpty(); |
116 | | - } |
117 | | - |
118 | | - if (decompressedLength == CompressionUtil.NO_COMPRESSION_LENGTH) { |
119 | | - // no compression |
120 | | - return CompressionUtil.extractUncompressedBuffer(compressedBuffer); |
121 | | - } |
122 | | - |
123 | | - try { |
124 | | - ArrowBuf decompressedBuffer = doDecompress(allocator, compressedBuffer); |
125 | | - compressedBuffer.close(); |
126 | | - return decompressedBuffer; |
127 | | - } catch (IOException e) { |
128 | | - throw new RuntimeException(e); |
129 | | - } |
130 | | - } |
131 | | - |
132 | | - private ArrowBuf doDecompress(BufferAllocator allocator, ArrowBuf compressedBuffer) throws IOException { |
133 | | - long decompressedLength = compressedBuffer.getLong(0); |
134 | | - if (!MemoryUtil.LITTLE_ENDIAN) { |
135 | | - decompressedLength = Long.reverseBytes(decompressedLength); |
136 | | - } |
| 71 | + long decompressedLength = readUncompressedLength(compressedBuffer); |
137 | 72 |
|
138 | 73 | byte[] inBytes = new byte[(int) (compressedBuffer.writerIndex() - CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH)]; |
139 | 74 | PlatformDependent.copyMemory( |
140 | 75 | compressedBuffer.memoryAddress() + CompressionUtil.SIZE_OF_UNCOMPRESSED_LENGTH, inBytes, 0, inBytes.length); |
141 | 76 | ByteArrayOutputStream out = new ByteArrayOutputStream((int) decompressedLength); |
142 | 77 | try (InputStream in = new FramedLZ4CompressorInputStream(new ByteArrayInputStream(inBytes))) { |
143 | 78 | IOUtils.copy(in, out); |
| 79 | + } catch (IOException e) { |
| 80 | + throw new RuntimeException(e); |
144 | 81 | } |
145 | 82 |
|
146 | 83 | byte[] outBytes = out.toByteArray(); |
|
0 commit comments