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

🐎 Optimized and restructured B+-Trees

parent f39fa127
......@@ -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/pmem0/test")
# Installation path (creates include and lib within this directory)
if(NOT PROJECT_INSTALL_DIR)
......@@ -40,6 +40,10 @@ if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
endif()
if(CMAKE_BUILD_TYPE EQUAL "Release")
# this disables asserts for release builds
add_definitions("-DNDEBUG")
endif()
# show used compiler
message("Using Compiler: ${CMAKE_CXX_COMPILER_ID}.")
......@@ -88,9 +92,9 @@ set(PROJECT_INCLUDE_DIR ${PROJECT_INSTALL_DIR}/include)
# Including Data Structures #
#############################
#
add_subdirectory(pbptree) # Persistent version of B⁺-Tree
add_subdirectory(fptree) # Remake of the FPTree
add_subdirectory(wbtree) # Remake of the wB+Tree
add_subdirectory(pbptrees) # Persistent versions of B⁺-Tree, contains also:
# - Remake of the FPTree
# - Remake of the wB+Tree
add_subdirectory(ptable) # BDCC-based analytical table structure
#########################
......
......@@ -21,7 +21,7 @@
#include <chrono>
#include <unistd.h>
#include <experimental/filesystem>
#include "PTable.hpp"
#include "ptable/PTable.hpp"
using pmem::obj::make_persistent;
using pmem::obj::p;
......@@ -89,7 +89,7 @@ const int hibit_pos(int n) noexcept {
template<size_t SIZE>
static inline VectorVector *createPointVector(VectorVector *v) {
if (SIZE >= 100) {
if constexpr (SIZE >= 100) {
createPointVector<SIZE / 10>(v);
v->emplace_back(Vector{SIZE, SIZE / 2});
}
......@@ -129,8 +129,8 @@ void insert (pool<root> &pop, const std::string &path, size_t entries) {
measures.push_back(diff);
}
auto avg = std::accumulate(measures.begin(), measures.end(), 0) / measures.size();
auto minmax = std::minmax_element(std::begin(measures), std::end(measures));
const auto avg = std::accumulate(measures.begin(), measures.end(), 0) / measures.size();
const auto minmax = std::minmax_element(std::begin(measures), std::end(measures));
LOG("\nInsert Statistics in µs: "
<< "\n\tAvg: \t" << avg
<< "\n\tMin: \t" << *minmax.first
......
......@@ -32,7 +32,7 @@
#include "benchmark/benchmark.h"
#include "PBPTree.hpp"
using namespace dbis::pbptree;
using namespace dbis::pbptrees;
using pmem::obj::delete_persistent;
using pmem::obj::make_persistent;
......@@ -45,11 +45,11 @@ using pmem::obj::transaction;
using MyTuple = std::tuple <int, int, double>;
using MyKey = unsigned long long;
constexpr auto TARGET_BRANCH_SIZE = 512;
constexpr auto TARGET_LEAF_SIZE = 512; //< 512B best performance
constexpr auto TARGET_LEAF_SIZE = 256; //< 512B best performance
constexpr auto TARGET_DEPTH = 1;
constexpr auto IS_HYBRID = false;
const std::string path = dbis::gPmemPath + "tree_bench.data";
constexpr auto POOL_SIZE = 1024 * 1024 * 1024 * 1ull; //< 1GB
constexpr auto IS_HYBRID = 0;
const std::string path = dbis::gPmemPath + "tree_benchSp.data";
constexpr auto POOL_SIZE = 1024 * 1024 * 1024 * 4ull; //< 1GB
constexpr auto LAYOUT = "Tree";
/* wBPTree pre-calculations */
......@@ -58,12 +58,12 @@ constexpr unsigned int getBranchKeyswBPTree() {
constexpr auto keys = getBranchKeyswBPTree<N-1>();
constexpr auto CL_h = keys + ((keys + 63) / 64) * 8;
constexpr auto CL = ((CL_h + 63) / 64) * 64;
constexpr auto SIZE = CL + keys * (sizeof(MyKey) + 16) + 16; //< CacheLine structure & n keys & n+1 children
return (SIZE <= TARGET_BRANCH_SIZE)? keys : ((TARGET_BRANCH_SIZE - CL - 16) / (sizeof(MyKey) + 16));
constexpr auto SIZE = CL + keys * (sizeof(MyKey) + 24) + 24; //< CacheLine structure & n keys & n+1 children
return (SIZE <= TARGET_BRANCH_SIZE)? keys : ((TARGET_BRANCH_SIZE - CL - 24) / (sizeof(MyKey) + 24));
}
template<>
constexpr unsigned int getBranchKeyswBPTree<1>() {
return ((TARGET_BRANCH_SIZE - 64 - 16) / (sizeof(MyKey) + 16));
return ((TARGET_BRANCH_SIZE - 64 - 24) / (sizeof(MyKey) + 24));
}
template<unsigned int N>
constexpr unsigned int getLeafKeyswBPTree() {
......@@ -91,7 +91,7 @@ constexpr unsigned int getLeafKeysPBPTree() {
/* FPTree pre-calculations */
template<unsigned int N>
constexpr unsigned int getBranchKeysFPTree() {
return ((TARGET_BRANCH_SIZE - 28) / (sizeof(MyKey) + 24)); //< lowest branch uses actually less space
return ((TARGET_BRANCH_SIZE - 28) / (sizeof(MyKey) + 24));
}
template<unsigned int N>
constexpr unsigned int getLeafKeysFPTree() {
......@@ -106,6 +106,33 @@ constexpr unsigned int getLeafKeysFPTree<1>() {
return ((TARGET_LEAF_SIZE - 64 - 32) / (sizeof(MyKey) + sizeof(MyTuple)));
}
/* BitPBPTree pre-calculations */
template<unsigned int N>
constexpr unsigned int getBranchKeysBitPBPTree() {
constexpr auto keys = getBranchKeysBitPBPTree<N-1>();
constexpr auto word = sizeof(unsigned long) * 8;
constexpr auto BM = (keys + word - 1) / word * 8;
constexpr auto SIZE = BM + keys * (sizeof(MyKey) + 24) + 24; //< bitmap structure & n keys & n+1 children
return (SIZE <= TARGET_BRANCH_SIZE)? keys : ((TARGET_BRANCH_SIZE - BM - 24) / (sizeof(MyKey) + 24));
}
template<>
constexpr unsigned int getBranchKeysBitPBPTree<1>() {
return ((TARGET_BRANCH_SIZE - sizeof(unsigned long) - 24) / (sizeof(MyKey) + 24));
}
template<unsigned int N>
constexpr unsigned int getLeafKeysBitPBPTree() {
constexpr auto keys = getLeafKeysBitPBPTree<N-1>();
constexpr auto word = sizeof(unsigned long) * 8;
constexpr auto BM = (keys + word - 1) / word * 8;
constexpr auto SIZE = BM + 32 + keys * (sizeof(MyKey) + sizeof(MyTuple));
return (SIZE <= TARGET_LEAF_SIZE)? keys : ((TARGET_LEAF_SIZE - BM - 32) / (sizeof(MyKey) + sizeof(MyTuple)));
}
template<>
constexpr unsigned int getLeafKeysBitPBPTree<1>() {
return ((TARGET_LEAF_SIZE - sizeof(unsigned long) - 32) / (sizeof(MyKey) + sizeof(MyTuple)));
}
/* Power of function */
constexpr uint64_t ipow(uint64_t base, int exp, uint64_t result = 1) {
return exp < 1 ? result : ipow(base*base, exp/2, (exp % 2) ? result*base : result);
......@@ -115,7 +142,7 @@ constexpr uint64_t ipow(uint64_t base, int exp, uint64_t result = 1) {
constexpr auto LEAFKEYS = getLeafKeysPBPTree<5>(); ///< 5 iterations should be enough
constexpr auto BRANCHKEYS = getBranchKeysPBPTree<5>() & ~1; ///< make this one even
constexpr auto ELEMENTS = LEAFKEYS*ipow(BRANCHKEYS+1, TARGET_DEPTH);
constexpr auto KEYPOS = ELEMENTS/ELEMENTS;
constexpr auto KEYPOS = 1;
using TreeType = PBPTree<MyKey, MyTuple, BRANCHKEYS, LEAFKEYS>;
......@@ -149,7 +176,7 @@ class HybridWrapper {
return node.branch->children.get_ro()[pos];
}
inline void recover(const T &tree, Int2Type<true>) const {
inline void recover(T &tree, Int2Type<true>) const {
tree.recover();
}
inline void recover(const T &tree, Int2Type<false>) const {
......@@ -169,7 +196,7 @@ class HybridWrapper {
return getChildAt(node, pos, Int2Type<isHybrid>());
}
inline void recover(const T &tree) const {
inline void recover(T &tree) const {
recover(tree, Int2Type<isHybrid>());
}
};
......
......@@ -19,8 +19,8 @@
/* Get benchmarks on Tree */
static void BM_TreeGet(benchmark::State &state) {
std::cout << "BRANCHKEYS: " << BRANCHKEYS
<< "\nLEAFKEYS: " << LEAFKEYS
std::cout << "BRANCHKEYS: " << BRANCHKEYS << " - " << sizeof(TreeType::BranchNode)
<< "\nLEAFKEYS: " << LEAFKEYS << " - " << sizeof(TreeType::LeafNode)
<< "\n";
struct root {
persistent_ptr<TreeType> tree;
......@@ -49,11 +49,11 @@ static void BM_TreeGet(benchmark::State &state) {
auto leaf = node.leaf;
/* BENCHMARKING */
unsigned int p;
for (auto _ : state) {
benchmark::DoNotOptimize(
p = treeRef.lookupPositionInLeafNode(leaf, LEAFKEYS)
);
unsigned int p;
benchmark::DoNotOptimize(
p = treeRef.lookupPositionInLeafNode(leaf, KEYPOS)
);
}
//treeRef.printBranchNode(0, treeRef.rootNode.branch);
......@@ -64,5 +64,4 @@ static void BM_TreeGet(benchmark::State &state) {
std::experimental::filesystem::remove_all(path);
}
BENCHMARK(BM_TreeGet);
BENCHMARK_MAIN();
......@@ -66,7 +66,9 @@ static void BM_TreeInsert(benchmark::State &state) {
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
split = treeRef.insertInLeafNode(leaf, KEYPOS, reqTup, &splitInfo);
transaction::run(pop, [&] {
split = treeRef.insertInLeafNode(leaf, KEYPOS, reqTup, &splitInfo);
});
state.PauseTiming();
assert(split == false);
......@@ -99,6 +101,6 @@ void prepare(const persistent_ptr<TreeType> tree) {
switch (KEYPOS) {
case 1 /*first*/: insertLoop(2, LEAFKEYS); break;
case ELEMENTS /*last*/: insertLoop(1, LEAFKEYS-1);break;
case ELEMENTS/2 /*middle*/: {insertLoop(1, KEYPOS-1); insertLoop(KEYPOS+1, LEAFKEYS);}
case (ELEMENTS+1)/2 /*middle*/: {insertLoop(1, KEYPOS-1); insertLoop(KEYPOS+1, LEAFKEYS);}
}
}
......@@ -31,27 +31,27 @@ static void BM_TreeScan(benchmark::State &state) {
if (access(path.c_str(), F_OK) != 0) {
pop = pool<root>::create(path, LAYOUT, POOL_SIZE);
transaction::run(pop, [&] {
pop.root()->tree = make_persistent<TreeType>();
});
insert(pop.root()->tree);
pop.root()->tree = make_persistent<TreeType>();
insert(pop.root()->tree);
});
} else {
LOG("Warning: " << path << " already exists");
pop = pool<root>::open(path, LAYOUT);
hybridWrapper.recover(*pop.root()->tree);
transaction::run(pop, [&] {
hybridWrapper.recover(*pop.root()->tree);
});
}
auto tree = pop.root()->tree;
auto &treeRef = *tree;
auto node = treeRef.rootNode;
MyKey key;
/* BENCHMARKING */
for (auto _ : state) {
//benchmark::DoNotOptimize(
treeRef.scan([](const auto& k, const auto& v) {
const auto key = k;
});
//);
//auto p = treeRef.lookupPositionInLeafNode(leaf, 1);
treeRef.scan([&key](const auto& k, const auto& v) {
benchmark::DoNotOptimize(key = k);
});
}
//treeRef.printBranchNode(0, treeRef.rootNode.branch);
std::cout << "Elements:" << ELEMENTS << "\n";
......
......@@ -64,7 +64,9 @@ static void BM_TreeSplit(benchmark::State &state) {
dbis::PersistEmulation::getBytesWritten();
state.ResumeTiming();
treeRef.splitLeafNode(leaf, &splitInfo);
transaction::run(pop, [&] {
treeRef.splitLeafNode(leaf, &splitInfo);
});
state.PauseTiming();
//treeRef.printLeafNode(0, leaf);
......
project (fptree)
include_directories(${PROJECT_SOURCE_DIR})
get_property(I_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
${I_DIRS}
CACHE INTERNAL "TESTING: Include Directories" FORCE
)
set(PROJECT_INCLUDES_F ${PROJECT_INCLUDES_F}
${CMAKE_CURRENT_SOURCE_DIR}/PTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/FPTree.hpp
PARENT_SCOPE)
......@@ -12,7 +12,11 @@ set(TEST_INCLUDE_DIRS ${TEST_INCLUDE_DIRS}
################
#
set(PROJECT_INCLUDES_F ${PROJECT_INCLUDES_F}
${CMAKE_CURRENT_SOURCE_DIR}/BitPBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/PBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/UnsortedPBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/BitPBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/PTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/FPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/wBPTree.hpp
${CMAKE_CURRENT_SOURCE_DIR}/wHBPTree.hpp
PARENT_SCOPE)
Persistent B<sup>+</sup>-Trees
==============================
......@@ -30,9 +30,9 @@
#include <libpmemobj++/utils.hpp>
#include "config.h"
#include "utils/ElementOfRankK.hpp"
#include "utils/BitOperations.hpp"
namespace dbis::wbptree {
namespace dbis::pbptrees {
using pmem::obj::delete_persistent;
using pmem::obj::make_persistent;
......@@ -125,17 +125,15 @@ class wHBPTree {
std::array<uint8_t, E+1> slot; ///< slot array for indirection, first = num
std::bitset<E> b; ///< bitset for valid entries
unsigned int getFreeZero() const {
unsigned int idx = 0;
while (idx < E && b.test(idx)) ++idx;
return idx;
inline const auto getFreeZero() const {
return BitOperations::getFreeZero(b);
}
};
/**
* A structure for representing a leaf node of a B+ tree.
*/
struct LeafNode {
struct alignas(64) LeafNode {
/**
* Constructor for creating a new empty leaf node.
*/
......@@ -153,7 +151,7 @@ class wHBPTree {
/**
* A structure for representing an branch node (branch node) of a B+ tree.
*/
struct BranchNode {
struct alignas(64) BranchNode {
/**
* Constructor for creating a new empty branch node.
*/
......@@ -207,8 +205,8 @@ class wHBPTree {
Node rightChild; ///< the resulting rhs child node
};
unsigned int depth; ///< the depth of the tree, i.e. the number of levels (0 => rootNode is LeafNode)
Node rootNode; ///< pointer to the root node
unsigned int depth; ///< the depth of the tree, i.e. the number of levels (0 => rootNode is LeafNode)
Node rootNode; ///< pointer to the root node
pptr<LeafNode> leafList; ///< pointer to the most left leaf node. Necessary for recovery
public:
......@@ -297,34 +295,31 @@ class wHBPTree {
* @param val the value that is associated with the key
*/
void insert(const KeyType &key, const ValueType &val) {
auto pop = pmem::obj::pool_by_vptr(this);
transaction::run(pop, [&] {
SplitInfo splitInfo;
SplitInfo splitInfo;
bool wasSplit = false;
if (depth == 0) {
/// the root node is a leaf node
auto n = rootNode.leaf;
wasSplit = insertInLeafNode(n, key, val, &splitInfo);
} else {
/// the root node is a branch node
auto n = rootNode.branch;
wasSplit = insertInBranchNode(n, depth, key, val, &splitInfo);
}
if (wasSplit) {
/* we had an overflow in the node and therefore the node is split */
const auto root = newBranchNode();
auto &rootRef = *root;
rootRef.keys[0] = splitInfo.key;
rootRef.children[0] = splitInfo.leftChild;
rootRef.children[N] = splitInfo.rightChild;
rootRef.search.slot[1] = 0;
rootRef.search.b.set(0);
rootRef.search.slot[0] = 1;
rootNode.branch = root;
++depth;
}
});
bool wasSplit = false;
if (depth == 0) {
/// the root node is a leaf node
auto n = rootNode.leaf;
wasSplit = insertInLeafNode(n, key, val, &splitInfo);
} else {
/// the root node is a branch node
auto n = rootNode.branch;
wasSplit = insertInBranchNode(n, depth, key, val, &splitInfo);
}
if (wasSplit) {
/* we had an overflow in the node and therefore the node is split */
const auto root = newBranchNode();
auto &rootRef = *root;
rootRef.keys[0] = splitInfo.key;
rootRef.children[0] = splitInfo.leftChild;
rootRef.children[N] = splitInfo.rightChild;
rootRef.search.slot[1] = 0;
rootRef.search.b.set(0);
rootRef.search.slot[0] = 1;
rootNode.branch = root;
++depth;
}
}
/**
......@@ -358,8 +353,6 @@ class wHBPTree {
*/
bool erase(const KeyType &key) {
bool deleted = false;
auto pop = pmem::obj::pool_by_vptr(this);
transaction::run(pop, [&] {
if (depth == 0) {
/* special case: the root node is a leaf node and there is no need to
* handle underflow */
......@@ -371,7 +364,6 @@ class wHBPTree {
assert(node != nullptr);
deleted = eraseFromBranchNode(node, depth, key);
}
});
return deleted;
}
/**
......@@ -430,14 +422,14 @@ class wHBPTree {
/// we traverse to the leftmost leaf node
auto node = rootNode;
auto d = depth;
while ( d-- > 0) node = node.branch->children[0];
while (d-- > 0) node = node.branch->children[0];
auto leaf = node.leaf;
while (leaf != nullptr) {
const auto &leafRef = *leaf;
/// for each key-value pair call func
const auto &bits = leafRef.search.get_ro().b;
for (auto i = 0u; i < M; i++) {
if (!leafRef.search.get_ro().b.test(i)) continue;
if (!bits.test(i)) continue;
const auto &key = leafRef.keys.get_ro()[i];
const auto &val = leafRef.values.get_ro()[i];
func(key, val);
......@@ -462,8 +454,9 @@ class wHBPTree {
while (!higherThanMax && leaf != nullptr) {
const auto &leafRef = *leaf;
/// for each key-value pair within the range call func
const auto &bits = leafRef.search.get_ro().b;
for (auto i = 0u; i < M; i++) {
if (!leafRef.search.get_ro().b.test(i)) continue;
if (!bits.test(i)) continue;
auto &key = leafRef.keys.get_ro()[i];
if (key < minKey) continue;
if (key > maxKey) { higherThanMax = true; continue; }
......@@ -509,7 +502,7 @@ class wHBPTree {
/// move all entries behind this position to a new sibling node
pptr<LeafNode> sibling = newLeafNode();
auto &sibRef = *sibling;
auto &sibRef = *sibling;
auto &sibSlots = sibRef.search.get_rw().slot;
sibSlots[0] = slotArray[0] - middle;
for (auto i = 1u; i < sibSlots[0] + 1; i++) {
......@@ -1351,6 +1344,6 @@ class wHBPTree {
}
}; /* end class wHBPTree */
} /* namespace dbis::wbptree */
} /* namespace dbis::pbptrees */
#endif /* DBIS_wHBPTree_hpp_ */
......@@ -24,7 +24,7 @@
#include "BitPBPTree.hpp"
using namespace dbis::pbptree;
using namespace dbis::pbptrees;
using pmem::obj::delete_persistent_atomic;
using pmem::obj::pool;
......@@ -93,7 +93,7 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
/* -------------------------------------------------------------------------------------------- */
SECTION("Looking up a key in a leaf node") {
auto &btree = *rootRef.btree10;
const auto node = btree.newLeafNode();
auto node = btree.newLeafNode();
auto &nodeRef = *node;
for (auto i = 0; i < 10; i++) {
nodeRef.keys.get_rw()[i] = i + 1;
......@@ -346,7 +346,7 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
btree.underflowAtBranchLevel(innerNodes[0], 0, innerNodes[1]);
REQUIRE(node1Ref.bits.get_ro().count() == 1);
REQUIRE((node1Ref.keys.get_ro())[btree.findMinKeyInNode(innerNodes[0])] == 9);
REQUIRE((node1Ref.keys.get_ro())[dbis::findMinKeyAtPNode(innerNodes[0], node1Ref.bits.get_ro())] == 9);
REQUIRE(node2Ref.bits.get_ro().count() == 2);
REQUIRE(node3Ref.bits.get_ro().count() == 2);
......@@ -498,8 +498,8 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
SECTION("Handling of underflow at a leaf node by merge and replace the root node") {
auto &btree = *rootRef.btree6;
const auto leaf1 = btree.newLeafNode();
const auto leaf2 = btree.newLeafNode();
auto leaf1 = btree.newLeafNode();
auto leaf2 = btree.newLeafNode();
auto &leaf1Ref = *leaf1;
auto &leaf2Ref = *leaf2;
leaf1Ref.nextLeaf = leaf2;
......@@ -517,12 +517,12 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
parentRef.keys.get_rw()[0] = 4;
parentRef.children.get_rw()[0] = leaf1;
parentRef.children.get_rw()[1] = leaf2;
parentRef.children.get_rw()[6] = leaf2;
parentRef.bits.get_rw().set(0);
btree.rootNode = parent;
btree.depth = 1;
btree.underflowAtLeafLevel(parent, 1, leaf2);
btree.underflowAtLeafLevel(parent, 6, leaf2);
REQUIRE(leaf1Ref.bits.get_ro().count() == 5);
REQUIRE(btree.rootNode.leaf == leaf1);
......@@ -540,7 +540,7 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
auto &btree = *rootRef.btree6;
const auto leaf1 = btree.newLeafNode();
const auto leaf2 = btree.newLeafNode();
auto leaf2 = btree.newLeafNode();
const auto leaf3 = btree.newLeafNode();
auto &leaf1Ref = *leaf1;
auto &leaf2Ref = *leaf2;
......@@ -573,6 +573,8 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
btree.underflowAtLeafLevel(parent, 1, leaf2);
REQUIRE(leaf1Ref.bits.get_ro().count() == 5);
REQUIRE(leaf2 == nullptr);
REQUIRE(leaf3Ref.bits.get_ro().count() == 3);
REQUIRE(btree.rootNode.branch == parent);
REQUIRE(parentRef.bits.get_ro().count() == 1);
}
......@@ -582,7 +584,7 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
auto &btree = *rootRef.btree6;
const auto leaf1 = btree.newLeafNode();
const auto leaf2 = btree.newLeafNode();
auto leaf2 = btree.newLeafNode();
auto &leaf1Ref = *leaf1;
auto &leaf2Ref = *leaf2;
leaf1Ref.nextLeaf = leaf2;
......@@ -784,9 +786,9 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
nodeRef.bits.get_rw().set(i);
}
btree.insertInLeafNodeAtFreePosition(node, 5, 5000);
btree.insertInLeafNodeAtPosition(node, 9, 5, 5000);
REQUIRE(nodeRef.bits.get_ro().count() == 10);
btree.insertInLeafNodeAtFreePosition(node, 1, 1);
btree.insertInLeafNodeAtPosition(node, 10, 1, 1);
REQUIRE(nodeRef.bits.get_ro().count() == 11);
std::array<int, 11> expectedKeys{{1, 2, 4, 5, 6, 8, 10, 12, 14, 16, 18}};
......@@ -841,10 +843,8 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
auto &btree = *rootRef.btree4;
PBPTreeType4::SplitInfo splitInfo;
const auto leaf1 = btree.newLeafNode();
const auto leaf2 = btree.newLeafNode();
auto leaf2 = btree.newLeafNode();
const auto node = btree.newBranchNode();
auto &leaf1Ref = *leaf1;
auto &leaf2Ref = *leaf2;
auto &nodeRef = *node;
btree.insertInLeafNode(leaf1, 1, 10, &splitInfo);
......@@ -862,18 +862,19 @@ TEST_CASE("Finding the leaf node containing a key", "[BitPBPTree]") {
nodeRef.bits.get_rw().set(0);
btree.rootNode = node;
btree.depth = 2;
btree.depth = 1;
btree.insertInBranchNode(node, 1, 12, 112, &splitInfo);
REQUIRE(leaf2Ref.bits.get_ro().count() == 2);
REQUIRE(nodeRef.bits.get_ro().count() == 2);
btree.insertInBranchNode(node, 1, 12, 120, &splitInfo);
REQUIRE(btree.rootNode.branch->bits.get_ro().count() == 2);
leaf2 = btree.findLeafNode(10);