|
@@ -10,12 +10,18 @@ package org.elasticsearch.index.codec.tsdb;
|
|
|
|
|
|
import org.apache.lucene.store.DataInput;
|
|
|
import org.apache.lucene.store.DataOutput;
|
|
|
+import org.elasticsearch.common.util.ByteUtils;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
public class DocValuesForUtil {
|
|
|
+ private static final int BITS_IN_FOUR_BYTES = 4 * Byte.SIZE;
|
|
|
+ private static final int BITS_IN_FIVE_BYTES = 5 * Byte.SIZE;
|
|
|
+ private static final int BITS_IN_SIX_BYTES = 6 * Byte.SIZE;
|
|
|
+ private static final int BITS_IN_SEVEN_BYTES = 7 * Byte.SIZE;
|
|
|
private final ForUtil forUtil = new ForUtil();
|
|
|
private final int blockSize;
|
|
|
+ private final byte[] encoded;
|
|
|
|
|
|
public DocValuesForUtil() {
|
|
|
this(ES87TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE);
|
|
@@ -23,9 +29,25 @@ public class DocValuesForUtil {
|
|
|
|
|
|
private DocValuesForUtil(int blockSize) {
|
|
|
this.blockSize = blockSize;
|
|
|
+ this.encoded = new byte[1024];
|
|
|
}
|
|
|
|
|
|
- public void encode(long[] in, int bitsPerValue, DataOutput out) throws IOException {
|
|
|
+ public static int roundBits(int bitsPerValue) {
|
|
|
+ if (bitsPerValue > 24 && bitsPerValue <= 32) {
|
|
|
+ return BITS_IN_FOUR_BYTES;
|
|
|
+ } else if (bitsPerValue > 32 && bitsPerValue <= BITS_IN_FIVE_BYTES) {
|
|
|
+ return BITS_IN_FIVE_BYTES;
|
|
|
+ } else if (bitsPerValue > BITS_IN_FIVE_BYTES && bitsPerValue <= BITS_IN_SIX_BYTES) {
|
|
|
+ return BITS_IN_SIX_BYTES;
|
|
|
+ } else if (bitsPerValue > BITS_IN_SIX_BYTES && bitsPerValue <= BITS_IN_SEVEN_BYTES) {
|
|
|
+ return BITS_IN_SEVEN_BYTES;
|
|
|
+ } else if (bitsPerValue > BITS_IN_SEVEN_BYTES) {
|
|
|
+ return Long.BYTES * Byte.SIZE;
|
|
|
+ }
|
|
|
+ return bitsPerValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void encode(long[] in, int bitsPerValue, final DataOutput out) throws IOException {
|
|
|
if (bitsPerValue <= 24) { // these bpvs are handled efficiently by ForUtil
|
|
|
forUtil.encode(in, bitsPerValue, out);
|
|
|
} else if (bitsPerValue <= 32) {
|
|
@@ -33,24 +55,49 @@ public class DocValuesForUtil {
|
|
|
for (int i = 0; i < blockSize / 2; ++i) {
|
|
|
out.writeLong(in[i]);
|
|
|
}
|
|
|
+ } else if (bitsPerValue == BITS_IN_FIVE_BYTES || bitsPerValue == BITS_IN_SIX_BYTES || bitsPerValue == BITS_IN_SEVEN_BYTES) {
|
|
|
+ encodeFiveSixOrSevenBytesPerValue(in, bitsPerValue, out);
|
|
|
} else {
|
|
|
+ assert bitsPerValue > 56 : "bitsPerValue must be greater than 56 but was [" + bitsPerValue + "]";
|
|
|
for (long l : in) {
|
|
|
out.writeLong(l);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void decode(int bitsPerValue, DataInput in, long[] out) throws IOException {
|
|
|
+ private void encodeFiveSixOrSevenBytesPerValue(long[] in, int bitsPerValue, final DataOutput out) throws IOException {
|
|
|
+ int bytesPerValue = bitsPerValue / Byte.SIZE;
|
|
|
+ for (int i = 0; i < in.length; ++i) {
|
|
|
+ ByteUtils.writeLongLE(in[i], this.encoded, i * bytesPerValue);
|
|
|
+ }
|
|
|
+ out.writeBytes(this.encoded, bytesPerValue * in.length);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void decode(int bitsPerValue, final DataInput in, long[] out) throws IOException {
|
|
|
if (bitsPerValue <= 24) {
|
|
|
forUtil.decode(bitsPerValue, in, out);
|
|
|
} else if (bitsPerValue <= 32) {
|
|
|
in.readLongs(out, 0, blockSize / 2);
|
|
|
expand32(out);
|
|
|
+ } else if (bitsPerValue == BITS_IN_FIVE_BYTES || bitsPerValue == BITS_IN_SIX_BYTES || bitsPerValue == BITS_IN_SEVEN_BYTES) {
|
|
|
+ decodeFiveSixOrSevenBytesPerValue(bitsPerValue, in, out);
|
|
|
} else {
|
|
|
+ assert bitsPerValue > 56 : "bitsPerValue must be greater than 56 but was [" + bitsPerValue + "]";
|
|
|
in.readLongs(out, 0, blockSize);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private void decodeFiveSixOrSevenBytesPerValue(int bitsPerValue, final DataInput in, long[] out) throws IOException {
|
|
|
+ // NOTE: we expect multibyte values to be written "least significant byte" first
|
|
|
+ int bytesPerValue = bitsPerValue / Byte.SIZE;
|
|
|
+ long mask = (1L << bitsPerValue) - 1;
|
|
|
+ byte[] buffer = new byte[bytesPerValue * blockSize + Long.BYTES - bytesPerValue];
|
|
|
+ in.readBytes(buffer, 0, bytesPerValue * blockSize);
|
|
|
+ for (int i = 0; i < blockSize; ++i) {
|
|
|
+ out[i] = ByteUtils.readLongLE(buffer, i * bytesPerValue) & mask;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static void collapse32(long[] arr) {
|
|
|
for (int i = 0; i < 64; ++i) {
|
|
|
arr[i] = (arr[i] << 32) | arr[64 + i];
|