|
|
@@ -26,18 +26,15 @@ import net.jpountz.lz4.LZ4Exception;
|
|
|
import net.jpountz.lz4.LZ4FastDecompressor;
|
|
|
|
|
|
import org.apache.lucene.util.BytesRef;
|
|
|
-import org.elasticsearch.common.bytes.BytesArray;
|
|
|
import org.elasticsearch.common.bytes.BytesReference;
|
|
|
-import org.elasticsearch.common.bytes.ReleasableBytesReference;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
|
import org.elasticsearch.common.recycler.Recycler;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
-import java.util.ArrayDeque;
|
|
|
import java.util.Locale;
|
|
|
|
|
|
/**
|
|
|
- * This file is forked from the https://netty.io project. In particular it forks the following file
|
|
|
+ * This file is forked from the https://netty.io project. In particular, it forks the following file
|
|
|
* io.netty.handler.codec.compression.Lz4FrameDecoder.
|
|
|
*
|
|
|
* It modifies the original netty code to operate on byte arrays opposed to ByteBufs.
|
|
|
@@ -46,7 +43,7 @@ import java.util.Locale;
|
|
|
*
|
|
|
* This class is necessary as Netty is not a dependency in Elasticsearch server module.
|
|
|
*/
|
|
|
-public class Lz4TransportDecompressor implements TransportDecompressor {
|
|
|
+public class Lz4TransportDecompressor extends TransportDecompressor {
|
|
|
|
|
|
private static final ThreadLocal<byte[]> DECOMPRESSED = ThreadLocal.withInitial(() -> BytesRef.EMPTY_BYTES);
|
|
|
private static final ThreadLocal<byte[]> COMPRESSED = ThreadLocal.withInitial(() -> BytesRef.EMPTY_BYTES);
|
|
|
@@ -68,9 +65,7 @@ public class Lz4TransportDecompressor implements TransportDecompressor {
|
|
|
*/
|
|
|
static final int COMPRESSION_LEVEL_BASE = 10;
|
|
|
|
|
|
- static final int MIN_BLOCK_SIZE = 64;
|
|
|
static final int MAX_BLOCK_SIZE = 1 << COMPRESSION_LEVEL_BASE + 0x0F; // 32 M
|
|
|
- static final int DEFAULT_BLOCK_SIZE = 1 << 16; // 64 KB
|
|
|
|
|
|
static final int BLOCK_TYPE_NON_COMPRESSED = 0x10;
|
|
|
static final int BLOCK_TYPE_COMPRESSED = 0x20;
|
|
|
@@ -104,37 +99,9 @@ public class Lz4TransportDecompressor implements TransportDecompressor {
|
|
|
*/
|
|
|
private int decompressedLength;
|
|
|
|
|
|
- private final Recycler<BytesRef> recycler;
|
|
|
- private final ArrayDeque<Recycler.V<BytesRef>> pages;
|
|
|
- private int pageOffset = 0;
|
|
|
- private int pageLength = 0;
|
|
|
- private boolean hasSkippedESHeader = false;
|
|
|
-
|
|
|
public Lz4TransportDecompressor(Recycler<BytesRef> recycler) {
|
|
|
+ super(recycler);
|
|
|
this.decompressor = Compression.Scheme.lz4Decompressor();
|
|
|
- this.recycler = recycler;
|
|
|
- this.pages = new ArrayDeque<>(4);
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public ReleasableBytesReference pollDecompressedPage(boolean isEOS) {
|
|
|
- if (pages.isEmpty()) {
|
|
|
- return null;
|
|
|
- } else if (pages.size() == 1) {
|
|
|
- if (isEOS) {
|
|
|
- Recycler.V<BytesRef> page = pages.pollFirst();
|
|
|
- BytesArray delegate = new BytesArray(page.v().bytes, page.v().offset, pageOffset);
|
|
|
- ReleasableBytesReference reference = new ReleasableBytesReference(delegate, page);
|
|
|
- pageLength = 0;
|
|
|
- pageOffset = 0;
|
|
|
- return reference;
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
- } else {
|
|
|
- Recycler.V<BytesRef> page = pages.pollFirst();
|
|
|
- return new ReleasableBytesReference(new BytesArray(page.v()), page);
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -142,18 +109,11 @@ public class Lz4TransportDecompressor implements TransportDecompressor {
|
|
|
return Compression.Scheme.LZ4;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void close() {
|
|
|
- for (Recycler.V<BytesRef> page : pages) {
|
|
|
- page.close();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public int decompress(BytesReference bytesReference) throws IOException {
|
|
|
int bytesConsumed = 0;
|
|
|
- if (hasSkippedESHeader == false) {
|
|
|
- hasSkippedESHeader = true;
|
|
|
+ if (hasSkippedHeader == false) {
|
|
|
+ hasSkippedHeader = true;
|
|
|
int esHeaderLength = Compression.Scheme.HEADER_LENGTH;
|
|
|
bytesReference = bytesReference.slice(esHeaderLength, bytesReference.length() - esHeaderLength);
|
|
|
bytesConsumed += esHeaderLength;
|
|
|
@@ -292,16 +252,8 @@ public class Lz4TransportDecompressor implements TransportDecompressor {
|
|
|
int bytesToCopy = decompressedLength;
|
|
|
int uncompressedOffset = 0;
|
|
|
while (bytesToCopy > 0) {
|
|
|
- final boolean isNewPage = pageOffset == pageLength;
|
|
|
- if (isNewPage) {
|
|
|
- Recycler.V<BytesRef> newPage = recycler.obtain();
|
|
|
- pageOffset = 0;
|
|
|
- pageLength = newPage.v().length;
|
|
|
- assert newPage.v().length > 0;
|
|
|
- pages.add(newPage);
|
|
|
- }
|
|
|
+ maybeAddNewPage();
|
|
|
final Recycler.V<BytesRef> page = pages.getLast();
|
|
|
-
|
|
|
int toCopy = Math.min(bytesToCopy, pageLength - pageOffset);
|
|
|
System.arraycopy(decompressed, uncompressedOffset, page.v().bytes, page.v().offset + pageOffset, toCopy);
|
|
|
pageOffset += toCopy;
|