Improve code decreasing tree depth

This commit is contained in:
Sebastian Messmer 2016-07-15 16:23:00 +02:00
parent b1b90b8c3d
commit 582917c1f5
3 changed files with 23 additions and 6 deletions

View File

@ -10,6 +10,7 @@ using std::vector;
using boost::none; using boost::none;
using cpputils::Data; using cpputils::Data;
using cpputils::unique_ref; using cpputils::unique_ref;
using cpputils::dynamic_pointer_move;
using blobstore::onblocks::datanodestore::DataNodeStore; using blobstore::onblocks::datanodestore::DataNodeStore;
using blobstore::onblocks::datanodestore::DataNode; using blobstore::onblocks::datanodestore::DataNode;
using blobstore::onblocks::datanodestore::DataInnerNode; using blobstore::onblocks::datanodestore::DataInnerNode;
@ -196,16 +197,30 @@ namespace blobstore {
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) { unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildReplaceRootWithItsChild(unique_ref<DataNode> root) {
DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get()); DataInnerNode *inner = dynamic_cast<DataInnerNode*>(root.get());
if (inner != nullptr && inner->numChildren() == 1) { if (inner != nullptr && inner->numChildren() == 1) {
auto child = _nodeStore->load(inner->getChild(0)->key()); auto newRoot = _whileRootHasOnlyOneChildRemoveRootReturnChild(inner->getChild(0)->key());
ASSERT(child != none, "Couldn't load first child of root node"); auto result = _nodeStore->overwriteNodeWith(std::move(root), *newRoot);
auto newRoot = _nodeStore->overwriteNodeWith(std::move(root), **child); _nodeStore->remove(std::move(newRoot));
_nodeStore->remove(std::move(*child)); return result;
return _whileRootHasOnlyOneChildReplaceRootWithItsChild(std::move(newRoot));
} else { } else {
return root; return root;
} }
} }
unique_ref<DataNode> LeafTraverser::_whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::Key &key) {
auto current = _nodeStore->load(key);
ASSERT(current != none, "Node not found");
auto inner = dynamic_pointer_move<DataInnerNode>(*current);
if (inner == none) {
return std::move(*current);
} else if ((*inner)->numChildren() == 1) {
auto result = _whileRootHasOnlyOneChildRemoveRootReturnChild((*inner)->getChild(0)->key());
_nodeStore->remove(std::move(*inner));
return result;
} else {
return std::move(*inner);
}
}
} }
} }
} }

View File

@ -5,6 +5,7 @@
#include <cpp-utils/macros.h> #include <cpp-utils/macros.h>
#include <cpp-utils/pointer/unique_ref.h> #include <cpp-utils/pointer/unique_ref.h>
#include <cpp-utils/data/Data.h> #include <cpp-utils/data/Data.h>
#include <blockstore/utils/Key.h>
namespace blobstore { namespace blobstore {
namespace onblocks { namespace onblocks {
@ -50,6 +51,7 @@ namespace blobstore {
uint32_t _maxLeavesForTreeDepth(uint8_t depth) const; uint32_t _maxLeavesForTreeDepth(uint8_t depth) const;
std::function<cpputils::Data (uint32_t index)> _createMaxSizeLeaf() const; std::function<cpputils::Data (uint32_t index)> _createMaxSizeLeaf() const;
cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildReplaceRootWithItsChild(cpputils::unique_ref<datanodestore::DataNode> root); cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildReplaceRootWithItsChild(cpputils::unique_ref<datanodestore::DataNode> root);
cpputils::unique_ref<datanodestore::DataNode> _whileRootHasOnlyOneChildRemoveRootReturnChild(const blockstore::Key &key);
DISALLOW_COPY_AND_ASSIGN(LeafTraverser); DISALLOW_COPY_AND_ASSIGN(LeafTraverser);
}; };

View File

@ -464,6 +464,6 @@ TEST_F(DataTreeTest_Performance, ResizeNumBytes_DecreaseTreeDepth_2to0) {
EXPECT_EQ(5u, blockStore->loadedBlocks().size()); // load new last leaf (+inner node), load second inner node to remove its subtree, then 2x load first child of root to replace root with its child. EXPECT_EQ(5u, blockStore->loadedBlocks().size()); // load new last leaf (+inner node), load second inner node to remove its subtree, then 2x load first child of root to replace root with its child.
EXPECT_EQ(0u, blockStore->createdBlocks()); EXPECT_EQ(0u, blockStore->createdBlocks());
EXPECT_EQ(3u + maxChildrenPerInnerNode, blockStore->removedBlocks().size()); EXPECT_EQ(3u + maxChildrenPerInnerNode, blockStore->removedBlocks().size());
EXPECT_EQ(2u, blockStore->distinctWrittenBlocks().size()); // 2x rewrite root node to be a leaf EXPECT_EQ(2u, blockStore->distinctWrittenBlocks().size()); // remove children from inner node and rewrite root node to be a leaf
EXPECT_EQ(0u, blockStore->resizedBlocks().size()); EXPECT_EQ(0u, blockStore->resizedBlocks().size());
} }