- Refactor GetLowestRightBorderNodeWithLessThanKChildrenOrNull into algorithm.h

- Started shrinking leaves
This commit is contained in:
Sebastian Messmer 2015-02-21 01:58:23 +01:00
parent e784e054d5
commit f5c48db10b
6 changed files with 81 additions and 56 deletions

View File

@ -4,7 +4,7 @@
#include "../datanodestore/DataInnerNode.h" #include "../datanodestore/DataInnerNode.h"
#include "../datanodestore/DataLeafNode.h" #include "../datanodestore/DataLeafNode.h"
#include "impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" #include "impl/algorithms.h"
#include "messmer/cpp-utils/pointer.h" #include "messmer/cpp-utils/pointer.h"
@ -32,8 +32,16 @@ DataTree::DataTree(DataNodeStore *nodeStore, unique_ptr<DataNode> rootNode)
DataTree::~DataTree() { DataTree::~DataTree() {
} }
void DataTree::removeLastDataLeaf() {
DataInnerNode *rootNode = dynamic_cast<DataInnerNode*>(_rootNode.get());
assert(rootNode != nullptr);
auto deletePosOrNull = algorithms::GetLowestRightBorderNodeWithMoreThanOneChildOrNull(_nodeStore, _rootNode.get());
//TODO ...
}
unique_ptr<DataLeafNode> DataTree::addDataLeaf() { unique_ptr<DataLeafNode> DataTree::addDataLeaf() {
auto insertPosOrNull = impl::GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(_nodeStore, _rootNode.get()); auto insertPosOrNull = algorithms::GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(_nodeStore, _rootNode.get());
if (insertPosOrNull) { if (insertPosOrNull) {
return addDataLeafAt(insertPosOrNull.get()); return addDataLeafAt(insertPosOrNull.get());
} else { } else {

View File

@ -3,8 +3,8 @@
#define BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREE_H_ #define BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREE_H_
#include <memory> #include <memory>
#include "messmer/cpp-utils/macros.h" #include <messmer/cpp-utils/macros.h>
#include "impl/GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" #include <messmer/cpp-utils/optional_ownership_ptr.h>
namespace blockstore { namespace blockstore {
class Key; class Key;
@ -25,6 +25,7 @@ public:
virtual ~DataTree(); virtual ~DataTree();
std::unique_ptr<datanodestore::DataLeafNode> addDataLeaf(); std::unique_ptr<datanodestore::DataLeafNode> addDataLeaf();
void removeLastDataLeaf();
const blockstore::Key &key() const; const blockstore::Key &key() const;

View File

@ -1,29 +0,0 @@
#pragma once
#ifndef TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_GETLOWESTRIGHTBORDERNODEWITHLESSTHANKCHILDRENORNULL_H_
#define TEST_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_GETLOWESTRIGHTBORDERNODEWITHLESSTHANKCHILDRENORNULL_H_
#include "messmer/cpp-utils/optional_ownership_ptr.h"
namespace blobstore {
namespace onblocks {
namespace datanodestore {
class DataNode;
class DataInnerNode;
class DataNodeStore;
}
namespace datatreestore {
namespace impl {
class GetLowestRightBorderNodeWithLessThanKChildrenOrNull {
public:
//Returns the lowest right border node with less than k children (not considering leaves).
//Returns nullptr, if all right border nodes have k children (the tree is full)
static cpputils::optional_ownership_ptr<datanodestore::DataInnerNode> run(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode);
};
}
}
}
}
#endif

View File

@ -1,24 +1,23 @@
#include "GetLowestRightBorderNodeWithLessThanKChildrenOrNull.h" #include "algorithms.h"
#include <messmer/cpp-utils/pointer.h>
#include <messmer/blockstore/utils/Key.h>
#include "../../datanodestore/DataInnerNode.h" #include "../../datanodestore/DataInnerNode.h"
#include "../../datanodestore/DataLeafNode.h"
#include "../../datanodestore/DataNodeStore.h" #include "../../datanodestore/DataNodeStore.h"
#include "messmer/cpp-utils/pointer.h" using std::function;
using std::unique_ptr; using std::unique_ptr;
using cpputils::dynamic_pointer_move;
using cpputils::optional_ownership_ptr; using cpputils::optional_ownership_ptr;
using blobstore::onblocks::datanodestore::DataNode; using cpputils::dynamic_pointer_move;
using blobstore::onblocks::datanodestore::DataInnerNode; using blobstore::onblocks::datanodestore::DataInnerNode;
using blobstore::onblocks::datanodestore::DataLeafNode; using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataNodeStore; using blobstore::onblocks::datanodestore::DataNodeStore;
using blockstore::Key; using blockstore::Key;
namespace blobstore { namespace blobstore {
namespace onblocks { namespace onblocks {
namespace datatreestore { namespace datatreestore {
namespace impl { namespace algorithms {
unique_ptr<DataInnerNode> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) { unique_ptr<DataInnerNode> getLastChildAsInnerNode(DataNodeStore *nodeStore, const DataInnerNode &node) {
Key key = node.LastChild()->key(); Key key = node.LastChild()->key();
@ -26,12 +25,14 @@ unique_ptr<DataInnerNode> getLastChildAsInnerNode(DataNodeStore *nodeStore, cons
return dynamic_pointer_move<DataInnerNode>(lastChild); return dynamic_pointer_move<DataInnerNode>(lastChild);
} }
optional_ownership_ptr<DataInnerNode> GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(DataNodeStore *nodeStore, DataNode *rootNode) { //Returns the lowest right border node meeting the condition specified (exclusive the leaf).
//Returns nullptr, if no inner right border node meets the condition.
optional_ownership_ptr<DataInnerNode> GetLowestInnerRightBorderNodeWithConditionOrNull(DataNodeStore *nodeStore, datanodestore::DataNode *rootNode, function<bool(const DataInnerNode &)> condition) {
optional_ownership_ptr<DataInnerNode> currentNode = cpputils::WithoutOwnership(dynamic_cast<DataInnerNode*>(rootNode)); optional_ownership_ptr<DataInnerNode> currentNode = cpputils::WithoutOwnership(dynamic_cast<DataInnerNode*>(rootNode));
optional_ownership_ptr<DataInnerNode> result = cpputils::null<DataInnerNode>(); optional_ownership_ptr<DataInnerNode> result = cpputils::null<DataInnerNode>();
for (unsigned int i=0; i < rootNode->depth(); ++i) { for (unsigned int i=0; i < rootNode->depth(); ++i) {
auto lastChild = getLastChildAsInnerNode(nodeStore, *currentNode); auto lastChild = getLastChildAsInnerNode(nodeStore, *currentNode);
if (currentNode->numChildren() < DataInnerNode::MAX_STORED_CHILDREN) { if (condition(*currentNode)) {
result = std::move(currentNode); result = std::move(currentNode);
} }
currentNode = std::move(lastChild); currentNode = std::move(lastChild);
@ -40,6 +41,19 @@ optional_ownership_ptr<DataInnerNode> GetLowestRightBorderNodeWithLessThanKChild
return result; return result;
} }
optional_ownership_ptr<DataInnerNode> GetLowestRightBorderNodeWithMoreThanOneChildOrNull(DataNodeStore *nodeStore, DataNode *rootNode) {
return GetLowestInnerRightBorderNodeWithConditionOrNull(nodeStore, rootNode, [] (const datanodestore::DataInnerNode &node) {
return node.numChildren() > 1;
});
}
//TODO Test this
optional_ownership_ptr<datanodestore::DataInnerNode> GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode) {
return GetLowestInnerRightBorderNodeWithConditionOrNull(nodeStore, rootNode, [] (const datanodestore::DataInnerNode &node) {
return node.numChildren() < DataInnerNode::MAX_STORED_CHILDREN;
});
}
} }
} }
} }

View File

@ -0,0 +1,30 @@
#pragma once
#ifndef MESSMER_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_ALGORITHMS_H_
#define MESSMER_BLOBSTORE_IMPLEMENTATIONS_ONBLOCKS_DATATREESTORE_IMPL_ALGORITHMS_H_
#include <messmer/cpp-utils/optional_ownership_ptr.h>
namespace blobstore {
namespace onblocks {
namespace datanodestore{
class DataNode;
class DataInnerNode;
class DataNodeStore;
}
namespace datatreestore {
namespace algorithms {
//Returns the lowest right border node with at least two children.
//Returns nullptr, if all right border nodes have only one child (since the root is a right border node, this means that the whole tree has exactly one leaf)
cpputils::optional_ownership_ptr<datanodestore::DataInnerNode> GetLowestRightBorderNodeWithMoreThanOneChildOrNull(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode);
//Returns the lowest right border node with less than k children (not considering leaves).
//Returns nullptr, if all right border nodes have k children (the tree is full)
cpputils::optional_ownership_ptr<datanodestore::DataInnerNode> GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(datanodestore::DataNodeStore *nodeStore, datanodestore::DataNode *rootNode);
}
}
}
}
#endif

View File

@ -5,6 +5,7 @@
#include "../../../../../implementations/onblocks/datanodestore/DataLeafNode.h" #include "../../../../../implementations/onblocks/datanodestore/DataLeafNode.h"
#include "../../../../../implementations/onblocks/datanodestore/DataInnerNode.h" #include "../../../../../implementations/onblocks/datanodestore/DataInnerNode.h"
#include "messmer/blockstore/implementations/testfake/FakeBlockStore.h" #include "messmer/blockstore/implementations/testfake/FakeBlockStore.h"
#include "../../../../../implementations/onblocks/datatreestore/impl/algorithms.h"
using ::testing::Test; using ::testing::Test;
using std::unique_ptr; using std::unique_ptr;
@ -17,9 +18,9 @@ using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataInnerNode; using blobstore::onblocks::datanodestore::DataInnerNode;
using blockstore::testfake::FakeBlockStore; using blockstore::testfake::FakeBlockStore;
using blockstore::Key; using blockstore::Key;
using blobstore::onblocks::datatreestore::impl::GetLowestRightBorderNodeWithLessThanKChildrenOrNull; using namespace blobstore::onblocks::datatreestore::algorithms;
class GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest: public DataTreeTest { class GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest: public DataTreeTest {
public: public:
struct TestData { struct TestData {
TestData(Key rootNode_, Key expectedResult_): rootNode(rootNode_), expectedResult(expectedResult_) {} TestData(Key rootNode_, Key expectedResult_): rootNode(rootNode_), expectedResult(expectedResult_) {}
@ -29,7 +30,7 @@ public:
void check(const TestData &testData) { void check(const TestData &testData) {
auto root = nodeStore.load(testData.rootNode); auto root = nodeStore.load(testData.rootNode);
auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); auto result = GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(&nodeStore, root.get());
EXPECT_EQ(testData.expectedResult, result->key()); EXPECT_EQ(testData.expectedResult, result->key());
} }
@ -68,40 +69,40 @@ public:
} }
}; };
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, Leaf) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, Leaf) {
auto leaf = nodeStore.createNewLeafNode(); auto leaf = nodeStore.createNewLeafNode();
auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, leaf.get()); auto result = GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(&nodeStore, leaf.get());
EXPECT_EQ(nullptr, result.get()); EXPECT_EQ(nullptr, result.get());
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, TwoRightBorderNodes) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, TwoRightBorderNodes) {
auto testData = CreateTwoRightBorderNodes(); auto testData = CreateTwoRightBorderNodes();
check(testData); check(testData);
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes) {
auto testData = CreateThreeRightBorderNodes(); auto testData = CreateThreeRightBorderNodes();
check(testData); check(testData);
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes_LastFull) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, ThreeRightBorderNodes_LastFull) {
auto testData = CreateThreeRightBorderNodes_LastFull(); auto testData = CreateThreeRightBorderNodes_LastFull();
check(testData); check(testData);
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, LargerTree) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, LargerTree) {
auto testData = CreateLargerTree(); auto testData = CreateLargerTree();
check(testData); check(testData);
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, FullTwoLevelTree) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, FullTwoLevelTree) {
auto root = nodeStore.load(CreateFullTwoLevelTree()); auto root = nodeStore.load(CreateFullTwoLevelTree());
auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); auto result = GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(&nodeStore, root.get());
EXPECT_EQ(nullptr, result.get()); EXPECT_EQ(nullptr, result.get());
} }
TEST_F(GetLowestRightBorderNodeWithLessThanKChildrenOrNullTest, FullThreeLevelTree) { TEST_F(GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNullTest, FullThreeLevelTree) {
auto root = nodeStore.load(CreateFullThreeLevelTree()); auto root = nodeStore.load(CreateFullThreeLevelTree());
auto result = GetLowestRightBorderNodeWithLessThanKChildrenOrNull::run(&nodeStore, root.get()); auto result = GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(&nodeStore, root.get());
EXPECT_EQ(nullptr, result.get()); EXPECT_EQ(nullptr, result.get());
} }