#include "DataTree.h" #include "../datanodestore/DataNodeStore.h" #include "../datanodestore/DataInnerNode.h" #include "../datanodestore/DataLeafNode.h" #include "impl/algorithms.h" #include "messmer/cpp-utils/pointer.h" 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; using std::dynamic_pointer_cast; using std::function; using cpputils::dynamic_pointer_move; using cpputils::optional_ownership_ptr; namespace blobstore { namespace onblocks { namespace datatreestore { DataTree::DataTree(DataNodeStore *nodeStore, unique_ptr rootNode) : _nodeStore(nodeStore), _rootNode(std::move(rootNode)) { } DataTree::~DataTree() { } void DataTree::removeLastDataLeaf() { 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() { DataInnerNode *rootNode = dynamic_cast(_rootNode.get()); assert(rootNode != nullptr); if (rootNode->numChildren() == 1) { auto child = _nodeStore->load(rootNode->getChild(0)->key()); _rootNode = _nodeStore->overwriteNodeWith(std::move(_rootNode), *child); _nodeStore->remove(std::move(child)); } } void DataTree::deleteLastChildSubtree(DataInnerNode *node) { deleteSubtree(node->LastChild()->key()); node->removeLastChild(); } void DataTree::deleteSubtree(const Key &key) { auto node = _nodeStore->load(key); deleteChildrenOf(*node); _nodeStore->remove(std::move(node)); } void DataTree::deleteChildrenOf(const DataNode &node) { const DataInnerNode *node_inner = dynamic_cast(&node); if (node_inner != nullptr) { deleteChildrenOf(*node_inner); } } void DataTree::deleteChildrenOf(const DataInnerNode &node) { for(int i = 0; i < node.numChildren(); ++i) { deleteSubtree(node.getChild(i)->key()); } } unique_ptr DataTree::addDataLeaf() { auto insertPosOrNull = algorithms::GetLowestInnerRightBorderNodeWithLessThanKChildrenOrNull(_nodeStore, _rootNode.get()); if (insertPosOrNull) { return addDataLeafAt(insertPosOrNull.get()); } else { return addDataLeafToFullTree(); } } unique_ptr DataTree::addDataLeafAt(DataInnerNode *insertPos) { auto new_leaf = _nodeStore->createNewLeafNode(); auto chain = createChainOfInnerNodes(insertPos->depth()-1, new_leaf.get()); insertPos->addChild(*chain); return new_leaf; } optional_ownership_ptr DataTree::createChainOfInnerNodes(unsigned int num, DataLeafNode *leaf) { optional_ownership_ptr chain = cpputils::WithoutOwnership(leaf); for(unsigned int i=0; icreateNewInnerNode(*chain); chain = cpputils::WithOwnership(std::move(newnode)); } return chain; } unique_ptr DataTree::addDataLeafToFullTree() { auto copyOfOldRoot = _nodeStore->createNewNodeAsCopyFrom(*_rootNode); auto newRootNode = DataNode::convertToNewInnerNode(std::move(_rootNode), *copyOfOldRoot); auto newLeaf = addDataLeafAt(newRootNode.get()); _rootNode = std::move(newRootNode); return newLeaf; } const Key &DataTree::key() const { return _rootNode->key(); } void DataTree::flush() const { _rootNode->flush(); } } } }