Normalize SHAMap visit functions

This commit is contained in:
Miguel Portilla
2017-07-13 11:11:54 -04:00
committed by Scott Schurr
parent 819ea46bf0
commit aeda2430cd
3 changed files with 101 additions and 78 deletions

View File

@@ -282,10 +282,10 @@ SHAMapStoreImp::copyNode (std::uint64_t& nodeCount,
if (! (++nodeCount % checkHealthInterval_)) if (! (++nodeCount % checkHealthInterval_))
{ {
if (health()) if (health())
return true; return false;
} }
return false; return true;
} }
void void

View File

@@ -177,10 +177,29 @@ public:
// traverse functions // traverse functions
const_iterator upper_bound(uint256 const& id) const; const_iterator upper_bound(uint256 const& id) const;
void visitNodes (std::function<bool (SHAMapAbstractNode&)> const&) const; /** Visit every node in this SHAMap
void
visitLeaves( @param function called with every node visited.
std::function<void(std::shared_ptr<SHAMapItem const> const&)> const&) const; If function returns false, visitNodes exits.
*/
void visitNodes (std::function<bool (
SHAMapAbstractNode&)> const& function) const;
/** Visit every node in this SHAMap that
is not present in the specified SHAMap
@param function called with every node visited.
If function returns false, visitDifferences exits.
*/
void visitDifferences(SHAMap const* have,
std::function<bool (SHAMapAbstractNode&)>) const;
/** Visit every leaf node in this SHAMap
@param function called with every non inner node visited.
*/
void visitLeaves(std::function<void (
std::shared_ptr<SHAMapItem const> const&)> const&) const;
// comparison/sync functions // comparison/sync functions
@@ -247,8 +266,6 @@ private:
using DeltaRef = std::pair<std::shared_ptr<SHAMapItem const> const&, using DeltaRef = std::pair<std::shared_ptr<SHAMapItem const> const&,
std::shared_ptr<SHAMapItem const> const&>; std::shared_ptr<SHAMapItem const> const&>;
void visitDifferences(SHAMap const* have, std::function<bool(SHAMapAbstractNode&)>) const;
// tree node cache operations // tree node cache operations
std::shared_ptr<SHAMapAbstractNode> getCache (SHAMapHash const& hash) const; std::shared_ptr<SHAMapAbstractNode> getCache (SHAMapHash const& hash) const;
void canonicalize (SHAMapHash const& hash, std::shared_ptr<SHAMapAbstractNode>&) const; void canonicalize (SHAMapHash const& hash, std::shared_ptr<SHAMapAbstractNode>&) const;

View File

