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

Cleaned some implementation details + and some fixes

parent 3f4e53b3
......@@ -28,13 +28,13 @@ option(USE_BOOST_SPIRIT_PARSER
# If switched to off, it will not be downloaded, saving initial building time.
option(USE_ROCKSDB_TABLE
"use RocksDB for implementing persistent tables"
OFF
OFF
)
# Use Non-Volatile Memory Library for implementing tables
option(USE_NVML_TABLE
"use nvml for implementing persistent memory tables"
ON
ON
)
# Build only pipefabric libraries (cep and core)
......@@ -55,7 +55,7 @@ option(BUILD_TEST_CASES
#Build google benchmark library
option(BUILD_GOOGLE_BENCH
"build google benchmark"
ON
OFF
)
# Build benchmark test
......@@ -75,7 +75,7 @@ endif()
#CMAKE_FORCE_CXX_COMPILER(icpc "Intel C++ Compiler")
# C++ compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wno-deprecated -g -O3 -Wsign-compare")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wno-deprecated -g -O2 -Wsign-compare")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-local-typedefs -Wno-#pragma-messages")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
......@@ -278,37 +278,43 @@ set(core_sources
${THIRD_PARTY_DIR}/catch
)
if(USE_ROCKSDB_TABLE)
if(BUILD_GOOGLE_BENCH)
set(core_sources
${core_sources}
${THIRD_PARTY_DIR}/rocksdb
${THIRD_PARTY_DIR}/benchmark
)
endif()
if(BUILD_GOOGLE_BENCH)
if(USE_ROCKSDB_TABLE)
set(core_sources
${core_sources}
${THIRD_PARTY_DIR}/benchmark
)
${THIRD_PARTY_DIR}/rocksdb)
add_library(pfabric_core SHARED
${core_sources})
target_link_libraries(pfabric_core
${BOOST_LIBRARIES}
${ZEROMQ_LIBRARIES}
${ROCKSDB_LIB})
add_executable(rock_test rock_test.cpp)
target_link_libraries(rock_test pfabric_core ${ROCKSDB_LIB})
endif()
if(USE_NVML_TABLE)
set(core_sources
${core_sources}
nvm/PTableInfo.cpp
${THIRD_PARTY_DIR}/nvml
)
endif()
add_library(pfabric_core SHARED
${THIRD_PARTY_DIR}/nvml)
add_library(pfabric_core SHARED
${core_sources}
)
)
target_link_libraries(pfabric_core
${BOOST_LIBRARIES}
${ZEROMQ_LIBRARIES}
${NVML_LIBRARIES})
target_link_libraries(pfabric_core
${BOOST_LIBRARIES}
${ZEROMQ_LIBRARIES}
${NVML_LIBRARIES}
)
add_executable(nvm_test nvm_test.cpp)
target_link_libraries(nvm_test pfabric_core)
endif()
#-----------------------------------------------------------------------------------------
#
......
......@@ -23,8 +23,6 @@
#include "dsl/PFabricContext.hpp"
#include "dsl/Topology.hpp"
#include "table/BaseTable.hpp"
#include "table/TableInfo.hpp"
using namespace pfabric;
......
......@@ -35,50 +35,57 @@
#include "nvml/include/libpmemobj++/transaction.hpp"
#include "nvml/include/libpmemobj++/utils.hpp"
namespace pfabric { namespace nvm {
namespace pfabric {
namespace nvm {
using nvml::obj::allocator;
using nvml::obj::delete_persistent;
using nvml::obj::make_persistent;
using nvml::obj::p;
using nvml::obj::persistent_ptr;
using nvml::obj::pool_by_vptr;
using nvml::obj::transaction;
using nvml::obj::allocator;
using nvml::obj::delete_persistent;
using nvml::obj::make_persistent;
using nvml::obj::p;
using nvml::obj::persistent_ptr;
using nvml::obj::pool_by_vptr;
using nvml::obj::transaction;
/**************************************************************************//**
* \brief Info structure about the BDCC meta data.
*
* It is used in persistent tables to store the BDCC meta data and statistics.
*****************************************************************************/
struct BDCCInfo {
typedef std::unordered_map<uint16_t, uint16_t> ColumnBitsMap; //<mapping from column id to number of bits
typedef std::vector<std::pair<uint16_t,uint16_t>, nvml::obj::allocator<std::pair<uint16_t, uint16_t>>> pColumnBitsMap;
class BDCCInfo {
using pColumnBitsMap = const std::vector<std::pair<uint16_t, uint16_t>, nvml::obj::allocator<std::pair<uint16_t, uint16_t>>>;
public:
using ColumnBitsMap = const std::unordered_map<uint16_t, uint16_t>; //<mapping from column id to number of bits
explicit BDCCInfo(const ColumnBitsMap &_bitMap) :
bitMap(_bitMap.cbegin(), _bitMap.cend()),
numberOfBins(std::accumulate(_bitMap.begin(), _bitMap.end(), 0,
[](const size_t sum, decltype(*_bitMap.begin()) p) { return sum + p.second; })) {}
explicit BDCCInfo(const ColumnBitsMap &_bitMap) {
auto pop = pool_by_vptr(this);
transaction::exec_tx(pop, [&] {
//bitMap = make_persistent<pColumnBitsMap>();
for (const auto& c : _bitMap) {
bitMap.insert(bitMap.cbegin(), std::make_pair(c.first, c.second));
const pColumnBitsMap::const_iterator find(uint16_t item) const {
for (auto it = bitMap.cbegin(); it != bitMap.cend(); it++) {
if (it->first == item) return it;
}
return bitMap.cend();
}
numBins = std::accumulate(_bitMap.begin(), _bitMap.end(), 0,
[](const size_t sum, decltype(*_bitMap.begin()) p) { return sum + p.second; });
});
}
pColumnBitsMap::const_iterator find(uint16_t item) {
for (auto it = bitMap.cbegin(); it!= bitMap.cend(); it++) {
if (it->first == item) return it;
}
return bitMap.cend();
}
const size_t numColumns() const {
return bitMap.size();
}
pColumnBitsMap bitMap;
p<size_t> numBins;
//std::map<uint32_t, std::size_t> histogram;
const size_t numBins() const {
return numberOfBins.get_ro();
}
};/* struct BDCCInfo */
const pColumnBitsMap::const_iterator cend() const {
return bitMap.cend();
}
// private:
const pColumnBitsMap bitMap;
p<const size_t> numberOfBins;
//std::map<uint32_t, std::size_t> histogram;
};/* struct BDCCInfo */
}} /* namespace pfabric::nvm */
}
} /* namespace pfabric::nvm */
#endif /* PTuple_hpp_ */
/*
* Copyright (c) 2014-17 The PipeFabric team,
* All Rights Reserved.
*
* This file is part of the PipeFabric package.
*
* PipeFabric is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This package 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file LICENSE.
* If not you can find the GPL at http://www.gnu.org/copyleft/gpl.html
*/
#ifndef NVM_Block_hpp_
#define NVM_Block_hpp_
#include <array>
#include "nvml/include/libpmemobj++/make_persistent.hpp"
#include "nvml/include/libpmemobj++/persistent_ptr.hpp"
namespace pfabric {
namespace nvm {
using nvml::obj::persistent_ptr;
using nvml::obj::make_persistent;
using nvml::obj::delete_persistent;
/** Positions in NVM_Block */
const int gDDCRangePos1 = 0;
const int gDDCRangePos2 = 4;
const int gCountPos = 8;
const int gFreeSpacePos = 12;
const int gSmaOffsetPos = 14;
const int gDataOffsetPos = 16;
/** Sizes/Lengths in NVM_Block */
const int gFixedHeaderSize = 14;
const int gDDCValueSize = 4;
const int gAttrOffsetSize = 4;
const int gOffsetSize = 2;
/** The size of a single block in persistent memory */
static constexpr uint16_t gBlockSize = 1 << 15; // 32KB
/**
* \brief This type represents a byte array used for persistent structures.
*
* A BDCC_Block is a PAX oriented data block with the following structure for 32KB:
* <ddc_range><ddc_cnt><sma_offset_0><data_offset_0> ...<sma_offset_n><data_offset_n>
* <sma_min_0><sma_max_0><data_vector_0> ... <sma_min_n><sma_max_n><data_vector_n>
* 0 ddc_range -> long (x2) - 8 Byte
* 8 ddc_cnt -> long - 4 Byte
* 12 free_space -> unsigned short
* for each attribute:
* 14 sma_offset_x -> unsigned short - 2 Byte (depends on block size)
* 16 data_offset_x -> unsigned short
* ...
*
* for each attribute (int, double):
* . sma_min_x -> size of attributes data type
* . sma_max_x -> size of attributes data type
* . data_vector -> size of attributes data type * ddc_cnt
* ...
*
* for each attribute (string - data starts at the end of the minipage):
* . sma_min_offset_x -> unsigned short
* . sma_max_offset_x -> unsigned short
* . data_offset_vector -> unsigned short * ddc_cnt
* . ...
* . data -> size of all strings + ddc_cnt (Nul termination)
*/
using BDCC_Block = typename std::array<uint8_t, gBlockSize>;
template<typename KeyType>
struct DataNode {
using KeyVector = std::array<KeyType, 8192>; // <KeyType, nvml::obj::allocator<KeyType>>;
DataNode() : next(nullptr), block(nullptr) {
keys = make_persistent<KeyVector>();
}
DataNode(BDCC_Block _block) : next(nullptr) {
block = make_persistent<BDCC_Block>(_block);
keys = make_persistent<KeyVector>();
}
persistent_ptr<struct DataNode> next;
persistent_ptr<BDCC_Block> block;
persistent_ptr<KeyVector> keys;
void clear() {
if (next) {
//delete_persistent<struct DataNode>(next);
next = nullptr;
}
if (block) {
delete_persistent<BDCC_Block>(block);
block = nullptr;
}
delete_persistent<struct DataNode>(this);
}
};
} /* end namespace nvm */
} /* end namespace pfabric */
#endif /* NVM_Block_hpp_ */
......@@ -39,7 +39,7 @@ class PBPTree {
#ifndef UNIT_TESTS
private:
#else
public:
public:f
#endif
// Forward declarations
......@@ -52,21 +52,15 @@ class PBPTree {
LeafOrBranchNode(const LeafOrBranchNode& other) { copy(other); };
void copy (const LeafOrBranchNode& other) throw() {
// NodeType tempTag = tag;
tag = other.tag;
// other.tag = tempTag;
switch (tag) {
case LEAF: {
// persistent_ptr<LeafNode> tempLeaf(leaf);
leaf = other.leaf;
// other.leaf = tempLeaf;
break;
}
case BRANCH: {
// persistent_ptr<BranchNode> tempBranch(branch);
branch = other.branch;
// other.branch = tempBranch;
break;
}
default: break;
......@@ -115,7 +109,7 @@ class PBPTree {
auto node = root;
while (d-- > 0) {
auto n = node.branch;
node = n->children->at(0);
node = n->children.get_ro()[0];
}
currentNode = node.leaf;
currentPosition = 0;
......@@ -137,7 +131,7 @@ class PBPTree {
bool operator!=(iterator other) const {return !(*this == other);}
std::pair<KeyType, ValueType> operator*() {
return std::make_pair(currentNode->keys->at(currentPosition), currentNode->values->at(currentPosition));
return std::make_pair(currentNode->keys.get_ro()[currentPosition], currentNode->values.get_ro()[currentPosition]);
}
// iterator traits
......@@ -153,8 +147,7 @@ class PBPTree {
/**
* Typedef for a function passed to the scan method.
*/
typedef std::function<void(const KeyType &key, const ValueType &val)>
ScanFunc;
using ScanFunc = std::function<void(const KeyType &key, const ValueType &val)>;
/**
* Constructor for creating a new B+ tree.
......@@ -198,9 +191,9 @@ class PBPTree {
if (wasSplit) {
// we had an overflow in the node and therefore the node is split
auto root = newBranchNode();
root->keys->at(0) = splitInfo.key;
root->children->at(0) = splitInfo.leftChild;
root->children->at(1) = splitInfo.rightChild;
root->keys.get_rw()[0] = splitInfo.key;
root->children.get_rw()[0] = splitInfo.leftChild;
root->children.get_rw()[1] = splitInfo.rightChild;
root->numKeys = root->numKeys + 1;
rootNode.branch = root;
depth = depth + 1;
......@@ -223,9 +216,9 @@ class PBPTree {
auto leafNode = findLeafNode(key);
auto pos = lookupPositionInLeafNode(leafNode, key);
if (pos < leafNode->numKeys && leafNode->keys->at(pos) == key) {
if (pos < leafNode->numKeys && leafNode->keys.get_ro()[pos] == key) {
// we found it!
*val = leafNode->values->at(pos);
*val = leafNode->values.get_ro()[pos];
result = true;
}
return result;
......@@ -277,14 +270,14 @@ class PBPTree {
while ( d-- > 0) {
// as long as we aren't at the leaf level we follow the path down
auto n = node.branch;
node = n->children->at(0);
node = n->children.get_ro()[0];
}
auto leaf = node.leaf;
while (leaf != nullptr) {
// for each key-value pair call func
for (auto i = 0u; i < leaf->numKeys; i++) {
auto &key = leaf->keys->at(i);
auto &val = leaf->values->at(i);
auto &key = leaf->keys.get_ro()[i];
auto &val = leaf->values.get_ro()[i];
func(key, val);
}
// move to the next leaf node
......@@ -306,10 +299,10 @@ class PBPTree {
while (leaf != nullptr) {
// for each key-value pair within the range call func
for (auto i = 0u; i < leaf->numKeys; i++) {
auto &key = leaf->keys->at(i);
auto &key = leaf->keys.get_ro()[i];
if (key > maxKey) return;
auto &val = leaf->values->at(i);
auto &val = leaf->values.get_ro()[i];
func(key, val);
}
// move to the next leaf node
......@@ -334,10 +327,10 @@ class PBPTree {
bool eraseFromLeafNode(persistent_ptr<LeafNode> node, const KeyType &key) {
bool deleted = false;
auto pos = lookupPositionInLeafNode(node, key);
if (node->keys->at(pos) == key) {
if (node->keys.get_rw()[pos] == key) {
for (auto i = pos; i < node->numKeys - 1; i++) {
node->keys->at(i) = node->keys->at(i + 1);
node->values->at(i) = node->values->at(i + 1);
node->keys.get_rw()[i] = node->keys.get_ro()[i + 1];
node->values.get_rw()[i] = node->values.get_ro()[i + 1];
}
node->numKeys--;
deleted = true;
......@@ -365,11 +358,11 @@ class PBPTree {
if (pos > 0 && leaf->prevLeaf->numKeys > middle) {
// we have a sibling at the left for rebalancing the keys
balanceLeafNodes(leaf->prevLeaf, leaf);
node->keys->at(pos) = leaf->keys->at(0);
node->keys.get_rw()[pos] = leaf->keys.get_ro()[0];
} else if (pos < node->numKeys && leaf->nextLeaf->numKeys > middle) {
// we have a sibling at the right for rebalancing the keys
balanceLeafNodes(leaf->nextLeaf, leaf);
node->keys->at(pos) = leaf->nextLeaf->keys->at(0);
node->keys.get_rw()[pos] = leaf->nextLeaf->keys.get_ro()[0];
} else {
// 2. if this fails we have to merge two leaf nodes
// but only if both nodes have the same direct parent
......@@ -391,10 +384,10 @@ class PBPTree {
if (pos > 0) pos--;
// just remove the child node from the current branch node
for (auto i = pos; i < node->numKeys - 1; i++) {
node->keys->at(i) = node->keys->at(i + 1);
node->children->at(i + 1) = node->children->at(i + 2);
node->keys.get_rw()[i] = node->keys.get_ro()[i + 1];
node->children.get_rw()[i + 1] = node->children.get_ro()[i + 2];
}
node->children->at(pos) = survivor;
node->children.get_rw()[pos] = survivor;
node->numKeys--;
} else {
// This is a special case that happens only if
......@@ -421,8 +414,8 @@ class PBPTree {
// we move all keys/values from node2 to node1
for (auto i = 0u; i < node2->numKeys; i++) {
node1->keys->at(node1->numKeys + i) = node2->keys->at(i);
node1->values->at(node1->numKeys + i) = node2->values->at(i);
node1->keys.get_rw()[node1->numKeys + i] = node2->keys.get_ro()[i];
node1->values.get_rw()[node1->numKeys + i] = node2->values.get_ro()[i];
}
node1->numKeys += node2->numKeys;
node1->nextLeaf = node2->nextLeaf;
......@@ -447,18 +440,18 @@ class PBPTree {
unsigned int toMove = donor->numKeys - balancedNum;
if (toMove == 0) return;
if (donor->keys->at(0) < receiver->keys->at(0)) {
if (donor->keys.get_rw()[0] < receiver->keys.get_ro()[0]) {
// move from one node to a node with larger keys
unsigned int i = 0, j = 0;
for (i = receiver->numKeys; i > 0; i--) {
// reserve space on receiver side
receiver->keys->at(i + toMove - 1) = receiver->keys->at(i - 1);
receiver->values->at(i + toMove - 1) = receiver->values->at(i - 1);
receiver->keys.get_rw()[i + toMove - 1] = receiver->keys.get_ro()[i - 1];
receiver->values.get_rw()[i + toMove - 1] = receiver->values.get_ro()[i - 1];
}
// move toMove keys/values from donor to receiver
for (i = balancedNum; i < donor->numKeys; i++, j++) {
receiver->keys->at(j) = donor->keys->at(i);
receiver->values->at(j) = donor->values->at(i);
receiver->keys.get_rw()[j] = donor->keys.get_ro()[i];
receiver->values.get_rw()[j] = donor->values.get_ro()[i];
receiver->numKeys++;
}
} else {
......@@ -466,14 +459,14 @@ class PBPTree {
unsigned int i = 0;
// move toMove keys/values from donor to receiver
for (i = 0; i < toMove; i++) {
receiver->keys->at(receiver->numKeys) = donor->keys->at(i);
receiver->values->at(receiver->numKeys) = donor->values->at(i);
receiver->keys.get_rw()[receiver->numKeys] = donor->keys.get_ro()[i];
receiver->values.get_rw()[receiver->numKeys] = donor->values.get_ro()[i];
receiver->numKeys++;
}
// on donor node move all keys and values to the left
for (i = 0; i < donor->numKeys - toMove; i++) {
donor->keys->at(i) = donor->keys->at(toMove + i);
donor->values->at(i) = donor->values->at(toMove + i);
donor->keys.get_rw()[i] = donor->keys.get_ro()[toMove + i];
donor->values.get_rw()[i] = donor->values.get_ro()[toMove + i];
}
}
donor->numKeys -= toMove;
......@@ -496,7 +489,7 @@ class PBPTree {
bool deleted = false;
// try to find the branch
auto pos = lookupPositionInBranchNode(node, key);
auto n = node->children->at(pos);
auto n = node->children.get_ro()[pos];
if (d == 1) {
// the next level is the leaf level
auto leaf = n.leaf;
......@@ -537,16 +530,16 @@ class PBPTree {
*/
void mergeBranchNodes(persistent_ptr<BranchNode> sibling, const KeyType &key,
persistent_ptr<BranchNode> node) {
assert(key <= node->keys->at(0));
assert(key <= node->keys.get_ro()[0]);
assert(sibling != nullptr);
assert(node != nullptr);
assert(sibling->keys->at(sibling->numKeys - 1) < key);
assert(sibling->keys.get_ro()[sibling->numKeys - 1] < key);
sibling->keys->at(sibling->numKeys) = key;
sibling->children->at(sibling->numKeys + 1) = node->children->at(0);
sibling->keys.get_rw()[sibling->numKeys] = key;
sibling->children.get_rw()[sibling->numKeys + 1] = node->children.get_ro()[0];
for (auto i = 0u; i < node->numKeys; i++) {
sibling->keys->at(sibling->numKeys + i + 1) = node->keys->at(i);
sibling->children->at(sibling->numKeys + i + 2) = node->children->at(i + 1);
sibling->keys.get_rw()[sibling->numKeys + i + 1] = node->keys.get_ro()[i];
sibling->children.get_rw()[sibling->numKeys + i + 2] = node->children.get_ro()[i + 1];
}
sibling->numKeys += node->numKeys + 1;
}
......@@ -573,16 +566,16 @@ class PBPTree {
unsigned int middle = (N + 1) / 2;
// 1. we check whether we can rebalance with one of the siblings
if (pos > 0 &&
(node->children->at(pos - 1)).branch->numKeys >
(node->children.get_ro()[pos - 1]).branch->numKeys >
middle) {
// we have a sibling at the left for rebalancing the keys
persistent_ptr<BranchNode> sibling = (node->children->at(pos - 1)).branch;
persistent_ptr<BranchNode> sibling = (node->children.get_ro()[pos - 1]).branch;
balanceBranchNodes(sibling, child, node, pos - 1);
// node->keys->at(pos) = child->keys->at(0);
// node->keys.get_rw()[pos] = child->keys.get_ro()[0];
return newChild;
} else if (pos < node->numKeys && (node->children->at(pos + 1)).branch->numKeys > middle) {
} else if (pos < node->numKeys && (node->children.get_ro()[pos + 1]).branch->numKeys > middle) {
// we have a sibling at the right for rebalancing the keys
auto sibling = (node->children->at(pos + 1)).branch;
auto sibling = (node->children.get_ro()[pos + 1]).branch;
balanceBranchNodes(sibling, child, node, pos);
return newChild;
} else {
......@@ -591,37 +584,37 @@ class PBPTree {
unsigned int prevKeys = 0, nextKeys = 0;
if (pos > 0) {
lSibling = (node->children->at(pos - 1)).branch;
lSibling = (node->children.get_ro()[pos - 1]).branch;
prevKeys = lSibling->numKeys;
}
if (pos < node->numKeys) {
rSibling = (node->children->at(pos + 1)).branch;
rSibling = (node->children.get_ro()[pos + 1]).branch;
nextKeys = rSibling->numKeys;
}
persistent_ptr<BranchNode> witnessNode = nullptr;
auto ppos = pos;
if (prevKeys > 0) {
mergeBranchNodes(lSibling, node->keys->at(pos - 1), child);
mergeBranchNodes(lSibling, node->keys.get_ro()[pos - 1], child);
ppos = pos - 1;
witnessNode = child;
newChild = lSibling;
// pos -= 1;
} else if (nextKeys > 0) {
mergeBranchNodes(child, node->keys->at(pos), rSibling);
mergeBranchNodes(child, node->keys.get_ro()[pos], rSibling);
witnessNode = rSibling