2015-01-23 04:39:36 +01:00
|
|
|
#include "DataTree.h"
|
|
|
|
|
2015-02-17 00:40:34 +01:00
|
|
|
#include "../datanodestore/DataNodeStore.h"
|
|
|
|
#include "../datanodestore/DataInnerNode.h"
|
|
|
|
#include "../datanodestore/DataLeafNode.h"
|
2015-01-23 04:39:36 +01:00
|
|
|
|
2015-02-21 01:58:23 +01:00
|
|
|
#include "impl/algorithms.h"
|
2015-01-26 00:38:06 +01:00
|
|
|
|
2015-02-17 00:40:34 +01:00
|
|
|
#include "messmer/cpp-utils/pointer.h"
|
2015-01-23 04:39:36 +01:00
|
|
|
|
|
|
|
using blockstore::Key;
|
|
|
|
using blobstore::onblocks::datanodestore::DataNodeStore;
|
|
|
|
using blobstore::onblocks::datanodestore::DataNode;
|
|
|
|
using blobstore::onblocks::datanodestore::DataInnerNode;
|
|
|
|
using blobstore::onblocks::datanodestore::DataLeafNode;
|
|
|
|
|
|
|
|
using std::unique_ptr;
|
2015-01-23 18:32:26 +01:00
|
|
|
using std::dynamic_pointer_cast;
|
|
|
|
using std::function;
|
2015-01-23 04:39:36 +01:00
|
|
|
|
2015-02-17 00:40:34 +01:00
|
|
|
using cpputils::dynamic_pointer_move;
|
|
|
|
using cpputils::optional_ownership_ptr;
|
2015-01-23 04:39:36 +01:00
|
|
|
|
|
|
|
namespace blobstore {
|
|
|
|
namespace onblocks {
|
|
|
|
namespace datatreestore {
|
|
|
|
|
|
|
|
DataTree::DataTree(DataNodeStore *nodeStore, unique_ptr<DataNode> rootNode)
|
|
|
|
: _nodeStore(nodeStore), _rootNode(std::move(rootNode)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
DataTree::~DataTree() {
|
|
|
|
}
|
|
|
|
|
2015-02-21 01:58:23 +01:00
|
|
|
void DataTree::removeLastDataLeaf() {
|
2015-02-22 19:30:42 +01:00
|
|
|
auto deletePosOrNull = algorithms::GetLowestRightBorderNodeWithMoreThanOneChildOrNull(_nodeStore, _rootNode.get());
|
|
|
|
assert(deletePosOrNull.get() != nullptr); //TODO Correct exception (tree has only one leaf, can't shrink it)
|
|
|
|
|
|
|
|
deleteLastChildSubtree(deletePosOrNull.get());
|
|
|
|
|
|
|
|
ifRootHasOnlyOneChildReplaceRootWithItsChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataTree::ifRootHasOnlyOneChildReplaceRootWithItsChild() {
|
2015-02-21 01:58:23 +01:00
|
|
|
DataInnerNode *rootNode = dynamic_cast<DataInnerNode*>(_rootNode.get());
|
|
|
|
assert(rootNode != nullptr);
|
2015-02-22 19:30:42 +01:00
|
|
|
if (rootNode->numChildren() == 1) {
|
|
|
|
auto child = _nodeStore->load(rootNode->getChild(0)->key());
|
|
|
|
_rootNode = _nodeStore->overwriteNodeWith(std::move(_rootNode), *child);
|
|
|
|
_nodeStore->remove(std::move(child));
|
|
|
|
}
|
|
|
|
}
|
2015-02-21 01:58:23 +01:00
|
|
|
|
2015-02-22 19:30:42 +01:00
|
|
|
void DataTree::deleteLastChildSubtree(DataInnerNode *node) {
|
2015-02-24 23:11:20 +01:00
|
|
|
auto lastChild = _nodeStore->load(node->LastChild()->key());
|
|
|
|
_nodeStore->removeSubtree(std::move(lastChild));
|
2015-02-22 19:30:42 +01:00
|
|
|
node->removeLastChild();
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:32:26 +01:00
|
|
|
unique_ptr<DataLeafNode> DataTree::addDataLeaf() {
|
2015-02-21 01:58:23 +01:00
|
|
|
auto insertPosOrNull = algorithms::GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(_nodeStore, _rootNode.get());
|
2015-01-23 04:39:36 +01:00
|
|
|
if (insertPosOrNull) {
|
2015-01-23 18:32:26 +01:00
|
|
|
return addDataLeafAt(insertPosOrNull.get());
|
2015-01-23 04:39:36 +01:00
|
|
|
} else {
|
2015-01-23 18:32:26 +01:00
|
|
|
return addDataLeafToFullTree();
|
2015-01-23 04:39:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<DataLeafNode> DataTree::addDataLeafAt(DataInnerNode *insertPos) {
|
|
|
|
auto new_leaf = _nodeStore->createNewLeafNode();
|
2015-01-23 18:32:26 +01:00
|
|
|
auto chain = createChainOfInnerNodes(insertPos->depth()-1, new_leaf.get());
|
|
|
|
insertPos->addChild(*chain);
|
2015-01-23 04:39:36 +01:00
|
|
|
return new_leaf;
|
|
|
|
}
|
|
|
|
|
2015-01-23 18:32:26 +01:00
|
|
|
optional_ownership_ptr<DataNode> DataTree::createChainOfInnerNodes(unsigned int num, DataLeafNode *leaf) {
|
2015-02-17 00:40:34 +01:00
|
|
|
optional_ownership_ptr<DataNode> chain = cpputils::WithoutOwnership<DataNode>(leaf);
|
2015-01-23 18:32:26 +01:00
|
|
|
for(unsigned int i=0; i<num; ++i) {
|
|
|
|
auto newnode = _nodeStore->createNewInnerNode(*chain);
|
2015-02-17 00:40:34 +01:00
|
|
|
chain = cpputils::WithOwnership<DataNode>(std::move(newnode));
|
2015-01-23 04:39:36 +01:00
|
|
|
}
|
|
|
|
return chain;
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr<DataLeafNode> DataTree::addDataLeafToFullTree() {
|
2015-01-24 01:59:42 +01:00
|
|
|
auto copyOfOldRoot = _nodeStore->createNewNodeAsCopyFrom(*_rootNode);
|
2015-01-24 00:54:27 +01:00
|
|
|
auto newRootNode = DataNode::convertToNewInnerNode(std::move(_rootNode), *copyOfOldRoot);
|
|
|
|
auto newLeaf = addDataLeafAt(newRootNode.get());
|
|
|
|
_rootNode = std::move(newRootNode);
|
|
|
|
return newLeaf;
|
2015-01-23 04:39:36 +01:00
|
|
|
}
|
|
|
|
|
2015-01-27 00:54:25 +01:00
|
|
|
const Key &DataTree::key() const {
|
|
|
|
return _rootNode->key();
|
|
|
|
}
|
2015-01-23 04:39:36 +01:00
|
|
|
|
2015-01-28 01:02:32 +01:00
|
|
|
void DataTree::flush() const {
|
|
|
|
_rootNode->flush();
|
|
|
|
}
|
|
|
|
|
2015-02-24 22:44:10 +01:00
|
|
|
unique_ptr<DataNode> DataTree::releaseRootNode() {
|
|
|
|
return std::move(_rootNode);
|
|
|
|
}
|
|
|
|
|
2015-01-23 04:39:36 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|