blob: 780eda63cbb3298d00e20565dd003a3c972a38f5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.drill.exec.store.parquet.columnreaders;
import io.netty.buffer.DrillBuf;
import java.nio.ByteBuffer;
import org.apache.drill.exec.store.parquet.columnreaders.VarLenColumnBulkInput.VarLenColumnBulkInputCallback;
/** Abstract class for sub-classes implementing several algorithms for loading a Bulk Entry */
abstract class VarLenAbstractEntryReader {
/** byte buffer used for buffering page data */
protected final ByteBuffer buffer;
/** Bulk entry */
protected final VarLenColumnBulkEntry entry;
/** A callback to allow bulk readers interact with their container */
private final VarLenColumnBulkInputCallback containerCallback;
/**
* CTOR.
* @param buffer byte buffer for data buffering (within CPU cache)
* @param entry reusable bulk entry object
* @param containerCallback callback to allow a bulk reader to interact with its parent
*/
VarLenAbstractEntryReader(ByteBuffer buffer,
VarLenColumnBulkEntry entry,
VarLenColumnBulkInputCallback containerCallback) {
this.buffer = buffer;
this.entry = entry;
this.containerCallback = containerCallback;
}
/**
* @param valsToReadWithinPage maximum values to read within the current page
* @return a bulk entry object
*/
abstract VarLenColumnBulkEntry getEntry(int valsToReadWithinPage);
/**
* @param newBitsMemory new "bits" memory size
* @param newOffsetsMemory new "offsets" memory size
* @param newDataMemory new "data" memory size
* @return true if the new payload ("bits", "offsets", "data") will trigger a constraint violation; false
* otherwise
*/
protected boolean batchMemoryConstraintsReached(int newBitsMemory, int newOffsetsMemory, int newDataMemory) {
return containerCallback.batchMemoryConstraintsReached(newBitsMemory, newOffsetsMemory, newDataMemory);
}
/**
* @param buff source buffer
* @param pos start position
* @return an integer encoded as a low endian
*/
static final int getInt(final byte[] buff, final int pos) {
return DrillBuf.getInt(buff, pos);
}
/**
* Copy data; expects 8bytes PADDING for source and target
*
* @param src source buffer
* @param srcIndex source index
* @param dest destination buffer
* @param destIndex destination buffer
* @param length length to copy (in bytes)
*/
static void vlCopy(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
if (length <= 8) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
} else {
vlCopyGTLongWithPadding(src, srcIndex, dest, destIndex, length);
}
}
/**
* Copy data; no PADDING needed for source and target (though less efficient than the copy with
* padding as more comparisons need to be made).
*
* @param src source buffer
* @param srcIndex source index
* @param dest destination buffer
* @param destIndex destination buffer
* @param length length to copy (in bytes)
*/
static void vlCopyNoPadding(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
if (length <= 8) {
vlCopyLELongNoPadding(src, srcIndex, dest, destIndex, length);
} else {
vlCopyGTLongNoPadding(src, srcIndex, dest, destIndex, length);
}
}
private static void vlCopyGTLongWithPadding(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
final int bulkCopyThreshold = 24;
if (length < bulkCopyThreshold) {
_vlCopyGTLongWithPadding(src, srcIndex, dest, destIndex, length);
} else {
System.arraycopy(src, srcIndex, dest, destIndex, length);
}
}
private static void _vlCopyGTLongWithPadding(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
final int numLongEntries = length >> 3;
assert numLongEntries < 3;
final int remaining = length & 0x7;
int prevCopied = 0;
if (numLongEntries == 1) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
prevCopied = 1 << 3;
} else {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
DrillBuf.putLong(src, srcIndex + DrillBuf.LONG_NUM_BYTES, dest, destIndex + DrillBuf.LONG_NUM_BYTES);
prevCopied = 1 << 4;
}
if (remaining > 0) {
final int srcPos = srcIndex + prevCopied;
final int destPos = destIndex + prevCopied;
DrillBuf.putLong(src, srcPos, dest, destPos);
}
}
private static final void vlCopyLELongNoPadding(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
if (length == 1) {
dest[destIndex] = src[srcIndex];
} else if (length == 2) {
DrillBuf.putShort(src, srcIndex, dest, destIndex);
} else if (length == 3) {
dest[destIndex] = src[srcIndex];
DrillBuf.putShort(src, srcIndex+1, dest, destIndex+1);
} else if (length == 4) {
DrillBuf.putInt(src, srcIndex, dest, destIndex);
} else if (length == 5) {
dest[destIndex] = src[srcIndex];
DrillBuf.putInt(src, srcIndex+1, dest, destIndex+1);
} else if (length == 6) {
DrillBuf.putShort(src, srcIndex, dest, destIndex);
DrillBuf.putInt(src, srcIndex+2, dest, destIndex+2);
} else if (length == 7) {
dest[destIndex] = src[srcIndex];
DrillBuf.putShort(src, srcIndex+1, dest, destIndex+1);
DrillBuf.putInt(src, srcIndex+3, dest, destIndex+3);
} else {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
}
}
private static final void vlCopyGTLongNoPadding(byte[] src, int srcIndex, byte[] dest, int destIndex, int length) {
final int numLongEntries = length >> 3;
final int remaining = length & 0x7;
if (numLongEntries == 1) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
} else if (numLongEntries == 2) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
DrillBuf.putLong(src, srcIndex + DrillBuf.LONG_NUM_BYTES, dest, destIndex + DrillBuf.LONG_NUM_BYTES);
} else if (numLongEntries == 3) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
DrillBuf.putLong(src, srcIndex + DrillBuf.LONG_NUM_BYTES, dest, destIndex + DrillBuf.LONG_NUM_BYTES);
DrillBuf.putLong(src, srcIndex + 2 * DrillBuf.LONG_NUM_BYTES, dest, destIndex + 2 * DrillBuf.LONG_NUM_BYTES);
} else if (numLongEntries == 4) {
DrillBuf.putLong(src, srcIndex, dest, destIndex);
DrillBuf.putLong(src, srcIndex + DrillBuf.LONG_NUM_BYTES, dest, destIndex + DrillBuf.LONG_NUM_BYTES);
DrillBuf.putLong(src, srcIndex + 2 * DrillBuf.LONG_NUM_BYTES, dest, destIndex + 2 * DrillBuf.LONG_NUM_BYTES);
DrillBuf.putLong(src, srcIndex + 3 * DrillBuf.LONG_NUM_BYTES, dest, destIndex + 3 * DrillBuf.LONG_NUM_BYTES);
} else {
for (int idx = 0; idx < numLongEntries; ++idx) {
DrillBuf.putLong(src, srcIndex + idx * DrillBuf.LONG_NUM_BYTES, dest, destIndex + idx * DrillBuf.LONG_NUM_BYTES);
}
}
if (remaining > 0) {
final int srcPos = srcIndex + numLongEntries * DrillBuf.LONG_NUM_BYTES;
final int destPos = destIndex + numLongEntries * DrillBuf.LONG_NUM_BYTES;
if (srcPos + 7 < src.length) {
DrillBuf.putLong(src, srcPos, dest, destPos);
} else {
vlCopyLELongNoPadding(src, srcPos, dest, destPos, remaining);
}
}
}
}