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

/🔨 Added FPTree (with hashing and bitmap) and some fixes

parent 8a568415
......@@ -6,7 +6,7 @@ project (nvm-DS)
################################################################################
# Set the mount path of your pmem device where the structures should be stored
set(PMEM_MNT_PATH "/mnt/pmem/test")
set(PMEM_MNT_PATH "/mnt/mem/test")
# Installation path (creates include and lib within this directory)
if(NOT PROJECT_INSTALL_DIR)
......@@ -107,10 +107,10 @@ set_target_properties(nvmDS_deps PROPERTIES LINKER_LANGUAGE CXX)
#################
#
#set(PROJECT_LIBS ${PROJECT_LIBS})
set(PROJECT_INCLUDES_D ${PROJECT_INCLUDES_D})
set(PROJECT_INCLUDES_D ${PROJECT_INCLUDES_D}
${CMAKE_CURRENT_SOURCE_DIR}/utils)
set(PROJECT_INCLUDES_F ${PROJECT_INCLUDES_F}
${CMAKE_BINARY_DIR}/generated/config.h
${CMAKE_CURRENT_SOURCE_DIR}/IdxProfile.hpp)
${CMAKE_BINARY_DIR}/generated/config.h)
set(PROJECT_LIB_DIR ${PROJECT_INSTALL_DIR}/lib)
set(PROJECT_INCLUDE_DIR ${PROJECT_INSTALL_DIR}/include)
......
......@@ -9,5 +9,6 @@ set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
)
set(PROJECT_INCLUDES_F ${PROJECT_INCLUDES_F}
${CMAKE_CURRENT_SOURCE_DIR}/PTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/FPTree.hpp
PARENT_SCOPE)
This diff is collapsed.
This diff is collapsed.
......@@ -13,7 +13,6 @@ set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
################
#
set(PROJECT_INCLUDES_F ${PROJECT_INCLUDES_F}
${CMAKE_CURRENT_SOURCE_DIR}/ElementOfRankK.hpp
${CMAKE_CURRENT_SOURCE_DIR}/PBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/UnsortedPBPTree.hpp
PARENT_SCOPE)
......@@ -28,7 +28,7 @@
#include <libpmemobj++/persistent_ptr.hpp>
#include <libpmemobj++/transaction.hpp>
#include <libpmemobj++/utils.hpp>
#include "ElementOfRankK.hpp"
#include "utils/ElementOfRankK.hpp"
#define BRANCH_PADDING 0
#define LEAF_PADDING 0
......@@ -968,26 +968,23 @@ class UnsortedPBPTree {
// the node is full, so we must split it
// determine the split position by finding the median in unsorted array of keys
PROFILE_SPLIT
KeyType data[M];
for (auto i = 0u; i < M; i++) {
PROFILE_READ()
data[i] = node->keys.get_ro()[i];
}
auto data = node->keys.get_ro();
PROFILE_READ(M)
KeyType middle = ElementOfRank::elementOfRank((M + 1) / 2 + 1, data, M, 0);
KeyType middle = ElementOfRankK::elementOfRankK((M + 1) / 2, data, 0, M);
// move all entries with greater or equal keys to a new sibling node
persistent_ptr<LeafNode> sibling = newLeafNode();
auto node_filled = 0u, sibling_filled = 0u;
for (auto i = 0u; i < node->numKeys; i++) {
PROFILE_READ()
KeyType currkey = node->keys.get_ro()[i];
if (currkey>=middle){
if (currkey > middle){
PROFILE_READ()
PROFILE_WRITE(2)
sibling->keys.get_rw()[sibling_filled] = currkey;
sibling->values.get_rw()[sibling_filled] = node->values.get_ro()[i];
sibling_filled++;
} else{
} else {
PROFILE_READ()
PROFILE_WRITE(2)
node->keys.get_rw()[node_filled] = currkey;
......@@ -1015,7 +1012,7 @@ class UnsortedPBPTree {
split = true;
splitInfo->leftChild = node;
splitInfo->rightChild = sibling;
splitInfo->key = middle;
splitInfo->key = sibling->keys.get_ro()[findMinKeyAtLeafNode(sibling)];
} else {
// otherwise, we can simply insert the new entry at the last position
insertInLeafNodeAtLastPosition(node, key, val);
......
......@@ -10,6 +10,7 @@ if (BUILD_TEST_CASES)
do_test(PBPTreeTest)
do_test(UnsortedPBPTreeTest)
# FPTree
do_test(PTreeTest)
do_test(FPTreeTest)
# PTable
do_test(VTableInfoTest ptable)
......
......@@ -97,8 +97,11 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
/* ------------------------------------------------------------------ */
SECTION("Looking up a key in a leaf node") {
auto node = q->btree1->newLeafNode();
for (auto i = 0; i < 10; i++) node->keys.get_rw()[i] = i + 1;
node->numKeys = 10;
for (auto i = 0; i < 10; i++) {
node->keys.get_rw()[i] = i + 1;
node->search.get_rw().data.b.set(i);
node->search.get_rw().data.fp[i] = q->btree1->fpHash(i + 1);
}
REQUIRE(q->btree1->lookupPositionInLeafNode(node, 1) == 0);
REQUIRE(q->btree1->lookupPositionInLeafNode(node, 10) == 9);
......@@ -367,22 +370,24 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
auto node2 = btree->newLeafNode();
for (auto i = 0; i < 4; i++) {
(node1->keys.get_rw())[i] = i;
(node1->values.get_rw())[i] = i + 100;
node1->keys.get_rw()[i] = i;
node1->values.get_rw()[i] = i + 100;
node1->search.get_rw().data.b.set(i);
node1->search.get_rw().data.fp[i] = btree->fpHash(i);
}
node1->numKeys = 4;
for (auto i = 0; i < 4; i++) {
(node2->keys.get_rw())[i] = i + 10;
(node2->values.get_rw())[i] = i + 200;
node2->keys.get_rw()[i] = i + 10;
node2->values.get_rw()[i] = i + 200;
node2->search.get_rw().data.b.set(i);
node2->search.get_rw().data.fp[i] = btree->fpHash(i + 10);
}
node2->numKeys = 4;
node1->nextLeaf = node2;
btree->mergeLeafNodes(node1, node2);
REQUIRE(node1->nextLeaf == nullptr);
REQUIRE(node1->numKeys == 8);
REQUIRE(node1->search.get_ro().data.b.count() == 8);
std::array<int, 8> expectedKeys{{0, 1, 2, 3, 10, 11, 12, 13}};
std::array<int, 8> expectedValues{{100, 101, 102, 103, 200, 201, 202, 203}};
......@@ -401,20 +406,22 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
auto node2 = btree->newLeafNode();
for (auto i = 0; i < 8; i++) {
(node1->keys.get_rw())[i] = i + 1;
(node1->values.get_rw())[i] = i * 100;
node1->keys.get_rw()[i] = i + 1;
node1->values.get_rw()[i] = i * 100;
node1->search.get_rw().data.b.set(i);
node1->search.get_rw().data.fp[i] = btree->fpHash(i+1);
}
node1->numKeys = 8;
for (auto i = 0; i < 4; i++) {
(node2->keys.get_rw())[i] = i + 11;
(node2->values.get_rw())[i] = i * 200;
node2->keys.get_rw()[i] = i + 11;
node2->values.get_rw()[i] = i * 200;
node2->search.get_rw().data.b.set(i);
node2->search.get_rw().data.fp[i] = btree->fpHash(i+11);
}
node2->numKeys = 4;
btree->balanceLeafNodes(node1, node2);
REQUIRE(node1->numKeys == 6);
REQUIRE(node2->numKeys == 6);
REQUIRE(node2->search.get_ro().data.b.count() == 6);
REQUIRE(node1->search.get_ro().data.b.count() == 6);
std::array<int, 6> expectedKeys1{{1, 2, 3, 4, 5, 6}};
std::array<int, 6> expectedValues1{{0, 100, 200, 300, 400, 500}};
......@@ -461,7 +468,7 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
btree->depth = 1;
btree->underflowAtLeafLevel(parent, 1, leaf2);
REQUIRE(leaf1->numKeys == 5);
REQUIRE(leaf1->search.get_ro().data.b.count() == 5);
REQUIRE(btree->rootNode.leaf == leaf1);
std::array<int, 5> expectedKeys{{1, 2, 3, 4, 5}};
......@@ -506,7 +513,7 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
btree->rootNode = parent;
btree->underflowAtLeafLevel(parent, 1, leaf2);
REQUIRE(leaf1->numKeys == 5);
REQUIRE(leaf1->search.get_ro().data.b.count() == 5);
REQUIRE(btree->rootNode.lowestbranch == parent);
REQUIRE(parent->numKeys == 1);
......@@ -536,8 +543,8 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
parent->children[1] = leaf2;
btree->underflowAtLeafLevel(parent, 1, leaf2);
REQUIRE(leaf1->numKeys == 3);
REQUIRE(leaf2->numKeys == 3);
REQUIRE(leaf1->search.get_ro().data.b.count() == 3);
REQUIRE(leaf2->search.get_ro().data.b.count() == 3);
std::array<int, 3> expectedKeys1{{1, 2, 3}};
std::array<int, 3> expectedValues1{{10, 20, 30}};
......@@ -652,23 +659,24 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
auto node = btree->newLeafNode();
for (auto i = 0; i < 9; i++) {
(node->keys.get_rw())[i] = (i + 1) * 2;
(node->values.get_rw())[i] = (i * 2) + 100;
node->keys.get_rw()[i] = (i + 1) * 2;
node->values.get_rw()[i] = (i * 2) + 100;
node->search.get_rw().data.b.set(i);
node->search.get_rw().data.fp[i] = btree->fpHash((i + 1) * 2);
}
node->numKeys = 9;
res = btree->insertInLeafNode(node, 5, 5000, &splitInfo);
REQUIRE(res == false);
REQUIRE(node->numKeys == 10);
REQUIRE(node->search.get_ro().data.b.count() == 10);
res = btree->insertInLeafNode(node, 1, 1, &splitInfo);
REQUIRE(res == false);
REQUIRE(node->numKeys == 11);
REQUIRE(node->search.get_ro().data.b.count() == 11);
res = btree->insertInLeafNode(node, 2, 1000, &splitInfo);
REQUIRE(res == false);
REQUIRE(node->numKeys == 11);
REQUIRE(node->search.get_ro().data.b.count() == 11);
std::array<int, 11> expectedKeys{{1, 2, 4, 5, 6, 8, 10, 12, 14, 16, 18}};
std::array<int, 11> expectedValues{
......@@ -699,15 +707,16 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
auto node = btree->newLeafNode();
for (auto i = 0; i < 9; i++) {
(node->keys.get_rw())[i] = (i + 1) * 2;
(node->values.get_rw())[i] = (i * 2) + 100;
node->keys.get_rw()[i] = (i + 1) * 2;
node->values.get_rw()[i] = (i * 2) + 100;
node->search.get_rw().data.b.set(i);
node->search.get_rw().data.fp[i] = btree->fpHash((i + 1) * 2);
}
node->numKeys = 9;
btree->insertInLeafNodeAtPosition(node, 2, 5, 5000);
REQUIRE(node->numKeys == 10);
btree->insertInLeafNodeAtPosition(node, 0, 1, 1);
REQUIRE(node->numKeys == 11);
btree->insertInLeafNodeAtPosition(node, 9, 5, 5000);
REQUIRE(node->search.get_ro().data.b.count() == 10);
btree->insertInLeafNodeAtPosition(node, 10, 1, 1);
REQUIRE(node->search.get_ro().data.b.count() == 11);
std::array<int, 11> expectedKeys{{1, 2, 4, 5, 6, 8, 10, 12, 14, 16, 18}};
std::array<int, 11> expectedValues{
......@@ -749,7 +758,7 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
btree->depth = 2;
btree->insertInLowestBranchNode(node, 11, 112, &splitInfo);
REQUIRE(leaf2->numKeys == 3);
REQUIRE(leaf2->search.get_ro().data.b.count() == 3);
}
......@@ -779,7 +788,7 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
btree->depth = 2;
btree->insertInLowestBranchNode(node, 12, 112, &splitInfo);
REQUIRE(leaf2->numKeys == 2);
REQUIRE(leaf2->search.get_ro().data.b.count() == 2);
REQUIRE(node->numKeys == 2);
std::array<int, 2> expectedKeys{{10, 12}};
......@@ -788,8 +797,12 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
std::array<int, 3> expectedKeys2{{12, 13, 14}};
auto leaf3 = node->children[2];
std::vector<int> actualKeys{};
for(auto i = 0u; i < 4; i++)
if(leaf3->search.get_ro().data.b.test(i))
actualKeys.push_back(leaf3->keys.get_ro()[i]);
REQUIRE(std::equal(std::begin(expectedKeys2), std::end(expectedKeys2),
std::begin(leaf3->keys.get_ro())));
std::begin(actualKeys)));
}
......@@ -800,22 +813,25 @@ TEST_CASE("Finding the leaf node containing a key", "[FPTree]") {
auto node = btree->newLeafNode();
for (auto i = 0; i < 9; i++) {
(node->keys.get_rw())[i] = i + 1;
(node->values.get_rw())[i] = i + 100;
node->keys.get_rw()[i] = i + 1;
node->values.get_rw()[i] = i + 100;
node->search.get_rw().data.b.set(i);
node->search.get_rw().data.fp[i] = btree->fpHash(i + 1);
}
node->numKeys = 9;
REQUIRE(btree->eraseFromLeafNode(node, 5) == true);
REQUIRE(node->numKeys == 8);
REQUIRE(node->search.get_ro().data.b.count() == 8);
REQUIRE(btree->eraseFromLeafNode(node, 15) == false);
REQUIRE(node->numKeys == 8);
REQUIRE(node->search.get_ro().data.b.count() == 8);
std::array<int, 8> expectedKeys{{1, 2, 3, 4, 6, 7, 8, 9 }};
std::array<int, 8> expectedValues{
{100, 101, 102, 103, 105, 106, 107, 108 }};
std::vector<int> nodevecK {std::begin(node->keys.get_ro()), std::begin(node->keys.get_ro())+8};
std::vector<int> nodevecV {std::begin(node->values.get_ro()), std::begin(node->values.get_ro())+8};
std::vector<int> nodevecK {std::begin(node->keys.get_ro()), std::begin(node->keys.get_ro())+9};
nodevecK.erase(nodevecK.begin() + 4);
std::vector<int> nodevecV {std::begin(node->values.get_ro()), std::begin(node->values.get_ro())+9};
nodevecV.erase(nodevecV.begin() + 4);
std::sort(std::begin(nodevecK), std::end(nodevecK));
std::sort(std::begin(nodevecV), std::end(nodevecV));
......
This diff is collapsed.
......@@ -671,8 +671,7 @@ TEST_CASE("Finding the leaf node containing a key", "[PBPTree]") {
REQUIRE(node->numKeys == 11);
std::array<int, 11> expectedKeys{{1, 2, 4, 5, 6, 8, 10, 12, 14, 16, 18}};
std::array<int, 11> expectedValues{
{1, 102, 104, 106, 108, 110, 112, 114, 116, 1000, 5000}};
std::array<int, 11> expectedValues{{1, 102, 104, 106, 108, 110, 112, 114, 116, 1000, 5000}};
std::vector<int> nodevecK {std::begin(node->keys.get_ro()), std::begin(node->keys.get_ro())+11};
std::vector<int> nodevecV {std::begin(node->values.get_ro()), std::begin(node->values.get_ro())+11};
......@@ -779,14 +778,14 @@ TEST_CASE("Finding the leaf node containing a key", "[PBPTree]") {
btree->depth = 2;
btree->insertInBranchNode(node, 1, 12, 112, &splitInfo);
REQUIRE(leaf2->numKeys == 3);
REQUIRE(leaf2->numKeys == 2);
REQUIRE(node->numKeys == 2);
std::array<int, 2> expectedKeys{{10, 13}};
std::array<int, 2> expectedKeys{{10, 12}};
REQUIRE(std::equal(std::begin(expectedKeys), std::end(expectedKeys),
std::begin(node->keys.get_ro())));
std::array<int, 2> expectedKeys2{{13, 14}};
std::array<int, 3> expectedKeys2{{13, 14, 12}};
auto leaf3 = (node->children.get_ro())[2].leaf;
REQUIRE(std::equal(std::begin(expectedKeys2), std::end(expectedKeys2),
std::begin(leaf3->keys.get_ro())));
......
......@@ -20,73 +20,82 @@
#ifndef DBIS_ELEMENTOFRANKK_HPP
#define DBIS_ELEMENTOFRANKK_HPP
namespace dbis::pbptree {
namespace dbis {
class ElementOfRank {
private:
template <typename KeyType>
static void swap(KeyType *data, int p, int q) {
if (p == q) return;
KeyType merke = data[p];
data[p] = data[q];
data[q] = merke;
}
template <typename KeyType>
static KeyType elementOfRankBySorting(int m, KeyType *data, int length, int start) {
int k = m - 1;
class ElementOfRankK {
private:
template<typename KeyType, std::size_t L>
static void insertionSort(std::array<KeyType, L> &data, int left, int right) {
for (auto i = left + 1; i <= right; i++) {
auto temp = data[i];
auto j = i - 1;
while (data[j] > temp && j >= left) {
data[j+1] = data[j];
j--;
}
data[j+1] = temp;
}
}
template<typename KeyType, std::size_t L>
static void bubbleSort(std::array<KeyType, L> &data, int left, int right) {
bool swapped = true;
while (swapped == true) {
while (swapped) {
swapped = false;
for (int i = start; i < start + length-1; i++) {
for (int i = left; i < right; i++) {
if (data[i] > data[i + 1]) {
swap(data, i, i + 1);
std::swap(data[i], data[i + 1]);
swapped = true;
}
}
}
return data[k];
}
}
template <typename KeyType, std::size_t L>
static KeyType elementOfRankKBySorting(int k, std::array<KeyType, L> &data, int start, int length) {
insertionSort(data, start, start + length - 1);
return data[k-1];
}
template <typename KeyType>
static KeyType findPivot(KeyType *data, int length, int start) {
int parts = length / 5;
KeyType medians[parts];
if (parts <= 1) { return elementOfRankBySorting(start + (length + 1) / 2, data, length, start); }
template <typename KeyType, std::size_t L>
static KeyType findPivot(std::array<KeyType, L> &data, int start) {
constexpr auto parts = L / 5;
if (parts <= 1) { return elementOfRankKBySorting(start + (L + 1) / 2 - 1, data, L, start); }
std::array<KeyType, parts> medians;
for (int i = 0; i < parts; i++) {
medians[i] = elementOfRankBySorting(3, data, 5, start + i * 5);
medians[i] = elementOfRankKBySorting(2, data, 5, start + i * 5);
}
return findPivot(medians, parts, 0);
return findPivot(medians, 0);
}
public:
template <typename KeyType>
static KeyType elementOfRank(int m, KeyType *data, int length, int start) {
int k = m - 1;
public:
template <typename KeyType, std::size_t L>
static KeyType elementOfRankK(int k, std::array<KeyType, L> &data, int start, int length) {
if (length <= 15) {
return elementOfRankBySorting(m, data, length, start);
return elementOfRankKBySorting(k, data, start, length);
}
int p = start, q = start;
KeyType pivot = findPivot(data, length, start);
for (int i = start; i < start + length; i++) {
auto p = start, q = start;
KeyType pivot = findPivot(data, start);
for (auto i = start; i < start + length; i++) {
if (data[i] < pivot) {
swap(data, i, q);
swap(data, p, q);
q++;
p++;
std::swap(data[i], data[q]);
std::swap(data[p], data[q]);
q++; p++;
}
if (data[i] == pivot) {
swap(data, i, q);
std::swap(data[i], data[q]);
q++;
}
}
if (k < p) {return elementOfRank(m, data, p - start, start); }
if (k >= q) {return elementOfRank(m, data, length + start - q - 1, q); }
if (k < p) { return elementOfRankK(k, data, start, p - start); }
if (k >= q) { return elementOfRankK(k, data, q, length + start - q - 1); }
return pivot;
}
}; /* end class */
} /* end namespace dbis::pbptree */
}; /* end class */
} /* end namespace dbis */
#endif /* DBIS_ELEMENTOFRANKK_HPP */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment