0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 package org.apache.spark.sql.catalyst.expressions.codegen;
0019
0020 import org.apache.spark.sql.catalyst.expressions.UnsafeRow;
0021 import org.apache.spark.unsafe.Platform;
0022 import org.apache.spark.unsafe.array.ByteArrayMethods;
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 final class BufferHolder {
0035
0036 private static final int ARRAY_MAX = ByteArrayMethods.MAX_ROUNDED_ARRAY_LENGTH;
0037
0038
0039 private byte[] buffer;
0040 private int cursor = Platform.BYTE_ARRAY_OFFSET;
0041 private final UnsafeRow row;
0042 private final int fixedSize;
0043
0044 BufferHolder(UnsafeRow row) {
0045 this(row, 64);
0046 }
0047
0048 BufferHolder(UnsafeRow row, int initialSize) {
0049 int bitsetWidthInBytes = UnsafeRow.calculateBitSetWidthInBytes(row.numFields());
0050 if (row.numFields() > (ARRAY_MAX - initialSize - bitsetWidthInBytes) / 8) {
0051 throw new UnsupportedOperationException(
0052 "Cannot create BufferHolder for input UnsafeRow because there are " +
0053 "too many fields (number of fields: " + row.numFields() + ")");
0054 }
0055 this.fixedSize = bitsetWidthInBytes + 8 * row.numFields();
0056 int roundedSize = ByteArrayMethods.roundNumberOfBytesToNearestWord(fixedSize + initialSize);
0057 this.buffer = new byte[roundedSize];
0058 this.row = row;
0059 this.row.pointTo(buffer, buffer.length);
0060 }
0061
0062
0063
0064
0065 void grow(int neededSize) {
0066 if (neededSize < 0) {
0067 throw new IllegalArgumentException(
0068 "Cannot grow BufferHolder by size " + neededSize + " because the size is negative");
0069 }
0070 if (neededSize > ARRAY_MAX - totalSize()) {
0071 throw new IllegalArgumentException(
0072 "Cannot grow BufferHolder by size " + neededSize + " because the size after growing " +
0073 "exceeds size limitation " + ARRAY_MAX);
0074 }
0075 final int length = totalSize() + neededSize;
0076 if (buffer.length < length) {
0077
0078 int newLength = length < ARRAY_MAX / 2 ? length * 2 : ARRAY_MAX;
0079 int roundedSize = ByteArrayMethods.roundNumberOfBytesToNearestWord(newLength);
0080 final byte[] tmp = new byte[roundedSize];
0081 Platform.copyMemory(
0082 buffer,
0083 Platform.BYTE_ARRAY_OFFSET,
0084 tmp,
0085 Platform.BYTE_ARRAY_OFFSET,
0086 totalSize());
0087 buffer = tmp;
0088 row.pointTo(buffer, buffer.length);
0089 }
0090 }
0091
0092 byte[] getBuffer() {
0093 return buffer;
0094 }
0095
0096 int getCursor() {
0097 return cursor;
0098 }
0099
0100 void increaseCursor(int val) {
0101 cursor += val;
0102 }
0103
0104 void reset() {
0105 cursor = Platform.BYTE_ARRAY_OFFSET + fixedSize;
0106 }
0107
0108 int totalSize() {
0109 return cursor - Platform.BYTE_ARRAY_OFFSET;
0110 }
0111 }