blob: b9c9e74cefd545f22dfca892108e4b9bc2141e6c [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.cache.dictionary;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.carbondata.core.constants.CarbonCommonConstants;
import org.apache.carbondata.core.util.CarbonUtil;
/**
* class that implements cacheable interface and methods specific to column dictionary
*/
public abstract class AbstractColumnDictionaryInfo implements DictionaryInfo {
/**
* list that will hold all the dictionary chunks for one column
*/
protected List<List<byte[]>> dictionaryChunks = new CopyOnWriteArrayList<>();
/**
* minimum value of surrogate key, dictionary value key will start from count 1
*/
protected static final int MINIMUM_SURROGATE_KEY = 1;
/**
* atomic integer to maintain the access count for a column access
*/
protected AtomicInteger accessCount = new AtomicInteger();
/**
* file timestamp
*/
protected long fileTimeStamp;
/**
* memory size of this object.We store it as calculation everytime is costly
*/
protected long memorySize;
/**
* size of one dictionary bucket
*/
private final int dictionaryOneChunkSize = CarbonUtil.getDictionaryChunkSize();
/**
* This method will return the timestamp of file based on which decision
* the decision will be taken whether to read that file or not
*
* @return
*/
@Override
public long getFileTimeStamp() {
return fileTimeStamp;
}
/**
* This method will return the access count for a column based on which decision will be taken
* whether to keep the object in memory
*
* @return
*/
@Override
public int getAccessCount() {
return accessCount.get();
}
/**
* This method will return the memory size of a column
*
* @return
*/
@Override
public long getMemorySize() {
return memorySize;
}
/**
* This method will decrement the access count for a column by 1
* whenever a column usage is complete
*/
private void decrementAccessCount() {
if (accessCount.get() > 0) {
accessCount.decrementAndGet();
}
}
/**
* The method return the list of dictionary chunks of a column
* Applications Scenario.
* For preparing the column Sort info while writing the sort index file.
*
* @return
*/
@Override
public DictionaryChunksWrapper getDictionaryChunks() {
return new DictionaryChunksWrapper(dictionaryChunks);
}
/**
* This method will release the objects and set default value for primitive types
*/
@Override
public void clear() {
decrementAccessCount();
}
/**
* This method will find and return the dictionary value for a given surrogate key.
* Applicable scenarios:
* 1. Query final result preparation : While convert the final result which will
* be surrogate key back to original dictionary values this method will be used
*
* @param surrogateKey a unique ID for a dictionary value
* @return value if found else null
*/
@Override
public String getDictionaryValueForKey(int surrogateKey) {
String dictionaryValue = null;
if (surrogateKey < MINIMUM_SURROGATE_KEY) {
return dictionaryValue;
}
byte[] dictionaryValueInBytes = getDictionaryBytesFromSurrogate(surrogateKey);
if (null != dictionaryValueInBytes) {
dictionaryValue = new String(dictionaryValueInBytes,
CarbonCommonConstants.DEFAULT_CHARSET_CLASS);
}
return dictionaryValue;
}
/**
* This method will find and return the dictionary value for a given surrogate key.
* Applicable scenarios:
* 1. Query final result preparation : While convert the final result which will
* be surrogate key back to original dictionary values this method will be used
*
* @param surrogateKey a unique ID for a dictionary value
* @return value if found else null
*/
@Override
public byte[] getDictionaryValueForKeyInBytes(int surrogateKey) {
if (surrogateKey < MINIMUM_SURROGATE_KEY) {
return null;
}
return getDictionaryBytesFromSurrogate(surrogateKey);
}
/**
* This method will find and return the dictionary value as byte array for a
* given surrogate key
*
* @param surrogateKey
* @return
*/
protected byte[] getDictionaryBytesFromSurrogate(int surrogateKey) {
byte[] dictionaryValueInBytes = null;
// surrogate key starts from 1 and list index will start from 0, so lets say if surrogate
// key is 10 then value will present at index 9 of the dictionary chunk list
int actualSurrogateIndex = surrogateKey - 1;
// lets say dictionaryOneChunkSize = 10, surrogateKey = 10, so bucket index will
// be 0 and dictionary chunk index will be 9 to get the value
int dictionaryBucketIndex = actualSurrogateIndex / dictionaryOneChunkSize;
if (dictionaryChunks.size() > dictionaryBucketIndex) {
int indexInsideBucket = actualSurrogateIndex % dictionaryOneChunkSize;
List<byte[]> dictionaryBucketContainingSurrogateValue =
dictionaryChunks.get(dictionaryBucketIndex);
if (dictionaryBucketContainingSurrogateValue.size() > indexInsideBucket) {
dictionaryValueInBytes = dictionaryBucketContainingSurrogateValue.get(indexInsideBucket);
}
}
return dictionaryValueInBytes;
}
@Override
public void invalidate() {
}
}