@@ -25,19 +25,21 @@
namespace ripple { namespace ripple {
void void
SHAMap::visitLeaves( SHAMap::visitLeaves(std::function<void (
std::function<void(std::shared_ptr<SHAMapItem const> const& item)> const& leafFunction) const std::shared_ptr<SHAMapItem const> const& item)> const& leafFunction) const
{ {
visitNodes( visitNodes(
[&leafFunction](SHAMapAbstractNode& node) [&leafFunction](SHAMapAbstractNode& node)
{ {
if (!node.isInner()) if (! node.isInner())
leafFunction(static_cast<SHAMapTreeNode&>(node).peekItem()); leafFunction(static_cast<SHAMapTreeNode&>(node).peekItem());
return false; return true;
}); });
} }
void SHAMap::visitNodes(std::function<bool (SHAMapAbstractNode&)> const& function) const void
SHAMap::visitNodes(std::function<bool (
SHAMapAbstractNode&)> const& function) const
{ {
// Visit every node in a SHAMap // Visit every node in a SHAMap
assert (root_->isValid ()); assert (root_->isValid ());
@@ -64,7 +66,7 @@ void SHAMap::visitNodes(std::function<bool (SHAMapAbstractNode&)> const& functio
if (!node->isEmptyBranch (pos)) if (!node->isEmptyBranch (pos))
{ {
std::shared_ptr<SHAMapAbstractNode> child = descendNoStore (node, pos); std::shared_ptr<SHAMapAbstractNode> child = descendNoStore (node, pos);
if (function (*child)) if (! function (*child))
return; return;
if (child->isLeaf ()) if (child->isLeaf ())
@@ -100,6 +102,74 @@ void SHAMap::visitNodes(std::function<bool (SHAMapAbstractNode&)> const& functio
} }
} }
void
SHAMap::visitDifferences(SHAMap const* have,
std::function<bool (SHAMapAbstractNode&)> function) const
{
// Visit every node in this SHAMap that is not present
// in the specified SHAMap
assert (root_->isValid ());
if (! root_)
return;
if (root_->getNodeHash ().isZero ())
return;
if (have && (root_->getNodeHash () == have->root_->getNodeHash ()))
return;
if (root_->isLeaf ())
{
auto leaf = std::static_pointer_cast<SHAMapTreeNode>(root_);
if (! have || ! have->hasLeafNode(leaf->peekItem()->key(), leaf->getNodeHash()))
function(*root_);
return;
}
// contains unexplored non-matching inner node entries
using StackEntry = std::pair <SHAMapInnerNode*, SHAMapNodeID>;
std::stack <StackEntry, std::vector<StackEntry>> stack;
stack.push ({static_cast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID{}});
while (! stack.empty())
{
SHAMapInnerNode* node;
SHAMapNodeID nodeID;
std::tie (node, nodeID) = stack.top ();
stack.pop ();
// 1) Add this node to the pack
if (! function(*node))
return;
// 2) push non-matching child inner nodes
for (int i = 0; i < 16; ++i)
{
if (! node->isEmptyBranch (i))
{
auto const& childHash = node->getChildHash (i);
SHAMapNodeID childID = nodeID.getChildNodeID (i);
auto next = descendThrow(node, i);
if (next->isInner ())
{
if (! have || ! have->hasInnerNode(childID, childHash))
stack.push ({static_cast<SHAMapInnerNode*>(next), childID});
}
else if (! have || ! have->hasLeafNode(
static_cast<SHAMapTreeNode*>(next)->peekItem()->key(),
childHash))
{
if (! function(*next))
return;
}
}
}
}
}
// Starting at the position referred to by the specfied // Starting at the position referred to by the specfied
// StackEntry, process that node and its first resident // StackEntry, process that node and its first resident
// children, descending the SHAMap until we complete the // children, descending the SHAMap until we complete the
@@ -753,68 +823,4 @@ void SHAMap::getFetchPack (SHAMap const* have, bool includeLeaves, int max,
}); });
} }
void
SHAMap::visitDifferences(SHAMap const* have,
std::function<bool (SHAMapAbstractNode&)> func) const
{
// Visit every node in this SHAMap that is not present
// in the specified SHAMap
if (root_->getNodeHash ().isZero ())
return;
if (have && (root_->getNodeHash () == have->root_->getNodeHash ()))
return;
if (root_->isLeaf ())
{
auto leaf = std::static_pointer_cast<SHAMapTreeNode>(root_);
if (!have || !have->hasLeafNode(leaf->peekItem()->key(), leaf->getNodeHash()))
func (*root_);
return;
}
// contains unexplored non-matching inner node entries
using StackEntry = std::pair <SHAMapInnerNode*, SHAMapNodeID>;
std::stack <StackEntry, std::vector<StackEntry>> stack;
stack.push ({static_cast<SHAMapInnerNode*>(root_.get()), SHAMapNodeID{}});
while (!stack.empty())
{
SHAMapInnerNode* node;
SHAMapNodeID nodeID;
std::tie (node, nodeID) = stack.top ();
stack.pop ();
// 1) Add this node to the pack
if (!func (*node))
return;
// 2) push non-matching child inner nodes
for (int i = 0; i < 16; ++i)
{
if (!node->isEmptyBranch (i))
{
auto const& childHash = node->getChildHash (i);
SHAMapNodeID childID = nodeID.getChildNodeID (i);
auto next = descendThrow(node, i);
if (next->isInner ())
{
if (!have || !have->hasInnerNode(childID, childHash))
stack.push ({static_cast<SHAMapInnerNode*>(next), childID});
}
else if (!have || !have->hasLeafNode(
static_cast<SHAMapTreeNode*>(next)->peekItem()->key(),
childHash))
{
if (! func (*next))
return;
}
}
}
}
}
} // ripple } // ripple