1111import java .io .EOFException ;
1212import java .io .IOException ;
1313import java .io .InputStream ;
14- import java .nio .ByteBuffer ;
1514
1615public class ClickHouseLZ4InputStream extends InputStream {
1716
@@ -20,7 +19,13 @@ public class ClickHouseLZ4InputStream extends InputStream {
2019
2120 private final InputStream in ;
2221
23- private ByteBuffer buffer ;
22+ private byte [] outBuffer ;
23+
24+ private int position = 0 ;
25+
26+ private int limit = 0 ;
27+
28+ private byte [] inBuffer ;
2429
2530 private byte [] tmpBuffer = new byte [1 ];
2631
@@ -29,8 +34,8 @@ public ClickHouseLZ4InputStream(InputStream in, LZ4FastDecompressor decompressor
2934 super ();
3035 this .decompressor = decompressor ;
3136 this .in = in ;
32- this .buffer = ByteBuffer . allocate ( bufferSize ) ;
33- this .buffer . limit ( 0 ) ;
37+ this .outBuffer = new byte [ bufferSize ] ;
38+ this .inBuffer = new byte [ bufferSize ] ;
3439 }
3540
3641 @ Override
@@ -55,8 +60,9 @@ public int read(byte[] b, int off, int len) throws IOException {
5560
5661 int readBytes = 0 ;
5762 do {
58- int remaining = Math .min (len - readBytes , buffer .remaining ());
59- buffer .get (b , off + readBytes , remaining );
63+ int remaining = Math .min (len - readBytes , limit - position );
64+ System .arraycopy (outBuffer , position , b , off + readBytes , remaining );
65+ position += remaining ;
6066 readBytes += remaining ;
6167 } while (readBytes < len && refill () != -1 );
6268
@@ -109,30 +115,33 @@ private int refill() throws IOException {
109115 int uncompressedSize = getInt32 (headerBuff , 21 );
110116
111117 int offset = 9 ;
112- final byte [] block = new byte [compressedSizeWithHeader ];
113- block [0 ] = MAGIC ;
114- setInt32 (block , 1 , compressedSizeWithHeader );
115- setInt32 (block , 5 , uncompressedSize );
118+ if (inBuffer .length < compressedSizeWithHeader ) {
119+ LOG .debug ("compressed buff too small, new size: {}" , compressedSizeWithHeader );
120+ }
121+ inBuffer = inBuffer .length >= compressedSizeWithHeader ? inBuffer : new byte [(int ) (compressedSizeWithHeader * 1.5 )];
122+ inBuffer [0 ] = MAGIC ;
123+ setInt32 (inBuffer , 1 , compressedSizeWithHeader );
124+ setInt32 (inBuffer , 5 , uncompressedSize );
116125 // compressed data: compressed_size - 9 bytes
117126 int remaining = compressedSizeWithHeader - offset ;
118127
119- readFully = readFully (block , offset , remaining );
128+ readFully = readFully (inBuffer , offset , remaining );
120129 if (!readFully ) {
121130 throw new EOFException ("Unexpected end of stream" );
122131 }
123132
124- long [] real = ClickHouseCityHash .cityHash128 (block , 0 , compressedSizeWithHeader );
133+ long [] real = ClickHouseCityHash .cityHash128 (inBuffer , 0 , compressedSizeWithHeader );
125134 if (real [0 ] != getInt64 (headerBuff , 0 ) || real [1 ] != ClickHouseByteUtils .getInt64 (headerBuff , 8 )) {
126135 throw new ClientException ("Corrupted stream: checksum mismatch" );
127136 }
128137
129- if (buffer . capacity () < uncompressedSize ) {
130- buffer = ByteBuffer . allocate ( uncompressedSize ) ;
131- LOG .warn ( "Buffer size is too small, reallocate buffer with size: " + uncompressedSize );
138+ if (outBuffer . length < uncompressedSize ) {
139+ outBuffer = new byte [ uncompressedSize ] ;
140+ LOG .debug ( "uncompressed buff too small, new size: {}" , uncompressedSize );
132141 }
133- decompressor .decompress (ByteBuffer . wrap ( block ) , offset , buffer , 0 , uncompressedSize );
134- buffer . position ( 0 ) ;
135- buffer . limit ( uncompressedSize ) ;
142+ decompressor .decompress (inBuffer , offset , outBuffer , 0 , uncompressedSize );
143+ position = 0 ;
144+ limit = uncompressedSize ;
136145 return uncompressedSize ;
137146 }
138147
0 commit comments