When shrinking a tree, LeafTraverser takes care of decreasing tree depth, not DataTree anymore. This way, LeafTraverser is now responsible for increasing and decreasing depth as necessary.

This commit is contained in:
Sebastian Messmer 2016-07-14 12:55:54 +02:00
parent 35a4e42ba5
commit 0dbfdf3e2b
4 changed files with 17 additions and 15 deletions

View File

@ -46,17 +46,6 @@ DataTree::DataTree(DataNodeStore *nodeStore, unique_ref<DataNode> rootNode)
DataTree::~DataTree() {
}
void DataTree::whileRootHasOnlyOneChildReplaceRootWithItsChild() {
DataInnerNode *rootNode = dynamic_cast<DataInnerNode*>(_rootNode.get());
if (rootNode != nullptr && rootNode->numChildren() == 1) {
auto child = _nodeStore->load(rootNode->getChild(0)->key());
ASSERT(child != none, "Couldn't load first child of root node");
_rootNode = _nodeStore->overwriteNodeWith(std::move(_rootNode), **child);
_nodeStore->remove(std::move(*child));
whileRootHasOnlyOneChildReplaceRootWithItsChild();
}
}
const Key &DataTree::key() const {
return _rootNode->key();
}
@ -184,7 +173,6 @@ void DataTree::resizeNumBytes(uint64_t newNumBytes) {
};
_traverseLeaves(newNumLeaves - 1, newNumLeaves, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree);
whileRootHasOnlyOneChildReplaceRootWithItsChild();
_numLeavesCache = newNumLeaves;
ASSERT(newNumBytes == _numStoredBytes(), "We resized to the wrong number of bytes ("+std::to_string(numStoredBytes())+" instead of "+std::to_string(newNumBytes)+")");
}

View File

@ -50,8 +50,6 @@ private:
cpputils::unique_ref<datanodestore::DataNode> releaseRootNode();
friend class DataTreeStore;
void whileRootHasOnlyOneChildReplaceRootWithItsChild();
//TODO Use underscore for private methods
void _traverseLeaves(uint32_t beginIndex, uint32_t endIndex,
std::function<void (uint32_t index, datanodestore::DataLeafNode* leaf)> onExistingLeaf,

View File

@ -45,7 +45,9 @@ namespace blobstore {
auto newRoot = _increaseTreeDepth(std::move(root));
return traverseAndReturnRoot(std::move(newRoot), std::max(beginIndex, maxLeavesForDepth), endIndex, onExistingLeaf, onCreateLeaf, onBacktrackFromSubtree);
} else {
return std::move(root);
// Once we're done growing the tree and done with the traversal, we might have to decrease tree depth,
// because the callbacks could have deleted nodes (this happens for example when shrinking the tree using a traversal).
return whileRootHasOnlyOneChildReplaceRootWithItsChild(std::move(root));
}
}
@ -192,6 +194,19 @@ namespace blobstore {
};
}
unique_ref<DataNode> LeafTraverser::whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) {
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
if (inner != nullptr && inner->numChildren() == 1) {
auto child = _nodeStore->load(inner->getChild(0)->key());
ASSERT(child != none, "Couldn't load first child of root node");
auto newRoot = _nodeStore->overwriteNodeWith(std::move(root), **child);
_nodeStore->remove(std::move(*child));
return whileRootHasOnlyOneChildReplaceRootWithItsChild(std::move(newRoot));
} else {
return root;
}
}
}
}
}

View File

@ -44,6 +44,7 @@ namespace blobstore {
std::function<void (datanodestore::DataInnerNode *node)> onBacktrackFromSubtree);
uint32_t _maxLeavesForTreeDepth(uint8_t depth) const;
std::function<cpputils::Data (uint32_t index)> _createMaxSizeLeaf() const;
cpputils::unique_ref<datanodestore::DataNode> whileRootHasOnlyOneChildReplaceRootWithItsChild(cpputils::unique_ref<datanodestore::DataNode> root);
DISALLOW_COPY_AND_ASSIGN(LeafTraverser);
};