/** * 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.data.column; import java.util.ArrayList; import java.util.List; import java.util.NavigableMap; import java.util.TreeMap; import org.diqube.data.dictionary.Dictionary; import org.diqube.data.dictionary.SerializableDictionary; import org.diqube.data.serialize.DeserializationException; import org.diqube.data.serialize.SerializationException; import org.diqube.data.serialize.thrift.v1.SColumnPage; import org.diqube.data.serialize.thrift.v1.SColumnShard; import org.diqube.data.serialize.thrift.v1.SColumnType; import org.diqube.data.serialize.thrift.v1.SDictionary; import org.diqube.data.util.StandardColumnShardUtil; /** * Abstract implementation of a {@link StandardColumnShard}. * * @author Bastian Gloeckle */ public abstract class AbstractStandardColumnShard implements StandardColumnShard, AdjustableStandardColumnShard { protected SerializableDictionary<?, ?> columnShardDictionary; protected String name; protected ColumnType columnType; /** * Map from firstId to {@link ColumnPage} */ protected NavigableMap<Long, ColumnPage> pages; /** for deserialization */ protected AbstractStandardColumnShard() { } /** * Create a new column shard. * * @param columnType * Type of the column * @param name * Name of the column * @param pages * ColumnPages, mapping from first RowID to the page itself. This map object can be empty when creating this * ColumnShard and be filled later on. * @param columnShardDictionary * The Column dictionary, see class comment. */ protected AbstractStandardColumnShard(ColumnType columnType, String name, NavigableMap<Long, ColumnPage> pages, SerializableDictionary<?, ?> columnShardDictionary) { this.columnType = columnType; this.name = name; this.pages = pages; this.columnShardDictionary = columnShardDictionary; } @Override public String getName() { return name; } @Override public NavigableMap<Long, ColumnPage> getPages() { return pages; } @Override public Dictionary<?> getColumnShardDictionary() { return columnShardDictionary; } @Override public ColumnType getColumnType() { return columnType; } @Override public long getNumberOfRowsInColumnShard() { if (pages.size() == 0) return 0; return pages.values().stream().mapToLong(page -> page.size()).sum(); } @Override public long getFirstRowId() { return pages.firstKey(); } @Override public void adjustToFirstRowId(long firstRowId) throws UnsupportedOperationException { long delta = firstRowId - pages.firstKey(); pages = new StandardColumnShardUtil().adjustFirstRowIdOnPages(pages, delta, name); } @Override public void serialize(DataSerializationHelper mgr, SColumnShard target) throws SerializationException { target.setName(name); switch (columnType) { case STRING: target.setType(SColumnType.STRING); break; case LONG: target.setType(SColumnType.LONG); break; case DOUBLE: target.setType(SColumnType.DOUBLE); break; } target.setDictionary(mgr.serializeChild(SDictionary.class, columnShardDictionary)); List<SColumnPage> serializedPages = new ArrayList<>(); for (ColumnPage page : pages.values()) serializedPages.add(mgr.serializeChild(SColumnPage.class, page)); target.setPages(serializedPages); } @SuppressWarnings("unchecked") @Override public void deserialize(DataSerializationHelper mgr, SColumnShard source) throws DeserializationException { name = source.getName(); switch (source.getType()) { case STRING: columnType = ColumnType.STRING; break; case LONG: columnType = ColumnType.LONG; break; case DOUBLE: columnType = ColumnType.DOUBLE; break; default: throw new DeserializationException("Unknown type"); } columnShardDictionary = mgr.deserializeChild(SerializableDictionary.class, source.getDictionary()); pages = new TreeMap<>(); for (SColumnPage serializedPage : source.getPages()) { ColumnPage page = mgr.deserializeChild(DefaultColumnPage.class, serializedPage); pages.put(page.getFirstRowId(), page); } } @Override public long calculateApproximateSizeInBytes() { long pagesSize = 0L; // "Long" keys: 8 bytes long value, 16 bytes object header pagesSize += pages.size() * (8 + 16); // ColumnPages: for (ColumnPage page : pages.values()) { pagesSize += page.calculateApproximateSizeInBytes(); } return 16 + // object header of this. name.getBytes().length + // columnShardDictionary.calculateApproximateSizeInBytes() + pagesSize; } }