blob: b924b384f6368656705c41cb97c38322fc9423ae [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.carbondata.core.datastore.chunk.impl;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.BitSet;
import java.util.List;
import org.apache.carbondata.core.constants.CarbonCommonConstants;
import org.apache.carbondata.core.datastore.FileReader;
import org.apache.carbondata.core.datastore.ReusableDataBuffer;
import org.apache.carbondata.core.datastore.chunk.AbstractRawColumnChunk;
import org.apache.carbondata.core.datastore.chunk.DimensionColumnPage;
import org.apache.carbondata.core.datastore.chunk.reader.DimensionColumnChunkReader;
import org.apache.carbondata.core.datastore.compression.Compressor;
import org.apache.carbondata.core.datastore.compression.CompressorFactory;
import org.apache.carbondata.core.datastore.page.ColumnPage;
import org.apache.carbondata.core.datastore.page.encoding.ColumnPageDecoder;
import org.apache.carbondata.core.datastore.page.encoding.DefaultEncodingFactory;
import org.apache.carbondata.core.scan.result.vector.CarbonDictionary;
import org.apache.carbondata.core.scan.result.vector.ColumnVectorInfo;
import org.apache.carbondata.core.scan.result.vector.impl.CarbonDictionaryImpl;
import org.apache.carbondata.core.util.CarbonMetadataUtil;
import org.apache.carbondata.format.Encoding;
import org.apache.carbondata.format.LocalDictionaryChunk;
/**
* Contains raw dimension data,
* 1. The read uncompressed raw data of column chunk with all pages is stored in this instance.
* 2. The raw data can be converted to processed chunk using decodeColumnPage method
* by specifying page number.
*/
public class DimensionRawColumnChunk extends AbstractRawColumnChunk {
private DimensionColumnPage[] dataChunks;
private DimensionColumnChunkReader chunkReader;
private FileReader fileReader;
private CarbonDictionary localDictionary;
public DimensionRawColumnChunk(int columnIndex, ByteBuffer rawData, long offSet, int length,
DimensionColumnChunkReader columnChunkReader) {
super(columnIndex, rawData, offSet, length);
this.chunkReader = columnChunkReader;
}
/**
* Convert all raw data with all pages to processed DimensionColumnPage's
* @return
*/
public DimensionColumnPage[] decodeAllColumnPages() {
if (dataChunks == null) {
dataChunks = new DimensionColumnPage[pagesCount];
}
for (int i = 0; i < pagesCount; i++) {
try {
if (dataChunks[i] == null) {
dataChunks[i] = chunkReader.decodeColumnPage(this, i, null);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return dataChunks;
}
/**
* Convert raw data with specified page number processed to DimensionColumnPage
* @param pageNumber
* @return
*/
public DimensionColumnPage decodeColumnPage(int pageNumber) {
assert pageNumber < pagesCount;
if (dataChunks == null) {
dataChunks = new DimensionColumnPage[pagesCount];
}
if (dataChunks[pageNumber] == null) {
try {
dataChunks[pageNumber] = chunkReader.decodeColumnPage(this, pageNumber, null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return dataChunks[pageNumber];
}
/**
* Convert raw data with specified page number processed to DimensionColumnDataChunk
*
* @param index
* @return
*/
public DimensionColumnPage convertToDimColDataChunkWithOutCache(int index,
ReusableDataBuffer reusableDataBuffer) {
assert index < pagesCount;
// in case of filter query filter column if filter column is decoded and stored.
// then return the same
if (dataChunks != null && null != dataChunks[index]) {
return dataChunks[index];
}
try {
return chunkReader.decodeColumnPage(this, index, reusableDataBuffer);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Convert raw data with specified page number processed to DimensionColumnDataChunk and fill
* the vector
*
* @param pageNumber page number to decode and fill the vector
* @param vectorInfo vector to be filled with column page
*/
public void convertToDimColDataChunkAndFillVector(int pageNumber, ColumnVectorInfo vectorInfo,
ReusableDataBuffer reusableDataBuffer) {
assert pageNumber < pagesCount;
try {
chunkReader.decodeColumnPageAndFillVector(this, pageNumber, vectorInfo, reusableDataBuffer);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void freeMemory() {
super.freeMemory();
if (null != dataChunks) {
for (int i = 0; i < dataChunks.length; i++) {
if (dataChunks[i] != null) {
dataChunks[i].freeMemory();
dataChunks[i] = null;
}
}
}
rawData = null;
}
public void setFileReader(FileReader fileReader) {
this.fileReader = fileReader;
}
public FileReader getFileReader() {
return fileReader;
}
public CarbonDictionary getLocalDictionary() {
if (null != getDataChunkV3() && null != getDataChunkV3().local_dictionary
&& null == localDictionary) {
try {
String compressorName = CarbonMetadataUtil.getCompressorNameFromChunkMeta(
getDataChunkV3().data_chunk_list.get(0).chunk_meta);
Compressor compressor = CompressorFactory.getInstance().getCompressor(compressorName);
localDictionary = getDictionary(getDataChunkV3().local_dictionary, compressor);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return localDictionary;
}
/**
* Below method will be used to get the local dictionary for a blocklet
* @param localDictionaryChunk
* local dictionary chunk thrift object
* @return local dictionary
* @throws IOException
*/
public static CarbonDictionary getDictionary(LocalDictionaryChunk localDictionaryChunk,
Compressor compressor) throws IOException {
if (null != localDictionaryChunk) {
List<Encoding> encodings = localDictionaryChunk.getDictionary_meta().getEncoders();
List<ByteBuffer> encoderMetas = localDictionaryChunk.getDictionary_meta().getEncoder_meta();
ColumnPageDecoder decoder = DefaultEncodingFactory.getInstance().createDecoder(
encodings, encoderMetas, compressor.getName());
ColumnPage decode = decoder.decode(localDictionaryChunk.getDictionary_data(), 0,
localDictionaryChunk.getDictionary_data().length);
BitSet usedDictionary = BitSet.valueOf(compressor.unCompressByte(
localDictionaryChunk.getDictionary_values()));
int length = usedDictionary.length();
int index = 0;
byte[][] dictionary = new byte[length][];
for (int i = 0; i < length; i++) {
if (usedDictionary.get(i)) {
dictionary[i] = decode.getBytes(index++);
} else {
dictionary[i] = null;
}
}
decode.freeMemory();
if (!usedDictionary.isEmpty()) {
// as dictionary values starts from 1 setting null default value
dictionary[1] = CarbonCommonConstants.MEMBER_DEFAULT_VAL_ARRAY;
}
return new CarbonDictionaryImpl(dictionary, usedDictionary.cardinality());
}
return null;
}
}