Commit 62d776be authored by Philipp Götze's avatar Philipp Götze
Browse files

Switched to PMDK (former NVML) +++ Added some switch-case alternatives +++...

Switched to PMDK (former NVML) +++ Added some switch-case alternatives +++ moved KeyType before TupleType for consistency +++ Some fixes
parent 20d943c3
......@@ -5,17 +5,18 @@ A persistent analytical table structure for non-volatile memory.
Please see the file [COPYING](COPYING) for license information.
### TODOs:
- [ ] Tests
- [x] Tests
- [ ] Get rid of expensive transactions
- [x] Improve benchmarks
- [ ] Describe usage
- [ ] The BlockIterator currently suffers from bugs (SEGSIGV with too big structures)
### Installation ###
We use the C++17 standard, thus, you need a very recent C++ compiler and CMake (3.2 or newer) build environment.
We use the C++14 standard, thus, you need a recent C++ compiler and CMake (3.2 or newer) build environment.
In addition some third party libraries such as [Catch](https://github.com/philsquared/Catch) for testing, [Google Benchmark](https://github.com/google/benchmark.git) for benchmarking, [Format](https://github.com/fmtlib/fmt.git), and [NVML](https://github.com/pmem/nvml.git) are used
These, however, are either included or downloaded during the build process.
In addition some third party libraries such as [Catch](https://github.com/philsquared/Catch) for testing, [Google Benchmark](https://github.com/google/benchmark.git) for benchmarking, [Format](https://github.com/fmtlib/fmt.git), and [PMDK](https://github.com/pmem/pmdk.git) are used.
These, however, are both downloaded and included during the build process.
After cloning and switching into the project directory, you can build the repository with with:
```
......@@ -29,4 +30,7 @@ make test
### Usage ###
The test cases and benchmarks use the directory _/mnt/pmem/test_ for storing data. Thus, make sure the pmem device is mounted at _/mnt/pmem_ and the subfolder _test_ has write permissions for everybody. Alternatively, you can change the directory in [common.h](src/bench/common.h).
The test cases and benchmarks use the directory _/mnt/pmem/test_ for storing data. Thus, make sure the pmem device is mounted at _/mnt/pmem_ and the subfolder _test_ has write permissions for everybody.
Alternatively, you can change the directory in the customization section in [CMakeLists.txt](src/CMakeLists.txt).
A detailed usage description will follow soon.
Till then the general usage can be found out by looking at test cases and benchmarks.
......@@ -44,7 +44,7 @@ if (BUILD_GOOGLE_BENCH)
# Google Benchmark framework
download_project(PROJ benchmark
GIT_REPOSITORY https://github.com/google/benchmark.git
GIT_TAG master
GIT_TAG releasing
UPDATE_DISCONNECTED 1
QUIET
)
......@@ -64,17 +64,17 @@ add_custom_command(
endif()
#--------------------------------------------------------------------------------
# Non-Volatile Memory Library (pmem.io)
download_project(PROJ nvml
GIT_REPOSITORY https://github.com/pmem/nvml.git
GIT_TAG 1.3.1-rc2
# Peristent Memory Development Kit (pmem.io)
download_project(PROJ pmdk
GIT_REPOSITORY https://github.com/pmem/pmdk.git
GIT_TAG master
UPDATE_DISCONNECTED 1
QUIET
)
add_custom_command(
OUTPUT ${THIRD_PARTY_DIR}/nvml
COMMAND ${CMAKE_COMMAND} -E chdir ${nvml_SOURCE_DIR} $(MAKE)
COMMAND ${CMAKE_COMMAND} -E chdir ${nvml_SOURCE_DIR} $(MAKE) install prefix=${THIRD_PARTY_DIR}/nvml
OUTPUT ${THIRD_PARTY_DIR}/pmdk
COMMAND ${CMAKE_COMMAND} -E chdir ${pmdk_SOURCE_DIR} $(MAKE)
COMMAND ${CMAKE_COMMAND} -E chdir ${pmdk_SOURCE_DIR} $(MAKE) install prefix=${THIRD_PARTY_DIR}/pmdk
)
#--------------------------------------------------------------------------------
......
......@@ -8,7 +8,7 @@ macro( build_test arg )
add_executable( ${arg} "${arg}.cpp" $<TARGET_OBJECTS:MainTest>)
target_link_libraries( ${arg}
ptable
${NVML_LIBRARIES}
${PMDK_LIBRARIES}
${BENCHMARK_LIB}
)
endmacro( build_test )
......@@ -17,7 +17,7 @@ macro( build_bench arg )
add_executable( ${arg} "${arg}.cpp")
target_link_libraries( ${arg}
ptable
${NVML_LIBRARIES}
${PMDK_LIBRARIES}
${BENCHMARK_LIB}
)
endmacro( build_bench )
......
......@@ -21,7 +21,7 @@ set(PMEM_MNT_PATH "/mnt/pmem/test")
option(ENABLE_LOG "enables log output for e.g. debugging" OFF)
option(BUILD_TEST_CASES "build tests for PTable functionality" ON )
option(BUILD_GOOGLE_BENCH "build google benchmark" OFF)
option(BUILD_BENCHMARKS "build benchmarks for Ptable" OFF)
option(BUILD_BENCHMARKS "build benchmarks for Ptable" ON )
################################################################################
# End of customization section #
......@@ -77,18 +77,18 @@ else()
endif()
########################
# Non-Volatile Memory Library
# Persistent Memory Development Kit
########################
#
set (NVML_LIBRARIES
"${THIRD_PARTY_DIR}/nvml/lib/libpmemblk.a"
"${THIRD_PARTY_DIR}/nvml/lib/libpmemlog.a"
"${THIRD_PARTY_DIR}/nvml/lib/libpmemobj.a"
"${THIRD_PARTY_DIR}/nvml/lib/libpmempool.a"
"${THIRD_PARTY_DIR}/nvml/lib/libpmem.a"
set (PMDK_LIBRARIES
"${THIRD_PARTY_DIR}/pmdk/lib/libpmemblk.a"
"${THIRD_PARTY_DIR}/pmdk/lib/libpmemlog.a"
"${THIRD_PARTY_DIR}/pmdk/lib/libpmemobj.a"
"${THIRD_PARTY_DIR}/pmdk/lib/libpmempool.a"
"${THIRD_PARTY_DIR}/pmdk/lib/libpmem.a"
${DYLIB_LIBRARY}
)
include_directories("${THIRD_PARTY_DIR}/nvml/include")
include_directories("${THIRD_PARTY_DIR}/pmdk/include")
include_directories("${THIRD_PARTY_DIR}/variant/include")
#-----------------------------------------------------------------------------------------
#
......@@ -107,7 +107,7 @@ set(core_sources
core/PTableInfo.cpp
${THIRD_PARTY_DIR}/fmt
${THIRD_PARTY_DIR}/catch
${THIRD_PARTY_DIR}/nvml
${THIRD_PARTY_DIR}/pmdk
${THIRD_PARTY_DIR}/variant
)
......
......@@ -35,11 +35,11 @@
namespace ptable {
using nvml::obj::delete_persistent;
using nvml::obj::make_persistent;
using nvml::obj::p;
using nvml::obj::persistent_ptr;
using nvml::obj::transaction;
using pmem::obj::delete_persistent;
using pmem::obj::make_persistent;
using pmem::obj::p;
using pmem::obj::persistent_ptr;
using pmem::obj::transaction;
/**
* A persistent memory implementation of a B+ tree.
......@@ -195,7 +195,7 @@ class PBPTree {
* @param val the value that is associated with the key
*/
void insert(const KeyType &key, const ValueType &val) {
auto pop = nvml::obj::pool_by_vptr(this);
auto pop = pmem::obj::pool_by_vptr(this);
transaction::exec_tx(pop, [&] {
SplitInfo splitInfo;
......@@ -321,6 +321,7 @@ class PBPTree {
// for each key-value pair within the range call func
for (auto i = 0u; i < leaf->numKeys; i++) {
auto &key = leaf->keys.get_ro()[i];
if (key < minKey) continue;
if (key > maxKey) return;
auto &val = leaf->values.get_ro()[i];
......@@ -1028,7 +1029,7 @@ class PBPTree {
* Create a new empty leaf node
*/
persistent_ptr<LeafNode> newLeafNode() {
auto pop = nvml::obj::pool_by_vptr(this);
auto pop = pmem::obj::pool_by_vptr(this);
persistent_ptr<LeafNode> newNode = nullptr;
transaction::exec_tx(pop, [&] {
newNode = make_persistent<LeafNode>();
......@@ -1037,7 +1038,7 @@ class PBPTree {
}
void deleteLeafNode(persistent_ptr<LeafNode> node) {
auto pop = nvml::obj::pool_by_vptr(this);
auto pop = pmem::obj::pool_by_vptr(this);
transaction::exec_tx(pop, [&] {
delete_persistent<LeafNode>(node);
});
......@@ -1047,7 +1048,7 @@ class PBPTree {
* Create a new empty branch node
*/
persistent_ptr<BranchNode> newBranchNode() {
auto pop = nvml::obj::pool_by_vptr(this);
auto pop = pmem::obj::pool_by_vptr(this);
persistent_ptr<BranchNode> newNode = nullptr;
transaction::exec_tx(pop, [&] {
newNode = make_persistent<BranchNode>();
......@@ -1056,7 +1057,7 @@ class PBPTree {
}
void deleteBranchNode(persistent_ptr<BranchNode> node) {
auto pop = nvml::obj::pool_by_vptr(this);
auto pop = pmem::obj::pool_by_vptr(this);
transaction::exec_tx(pop, [&] {
delete_persistent<BranchNode>(node);
});
......
......@@ -30,13 +30,14 @@
#include "core/PTuple.hpp"
#include "core/serialize.hpp"
#include "core/utils.hpp"
#include "core/VTableInfo.hpp"
#include "PBPTree.hpp"
namespace ptable {
const std::string LAYOUT = "PTable";
auto const TARGET_INDEX_NODE_SIZE = 4 * 1024; // 4KB
auto const TARGET_INDEX_NODE_SIZE = 1024; // 1KB
/** Abort reason codes: */
const auto NOT_ENOUGH_SPACE = 1;
......@@ -52,14 +53,20 @@ using ColumnRangeMap = std::unordered_map<uint16_t, std::pair<IntDoubleString, I
*
* \author Philipp Goetze <philipp.goetze@tu-ilmenau.de>
*****************************************************************************/
template<class Tuple, typename KeyType>
class PTable {
template<typename KeyType, class TupleType>
class PTable;
template<typename KeyType, class... Types>
class PTable<KeyType, std::tuple<Types...>> {
using Tuple = std::tuple<Types...>;
static const auto BRANCHKEYS = ((TARGET_INDEX_NODE_SIZE - 28) / (sizeof(KeyType) + 24)) & ~1;
static const auto LEAFKEYS = ((TARGET_INDEX_NODE_SIZE - 36) /
(sizeof(KeyType) + sizeof(PTuple<Tuple, KeyType>))) & ~1;
(sizeof(KeyType) + sizeof(PTuple<KeyType, Tuple>))) & ~1;
using VTableInfoType = VTableInfo<KeyType, Tuple>;
using PTableInfoType = PTableInfo<KeyType, Tuple>;
using ColumnIntMap = std::map<uint16_t, uint16_t>;
using IndexType = PBPTree<KeyType, PTuple<Tuple, KeyType>, BRANCHKEYS, LEAFKEYS>;
using IndexType = PBPTree<KeyType, PTuple<KeyType, Tuple>, BRANCHKEYS, LEAFKEYS>;
using DataNodePtr = persistent_ptr<DataNode<KeyType>>;
/************************************************************************//**
......@@ -67,7 +74,7 @@ class PTable {
***************************************************************************/
class BlockIterator {
using DataNodeVector = std::vector<persistent_ptr<DataNode<KeyType>>>;
const PTable<Tuple, KeyType> parent;
const PTable<KeyType, Tuple> parent;
const ColumnRangeMap predicates;
const DataNodeVector candidates;
typename DataNodeVector::const_iterator currentNode;
......@@ -75,7 +82,7 @@ class PTable {
uint16_t currentPos = 0u;
public:
BlockIterator(const PTable<Tuple, KeyType> &_parent, const ColumnRangeMap &_predicates) :
BlockIterator(const PTable<KeyType, Tuple> &_parent, const ColumnRangeMap &_predicates) :
parent(_parent),
predicates(_predicates),
candidates(parent.getCandidateBlocks(predicates)),
......@@ -86,7 +93,7 @@ class PTable {
else currentPos = 1; // --> setting to end()
}
BlockIterator(const PTable<Tuple, KeyType> &_parent,
BlockIterator(const PTable<KeyType, Tuple> &_parent,
const ColumnRangeMap &_predicates,
const DataNodeVector &_candidates) :
parent(_parent),
......@@ -99,7 +106,7 @@ class PTable {
else currentPos = 1; // --> setting to end()
}
BlockIterator(const PTable<Tuple, KeyType> &_parent) :
BlockIterator(const PTable<KeyType, Tuple> &_parent) :
parent(_parent), currentNode(nullptr), currentPos(1) {}
BlockIterator &operator++() {
......@@ -148,8 +155,21 @@ class PTable {
}
bool operator!=(BlockIterator other) const { return !(*this == other); }
PTuple<Tuple, KeyType> operator*() {
std::array<uint16_t, PTuple<Tuple, KeyType>::NUM_ATTRIBUTES> pTupleOffsets;
PTuple<KeyType, Tuple> operator*() {
std::array<uint16_t, PTuple<KeyType, Tuple>::NUM_ATTRIBUTES> pTupleOffsets;
/*
auto setPTupleOffsets = [&](auto element, std::size_t idx) {
pTupleOffsets[idx] = ColumnAttributes<toColumnType<decltype(element)>()>::dataOffsetPos(
currentNode->get()->block.get_ro(),
gDataOffsetPos + idx * gAttrOffsetSize,
currentPos
);
};
forEachTypeInTuple<decltype(setPTupleOffsets), Types...>(setPTupleOffsets);
return PTuple<KeyType, Tuple>(*currentNode, pTupleOffsets);
*/
auto idx = 0u;
for (const auto &c : *parent.root->tInfo) {
const auto
......@@ -157,15 +177,15 @@ class PTable {
reinterpret_cast<const uint16_t &>((*currentNode)->block.get_ro()[gDataOffsetPos + idx * gAttrOffsetSize]);
uint16_t dataOffset;
switch (c.getType()) {
case Int_Type: {
case ColumnType::IntType: {
dataOffset = dataPos + (currentPos - 1) * sizeof(int);
}
break;
case Double_Type: {
case ColumnType::DoubleType: {
dataOffset = dataPos + (currentPos - 1) * sizeof(double);
}
break;
case String_Type: {
case ColumnType::StringType: {
dataOffset = reinterpret_cast<const uint16_t &>((*currentNode)->block.get_ro()[dataPos
+ (currentPos - 1) * gOffsetSize]);
}
......@@ -175,14 +195,14 @@ class PTable {
pTupleOffsets[idx] = dataOffset;
++idx;
}
return *(new PTuple<Tuple, KeyType>(*currentNode, pTupleOffsets));
return std::move(PTuple<KeyType, Tuple>(*currentNode, pTupleOffsets));
}
// iterator traits
using difference_type = long;
using value_type = PTuple<Tuple, KeyType>;
using pointer = const PTuple<Tuple, KeyType> *;
using reference = const PTuple<Tuple, KeyType> &;
using value_type = PTuple<KeyType, Tuple>;
using pointer = const PTuple<KeyType, Tuple> *;
using reference = const PTuple<KeyType, Tuple> &;
using iterator_category = std::forward_iterator_tag;
};
......@@ -192,12 +212,12 @@ class PTable {
***************************************************************************/
class iterator {
public:
using Predicate = std::function<bool(const PTuple<Tuple, KeyType> &)>;
using Predicate = std::function<bool(const PTuple<KeyType, Tuple> &)>;
using TreeIter = typename IndexType::iterator;
iterator() : treeIter() {}
iterator(TreeIter _iter, TreeIter _end, Predicate _pred = [](const PTuple<Tuple, KeyType> &) { return true; })
iterator(TreeIter _iter, TreeIter _end, Predicate _pred = [](const PTuple<KeyType, Tuple> &) { return true; })
: treeIter(_iter), end(_end), pred(_pred) {
while (isValid() && !pred((*treeIter).second))
treeIter++;
......@@ -231,15 +251,15 @@ class PTable {
bool operator!=(iterator other) const { return !(treeIter == other.treeIter); }
PTuple<Tuple, KeyType> operator*() {
PTuple<KeyType, Tuple> operator*() {
return (*treeIter).second;
}
// iterator traits
using difference_type = long;
using value_type = PTuple<Tuple, KeyType>;
using pointer = const PTuple<Tuple, KeyType> *;
using reference = const PTuple<Tuple, KeyType> &;
using value_type = PTuple<KeyType, Tuple>;
using pointer = const PTuple<KeyType, Tuple> *;
using reference = const PTuple<KeyType, Tuple> &;
using iterator_category = std::forward_iterator_tag;
protected:
TreeIter treeIter, end;
......@@ -270,7 +290,7 @@ class PTable {
/************************************************************************//**
* \brief Constructor for a given schema (using TableInfo) and dimension clustering.
***************************************************************************/
PTable(const VTableInfo &tInfo, const Dimensions &_bdccInfo = Dimensions()) {
PTable(const VTableInfoType &tInfo, const Dimensions &_bdccInfo = Dimensions()) {
auto pop = pool_by_vptr(this);
transaction::exec_tx(pop, [&] { init(tInfo, _bdccInfo); });
}
......@@ -409,16 +429,8 @@ class PTable {
// indicate the deleted tuple
const auto &dataPos = reinterpret_cast<const uint16_t &>(ptp.getNode()->block.get_ro()[gDataOffsetPos]);
uint16_t pos = 0u;
switch (root->tInfo->columnInfo(0).getType()) {
case Int_Type: pos = (ptp.getOffsetAt(0) - ptp.getNode()->block.get_ro()[dataPos]) / sizeof(int) + 1;
break;
case Double_Type: pos = (ptp.getOffsetAt(0) - ptp.getNode()->block.get_ro()[dataPos]) / sizeof(double) + 1;
break;
case String_Type: pos = (ptp.getOffsetAt(0) - ptp.getNode()->block.get_ro()[dataPos]) / gOffsetSize + 1;
break;
default:;
}
const auto colSize = ColumnAttributes<toColumnType<typename std::tuple_element<0, Tuple>::type>()>::dataSize;
const auto pos = (ptp.getOffsetAt(0) - dataPos) / colSize;
ptp.getNode()->deleted.get_rw().emplace_back(pos);
//TODO: Delete from histogram?
......@@ -430,7 +442,7 @@ class PTable {
nres = static_cast<std::size_t>(root->index->erase(key));
// free space of PTuple
// delete_persistent<PTuple<Tuple, KeyType>>(ptp);
// delete_persistent<PTuple<KeyType, Tuple>>(ptp);
});
return nres;
}
......@@ -446,8 +458,8 @@ class PTable {
* \return
* the PTuple associated with the given key
***************************************************************************/
PTuple<Tuple, KeyType> getByKey(KeyType key) const {
PTuple<Tuple, KeyType> val;
PTuple<KeyType, Tuple> getByKey(KeyType key) const {
PTuple<KeyType, Tuple> val;
if (root->index->lookup(key, &val)) {
return val;
} else {
......@@ -470,6 +482,10 @@ class PTable {
return BlockIterator(*this, rangePredicates);
}
void rangeScan2(const KeyType &min, const KeyType &max, typename IndexType::ScanFunc func) const {
root->index->scan(min, max, func);
}
/************************************************************************//**
* @brief Return the number of tuples stored in the table.
*
......@@ -525,7 +541,7 @@ class PTable {
/* Header/General information */
std::cout << "\nBDCC Range min: " << key1 << '\n'
<< "BDCC Range max: " << key2 << '\n'
<< "Tuple count: " << cnt << '\n'
<< "Tuple count: " << cnt - currentNode->deleted.get_ro().size() << '\n'
<< "Header size: " << headerSize << " Bytes" << '\n'
<< "Body size: " << bodySize << " Bytes" << '\n'
<< "Free Space: " << space << " Bytes" << std::endl;
......@@ -533,92 +549,33 @@ class PTable {
/* Body/Column/Minipage data */
if (cnt > 0) {
size_t idx = 0;
for (const auto &c : tInfo) {
std::cout << "Column Info: " << c.getName() << ": " << c.getType() << std::endl;
const auto &smaPos = reinterpret_cast<const uint16_t &>(b[gSmaOffsetPos + idx * gAttrOffsetSize]);
const auto nCols = std::tuple_size<Tuple>::value;
auto printColumns = [&] (auto element, std::size_t idx) {
const auto colName = tInfo.columnInfo(idx).getName();
using cAttributes = ColumnAttributes<toColumnType<decltype(element)>()>;
std::cout << "Column Info: " << colName << ": " << cAttributes::typeName << std::endl;
const auto smas = cAttributes::smaPos(b, gSmaOffsetPos + idx * gAttrOffsetSize);
const auto &dataPos = reinterpret_cast<const uint16_t &>(b[gDataOffsetPos + idx * gAttrOffsetSize]);
const auto &data = reinterpret_cast<const int (&)[cnt]>(b[dataPos]);
switch (c.getType()) {
case Int_Type: {
const auto &smaMin = reinterpret_cast<const int &>(b[smaPos]);
const auto &smaMax = reinterpret_cast<const int &>(b[smaPos + sizeof(int)]);
const auto &data = reinterpret_cast<const int (&)[cnt]>(b[dataPos]);
/* Remaining Space */
auto nextSmaPos = (colCnt == idx + 1) ?
gBlockSize :
reinterpret_cast<const uint16_t &>(b[gSmaOffsetPos + (idx + 1) * gAttrOffsetSize]);
const auto freeSpaceMiniPage = nextSmaPos - dataPos - (cnt * sizeof(int));
std::cout << "Column[" << idx << "]: " << c.getName()
<< "\n\tSpace left: " << freeSpaceMiniPage << " Bytes"
<< "\n\tsmaMin: " << smaMin
<< "\n\tsmaMax: " << smaMax
<< "\n\tData: {";
// const char *padding = "";
// for (auto i = 0u; i < cnt; i++) {
// std::cout << padding << data[i];
// padding = ", ";
// }
std::cout << "}\n";
}
break;
/* Remaining Space */
const auto freeSpace = cAttributes::freeSpace(b, dataPos, cnt, nCols, idx);
case Double_Type: {
const auto &smaMin = reinterpret_cast<const double &>(b[smaPos]);
const auto &smaMax = reinterpret_cast<const double &>(b[smaPos + sizeof(double)]);
const auto &data = reinterpret_cast<const double (&)[cnt]>(b[dataPos]);
/* Remaining Space */
auto nextSmaPos = (colCnt == idx + 1) ?
gBlockSize :
reinterpret_cast<const uint16_t &>(b[gSmaOffsetPos + (idx + 1) * gAttrOffsetSize]);
const auto freeSpaceMiniPage = nextSmaPos - dataPos - (cnt * sizeof(double));
std::cout << "Column[" << idx << "]: " << c.getName()
<< "\n\tSpace left: " << freeSpaceMiniPage << " Bytes"
<< "\n\tsmaMin: " << smaMin
<< "\n\tsmaMax: " << smaMax
<< "\n\tData: {";
std::cout << "Column[" << idx << "]: " << colName
<< "\n\tSpace left: " << freeSpace << " Bytes"
<< "\n\tsmaMin: " << smas.first
<< "\n\tsmaMax: " << smas.second
<< "\n\tData: {";
// const char *padding = "";
// for (auto i = 0u; i < cnt; i++) {
// std::cout << padding << data[i];
// padding = ", ";
// }
std::cout << "}\n";
}
break;
case String_Type: {
auto &smaMinPos = (uint16_t &) b[smaPos];
auto &smaMaxPos = (uint16_t &) b[smaPos + gOffsetSize];
auto &stringPos = (uint16_t (&)[cnt]) b[dataPos];
auto smaMin(reinterpret_cast<const char (&)[]>(b[smaMinPos]));
auto smaMax(reinterpret_cast<const char (&)[]>(b[smaMaxPos]));
auto currentOffsetPos = dataPos + cnt * gOffsetSize;
auto currentOffset = reinterpret_cast<const uint16_t &>(b[currentOffsetPos - gOffsetSize]);
auto freeSpaceMiniPage = currentOffset - currentOffsetPos;
std::cout << "Column[" << idx << "]: " << c.getName()
<< "\n\tSpace left: " << freeSpaceMiniPage << " Bytes"
<< "\n\tsmaMin: " << smaMin
<< "\n\tsmaMax: " << smaMax
<< "\n\tData: {";
// const char *padding = "";
// for (auto i = 0u; i < cnt; i++) {
// std::string data(reinterpret_cast<char (&)[]>(b[stringPos[i]]));
// std::cout << padding << data;
// padding = ", ";
// }
std::cout << "}\n";
}
break;
default:throw PTableException("unsupported column type\n");
}
++idx;
} /* end for (auto &c: tInfo) */
std::cout << "}\n";
};
forEachTypeInTuple<decltype(printColumns), Types...>(printColumns);
} /* if cnt > 0 */
std::cout << "\n";
currentNode = currentNode->next;
......@@ -631,7 +588,7 @@ class PTable {
struct root {
DataNodePtr dataNodes;
persistent_ptr<IndexType> index;
persistent_ptr<PTableInfo> tInfo;
persistent_ptr<PTableInfoType> tInfo;
persistent_ptr<BDCCInfo> bdccInfo;
};
persistent_ptr<struct root> root;
......@@ -649,38 +606,65 @@ class PTable {
ColumnIntMap calcMinipageSizes(uint16_t totalSize, ColumnIntMap customizations = ColumnIntMap()) {
auto portions = 0u;
ColumnIntMap miniPageSizes = ColumnIntMap();
/* Get the sum of all column portitions */
/*
auto countPortitions = [&] (auto element, std::size_t idx) {
if (customizations.find(idx) == customizations.end()) {
portions += ColumnAttributes<toColumnType<decltype(element)>()>::miniPagePortion;
} else {
portions += customizations[idx];
}
};
forEachTypeInTuple<decltype(countPortitions), Types...>(countPortitions);
*/
for (auto i = 0u; i < root->tInfo->numColumns(); i++) {
const auto &c = root->tInfo->columnInfo(i);
if (customizations.find(i) == customizations.end()) {
switch (c.getType()) {
case Int_Type:portions += 1;
case ColumnType::IntType:portions += 1;
break;
case Double_Type:portions += 2;
case ColumnType::DoubleType:portions += 2;
break;
case String_Type:portions += 4;
case ColumnType::StringType:portions += 4;
break;
default:throw PTableException("unsupported column type\n");
}
} else
portions += customizations[i];
}
/* Calculate and save the minipage sizes for all columns */
/*
auto calcMiniPageSizes = [&] (auto element, std::size_t idx) {
if (customizations.find(idx) == customizations.end()) {
miniPageSizes[idx] = ColumnAttributes<toColumnType<decltype(element)>()>::miniPagePortion * totalSize / portions;
} else {
miniPageSizes[idx] = customizations[idx] * totalSize / portions;
}
};
forEachTypeInTuple<decltype(calcMiniPageSizes), Types...>(calcMiniPageSizes);
*/
for (auto i = 0u; i < root->tInfo->numColumns(); i++) {
const auto &c = root->tInfo->columnInfo(i);
if (customizations.find(i) == customizations.end()) {
switch (c.getType()) {
case Int_Type:miniPageSizes[i] = 1 * totalSize / portions;
case ColumnType::IntType:miniPageSizes[i] = 1 * totalSize / portions;
break;
case Double_Type:miniPageSizes[i] = 2 * totalSize / portions;