/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.loader.columnshard;
import java.util.Map;
import java.util.NavigableMap;
import java.util.function.Function;
import org.diqube.data.column.ColumnPage;
import org.diqube.data.column.ColumnPageFactory;
import org.diqube.data.types.lng.array.CompressedLongArray;
import org.diqube.data.types.lng.dict.LongDictionary;
import org.diqube.loader.compression.CompressedLongArrayBuilder;
import org.diqube.loader.compression.CompressedLongArrayBuilder.BitEfficientCompressionStrategy;
import org.diqube.loader.compression.CompressedLongArrayBuilder.RunLengthAndBitEfficientCompressionStrategy;
import org.diqube.loader.compression.CompressedLongDictionaryBuilder;
import org.diqube.util.Pair;
/**
* Builds a {@link ColumnPage} and takes care of compressing the dictionary and the value array.
*
* @author Bastian Gloeckle
*/
public class ColumnPageBuilder {
private long firstRowId;
private NavigableMap<Long, Long> valueMap;
private long[] values;
private ColumnPageFactory columnPageFactory;
private String name;
private Function<LongDictionary<?>, LongDictionary<?>> colPageDictFn;
public ColumnPageBuilder(ColumnPageFactory columnPageFactory) {
this.columnPageFactory = columnPageFactory;
}
public ColumnPageBuilder withColumnPageName(String name) {
this.name = name;
return this;
}
/**
* @param firstRowId
* The row ID of the first of the {@link #withValues(long[])}.
*/
public ColumnPageBuilder withFirstRowId(long firstRowId) {
this.firstRowId = firstRowId;
return this;
}
/**
* @param valueMap
* From value long to id long. ID longs are the same that are used in {@link #withValues(long[])}.
*/
public ColumnPageBuilder withValueMap(NavigableMap<Long, Long> valueMap) {
this.valueMap = valueMap;
return this;
}
/**
* @param values
* Value IDs for each row of the future column page. The Value IDs are the values of the map specified in
* {@link #withValueMap(NavigableMap)}. This array will be written to by this builder.
*/
public ColumnPageBuilder withValues(long[] values) {
this.values = values;
return this;
}
/**
* @param fn
* Optional function that receives the internally built colPageDict and can return another dict.
*/
public ColumnPageBuilder withColumnPageDictFunction(Function<LongDictionary<?>, LongDictionary<?>> colPageDictFn) {
this.colPageDictFn = colPageDictFn;
return this;
}
/**
* Build a new {@link ColumnPage} and take care of compression.
*
* @return The new {@link ColumnPage}
*/
public ColumnPage build() {
// Build a LongDictionary from the values we want to store in the page. This might re-assign IDs.
CompressedLongDictionaryBuilder columnPageDictBuilder = new CompressedLongDictionaryBuilder();
columnPageDictBuilder.withDictionaryName(name).fromEntityMap(this.valueMap);
Pair<LongDictionary<?>, Map<Long, Long>> builderRes = columnPageDictBuilder.build();
LongDictionary<?> columnPageDict = builderRes.getLeft();
Map<Long, Long> columnPageIdAdjust = builderRes.getRight();
// If the builder of the columnPage dict decided to adjust the IDs, we need to integrate those changes into
// pageValue array.
if (columnPageIdAdjust != null) {
for (int i = 0; i < values.length; i++) {
if (columnPageIdAdjust.containsKey(values[i]))
values[i] = columnPageIdAdjust.get(values[i]);
}
}
@SuppressWarnings("unchecked")
CompressedLongArrayBuilder compressedBuilder = new CompressedLongArrayBuilder().withLogName(name).withValues(values)
.withStrategies(BitEfficientCompressionStrategy.class, RunLengthAndBitEfficientCompressionStrategy.class);
CompressedLongArray<?> compressedValues = compressedBuilder.build();
if (colPageDictFn != null)
columnPageDict = colPageDictFn.apply(columnPageDict);
// build final ColumnPage
ColumnPage page = columnPageFactory.createDefaultColumnPage(columnPageDict, compressedValues, firstRowId, name);
return page;
}
}