Make SHAMap::fetchNodeFromDB const

When fetchNodeFromDB discovers a missing node in the database it
must reset the ledger sequence to 0.  By treating this as a logically
const operation, even though not physically const, many other member
functions can be made const, including compare.
This commit is contained in:
Howard Hinnant
2015-02-25 12:10:16 -05:00
committed by Tom Ritchford
parent f56e37398c
commit c59633a588
4 changed files with 73 additions and 73 deletions

View File

@@ -118,7 +118,7 @@ public:
bool fetchRoot (uint256 const& hash, SHAMapSyncFilter * filter);
// normal hash access functions
bool hasItem (uint256 const& id);
bool hasItem (uint256 const& id) const;
bool delItem (uint256 const& id);
bool addItem (SHAMapItem const& i, bool isTransaction, bool hasMeta);
uint256 getHash () const;
@@ -128,26 +128,26 @@ public:
bool addGiveItem (std::shared_ptr<SHAMapItem> const&, bool isTransaction, bool hasMeta);
// save a copy if you only need a temporary
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id);
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id, uint256 & hash);
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id, SHAMapTreeNode::TNType & type);
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id) const;
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id, uint256 & hash) const;
std::shared_ptr<SHAMapItem> peekItem (uint256 const& id, SHAMapTreeNode::TNType & type) const;
// traverse functions
std::shared_ptr<SHAMapItem> peekFirstItem ();
std::shared_ptr<SHAMapItem> peekFirstItem (SHAMapTreeNode::TNType & type);
std::shared_ptr<SHAMapItem> peekLastItem ();
std::shared_ptr<SHAMapItem> peekNextItem (uint256 const& );
std::shared_ptr<SHAMapItem> peekNextItem (uint256 const& , SHAMapTreeNode::TNType & type);
std::shared_ptr<SHAMapItem> peekPrevItem (uint256 const& );
std::shared_ptr<SHAMapItem> peekFirstItem () const;
std::shared_ptr<SHAMapItem> peekFirstItem (SHAMapTreeNode::TNType & type) const;
std::shared_ptr<SHAMapItem> peekLastItem () const;
std::shared_ptr<SHAMapItem> peekNextItem (uint256 const& ) const;
std::shared_ptr<SHAMapItem> peekNextItem (uint256 const& , SHAMapTreeNode::TNType & type) const;
std::shared_ptr<SHAMapItem> peekPrevItem (uint256 const& ) const;
void visitNodes (std::function<bool (SHAMapTreeNode&)> const&);
void visitLeaves(std::function<void (std::shared_ptr<SHAMapItem> const&)> const&);
void visitNodes (std::function<bool (SHAMapTreeNode&)> const&) const;
void visitLeaves(std::function<void (std::shared_ptr<SHAMapItem> const&)> const&) const;
// comparison/sync functions
void getMissingNodes (std::vector<SHAMapNodeID>& nodeIDs, std::vector<uint256>& hashes, int max,
SHAMapSyncFilter * filter);
bool getNodeFat (SHAMapNodeID node, std::vector<SHAMapNodeID>& nodeIDs,
std::list<Blob >& rawNode, bool fatRoot, bool fatLeaves);
std::list<Blob >& rawNode, bool fatRoot, bool fatLeaves) const;
bool getRootNode (Serializer & s, SHANodeFormat format) const;
std::vector<uint256> getNeededHashes (int max, SHAMapSyncFilter * filter);
SHAMapAddNode addRootNode (uint256 const& hash, Blob const& rootNode, SHANodeFormat format,
@@ -167,18 +167,18 @@ public:
// caution: otherMap must be accessed only by this function
// return value: true=successfully completed, false=too different
bool compare (std::shared_ptr<SHAMap> const& otherMap,
Delta& differences, int maxCount); // HINNANT should be const
Delta& differences, int maxCount) const;
int flushDirty (NodeObjectType t, std::uint32_t seq);
void walkMap (std::vector<SHAMapMissingNode>& missingNodes, int maxMissing);
bool deepCompare (SHAMap & other);
void walkMap (std::vector<SHAMapMissingNode>& missingNodes, int maxMissing) const;
bool deepCompare (SHAMap & other) const;
typedef std::pair <uint256, Blob> fetchPackEntry_t;
void visitDifferences (SHAMap * have, std::function<bool (SHAMapTreeNode&)>);
void visitDifferences (SHAMap * have, std::function<bool (SHAMapTreeNode&)>) const;
void getFetchPack (SHAMap * have, bool includeLeaves, int max,
std::function<void (uint256 const&, const Blob&)>);
std::function<void (uint256 const&, const Blob&)>) const;
void setUnbacked ();
@@ -197,13 +197,13 @@ private:
void canonicalize (uint256 const& hash, std::shared_ptr<SHAMapTreeNode>&) const;
// database operations
std::shared_ptr<SHAMapTreeNode> fetchNodeFromDB (uint256 const& hash);
std::shared_ptr<SHAMapTreeNode> fetchNodeNT (uint256 const& hash);
std::shared_ptr<SHAMapTreeNode> fetchNodeFromDB (uint256 const& hash) const;
std::shared_ptr<SHAMapTreeNode> fetchNodeNT (uint256 const& hash) const;
std::shared_ptr<SHAMapTreeNode> fetchNodeNT (
SHAMapNodeID const& id,
uint256 const& hash,
SHAMapSyncFilter *filter);
std::shared_ptr<SHAMapTreeNode> fetchNode (uint256 const& hash);
SHAMapSyncFilter *filter) const;
std::shared_ptr<SHAMapTreeNode> fetchNode (uint256 const& hash) const;
std::shared_ptr<SHAMapTreeNode> checkFilter (uint256 const& hash, SHAMapNodeID const& id,
SHAMapSyncFilter* filter) const;
@@ -213,10 +213,10 @@ private:
/** Get the path from the root to the specified node */
SharedPtrNodeStack
getStack (uint256 const& id, bool include_nonmatching_leaf);
getStack (uint256 const& id, bool include_nonmatching_leaf) const;
/** Walk to the specified index, returning the node */
SHAMapTreeNode* walkToPointer (uint256 const& id);
SHAMapTreeNode* walkToPointer (uint256 const& id) const;
/** Unshare the node, allowing it to be modified */
void unshareNode (std::shared_ptr<SHAMapTreeNode>&, SHAMapNodeID const& nodeID);
@@ -228,15 +228,15 @@ private:
void writeNode (NodeObjectType t, std::uint32_t seq,
std::shared_ptr<SHAMapTreeNode>& node) const;
SHAMapTreeNode* firstBelow (SHAMapTreeNode*);
SHAMapTreeNode* lastBelow (SHAMapTreeNode*);
SHAMapTreeNode* firstBelow (SHAMapTreeNode*) const;
SHAMapTreeNode* lastBelow (SHAMapTreeNode*) const;
// Simple descent
// Get a child of the specified node
SHAMapTreeNode* descend (SHAMapTreeNode*, int branch);
SHAMapTreeNode* descendThrow (SHAMapTreeNode*, int branch);
std::shared_ptr<SHAMapTreeNode> descend (std::shared_ptr<SHAMapTreeNode> const&, int branch);
std::shared_ptr<SHAMapTreeNode> descendThrow (std::shared_ptr<SHAMapTreeNode> const&, int branch);
SHAMapTreeNode* descend (SHAMapTreeNode*, int branch) const;
SHAMapTreeNode* descendThrow (SHAMapTreeNode*, int branch) const;
std::shared_ptr<SHAMapTreeNode> descend (std::shared_ptr<SHAMapTreeNode> const&, int branch) const;
std::shared_ptr<SHAMapTreeNode> descendThrow (std::shared_ptr<SHAMapTreeNode> const&, int branch) const;
// Descend with filter
SHAMapTreeNode* descendAsync (SHAMapTreeNode* parent, int branch,
@@ -244,21 +244,21 @@ private:
std::pair <SHAMapTreeNode*, SHAMapNodeID>
descend (SHAMapTreeNode* parent, SHAMapNodeID const& parentID,
int branch, SHAMapSyncFilter* filter);
int branch, SHAMapSyncFilter* filter) const;
// Non-storing
// Does not hook the returned node to its parent
std::shared_ptr<SHAMapTreeNode> descendNoStore (std::shared_ptr<SHAMapTreeNode> const&, int branch);
std::shared_ptr<SHAMapTreeNode> descendNoStore (std::shared_ptr<SHAMapTreeNode> const&, int branch) const;
/** If there is only one leaf below this node, get its contents */
std::shared_ptr<SHAMapItem> onlyBelow (SHAMapTreeNode*);
std::shared_ptr<SHAMapItem> onlyBelow (SHAMapTreeNode*) const;
bool hasInnerNode (SHAMapNodeID const& nodeID, uint256 const& hash);
bool hasLeafNode (uint256 const& tag, uint256 const& hash);
bool hasInnerNode (SHAMapNodeID const& nodeID, uint256 const& hash) const;
bool hasLeafNode (uint256 const& tag, uint256 const& hash) const;
bool walkBranch (SHAMapTreeNode* node,
std::shared_ptr<SHAMapItem> const& otherMapItem, bool isFirstMap,
Delta & differences, int & maxCount);
Delta & differences, int & maxCount) const;
int walkSubTree (bool doWrite, NodeObjectType t, std::uint32_t seq);
};

View File

@@ -85,7 +85,7 @@ SHAMap::snapShot (bool isMutable) const
}
SHAMap::SharedPtrNodeStack
SHAMap::getStack (uint256 const& id, bool include_nonmatching_leaf)
SHAMap::getStack (uint256 const& id, bool include_nonmatching_leaf) const
{
// Walk the tree as far as possible to the specified identifier
// produce a stack of nodes along the way, with the terminal node at the top
@@ -154,7 +154,7 @@ SHAMap::dirtyUp (SharedPtrNodeStack& stack,
}
}
SHAMapTreeNode* SHAMap::walkToPointer (uint256 const& id)
SHAMapTreeNode* SHAMap::walkToPointer (uint256 const& id) const
{
SHAMapTreeNode* inNode = root_.get ();
SHAMapNodeID nodeID;
@@ -175,7 +175,7 @@ SHAMapTreeNode* SHAMap::walkToPointer (uint256 const& id)
}
std::shared_ptr<SHAMapTreeNode>
SHAMap::fetchNodeFromDB (uint256 const& hash)
SHAMap::fetchNodeFromDB (uint256 const& hash) const
{
std::shared_ptr<SHAMapTreeNode> node;
@@ -200,7 +200,7 @@ SHAMap::fetchNodeFromDB (uint256 const& hash)
else if (ledgerSeq_ != 0)
{
f_.missing_node(ledgerSeq_);
ledgerSeq_ = 0;
const_cast<std::uint32_t&>(ledgerSeq_) = 0;
}
}
@@ -235,7 +235,7 @@ std::shared_ptr<SHAMapTreeNode> SHAMap::checkFilter (
std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNodeNT(
SHAMapNodeID const& id,
uint256 const& hash,
SHAMapSyncFilter* filter)
SHAMapSyncFilter* filter) const
{
std::shared_ptr<SHAMapTreeNode> node = getCache (hash);
if (node)
@@ -257,7 +257,7 @@ std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNodeNT(
return node;
}
std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNodeNT (uint256 const& hash)
std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNodeNT (uint256 const& hash) const
{
std::shared_ptr<SHAMapTreeNode> node = getCache (hash);
@@ -268,7 +268,7 @@ std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNodeNT (uint256 const& hash)
}
// Throw if the node is missing
std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNode (uint256 const& hash)
std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNode (uint256 const& hash) const
{
std::shared_ptr<SHAMapTreeNode> node = fetchNodeNT (hash);
@@ -278,7 +278,7 @@ std::shared_ptr<SHAMapTreeNode> SHAMap::fetchNode (uint256 const& hash)
return node;
}
SHAMapTreeNode* SHAMap::descendThrow (SHAMapTreeNode* parent, int branch)
SHAMapTreeNode* SHAMap::descendThrow (SHAMapTreeNode* parent, int branch) const
{
SHAMapTreeNode* ret = descend (parent, branch);
@@ -289,7 +289,7 @@ SHAMapTreeNode* SHAMap::descendThrow (SHAMapTreeNode* parent, int branch)
}
std::shared_ptr<SHAMapTreeNode>
SHAMap::descendThrow (std::shared_ptr<SHAMapTreeNode> const& parent, int branch)
SHAMap::descendThrow (std::shared_ptr<SHAMapTreeNode> const& parent, int branch) const
{
std::shared_ptr<SHAMapTreeNode> ret = descend (parent, branch);
@@ -299,7 +299,7 @@ SHAMap::descendThrow (std::shared_ptr<SHAMapTreeNode> const& parent, int branch)
return ret;
}
SHAMapTreeNode* SHAMap::descend (SHAMapTreeNode* parent, int branch)
SHAMapTreeNode* SHAMap::descend (SHAMapTreeNode* parent, int branch) const
{
SHAMapTreeNode* ret = parent->getChildPointer (branch);
if (ret || !backed_)
@@ -314,7 +314,7 @@ SHAMapTreeNode* SHAMap::descend (SHAMapTreeNode* parent, int branch)
}
std::shared_ptr<SHAMapTreeNode>
SHAMap::descend (std::shared_ptr<SHAMapTreeNode> const& parent, int branch)
SHAMap::descend (std::shared_ptr<SHAMapTreeNode> const& parent, int branch) const
{
std::shared_ptr<SHAMapTreeNode> node = parent->getChild (branch);
if (node || !backed_)
@@ -331,7 +331,7 @@ SHAMap::descend (std::shared_ptr<SHAMapTreeNode> const& parent, int branch)
// Gets the node that would be hooked to this branch,
// but doesn't hook it up.
std::shared_ptr<SHAMapTreeNode>
SHAMap::descendNoStore (std::shared_ptr<SHAMapTreeNode> const& parent, int branch)
SHAMap::descendNoStore (std::shared_ptr<SHAMapTreeNode> const& parent, int branch) const
{
std::shared_ptr<SHAMapTreeNode> ret = parent->getChild (branch);
if (!ret && backed_)
@@ -341,7 +341,7 @@ SHAMap::descendNoStore (std::shared_ptr<SHAMapTreeNode> const& parent, int branc
std::pair <SHAMapTreeNode*, SHAMapNodeID>
SHAMap::descend (SHAMapTreeNode * parent, SHAMapNodeID const& parentID,
int branch, SHAMapSyncFilter * filter)
int branch, SHAMapSyncFilter * filter) const
{
assert (parent->isInner ());
assert ((branch >= 0) && (branch < 16));
@@ -427,7 +427,7 @@ SHAMap::unshareNode (std::shared_ptr<SHAMapTreeNode>& node, SHAMapNodeID const&
}
SHAMapTreeNode*
SHAMap::firstBelow (SHAMapTreeNode* node)
SHAMap::firstBelow (SHAMapTreeNode* node) const
{
// Return the first item below this node
do
@@ -455,7 +455,7 @@ SHAMap::firstBelow (SHAMapTreeNode* node)
}
SHAMapTreeNode*
SHAMap::lastBelow (SHAMapTreeNode* node)
SHAMap::lastBelow (SHAMapTreeNode* node) const
{
do
{
@@ -480,7 +480,7 @@ SHAMap::lastBelow (SHAMapTreeNode* node)
}
std::shared_ptr<SHAMapItem>
SHAMap::onlyBelow (SHAMapTreeNode* node)
SHAMap::onlyBelow (SHAMapTreeNode* node) const
{
// If there is only one item below this node, return it
@@ -516,7 +516,7 @@ SHAMap::onlyBelow (SHAMapTreeNode* node)
static const std::shared_ptr<SHAMapItem> no_item;
std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem ()
std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem () const
{
SHAMapTreeNode* node = firstBelow (root_.get ());
@@ -526,7 +526,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem ()
return node->peekItem ();
}
std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem (SHAMapTreeNode::TNType& type)
std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem (SHAMapTreeNode::TNType& type) const
{
SHAMapTreeNode* node = firstBelow (root_.get ());
@@ -537,7 +537,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekFirstItem (SHAMapTreeNode::TNType& type)
return node->peekItem ();
}
std::shared_ptr<SHAMapItem> SHAMap::peekLastItem ()
std::shared_ptr<SHAMapItem> SHAMap::peekLastItem () const
{
SHAMapTreeNode* node = lastBelow (root_.get ());
@@ -547,13 +547,13 @@ std::shared_ptr<SHAMapItem> SHAMap::peekLastItem ()
return node->peekItem ();
}
std::shared_ptr<SHAMapItem> SHAMap::peekNextItem (uint256 const& id)
std::shared_ptr<SHAMapItem> SHAMap::peekNextItem (uint256 const& id) const
{
SHAMapTreeNode::TNType type;
return peekNextItem (id, type);
}
std::shared_ptr<SHAMapItem> SHAMap::peekNextItem (uint256 const& id, SHAMapTreeNode::TNType& type)
std::shared_ptr<SHAMapItem> SHAMap::peekNextItem (uint256 const& id, SHAMapTreeNode::TNType& type) const
{
// Get a pointer to the next item in the tree after a given item - item need not be in tree
@@ -596,7 +596,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekNextItem (uint256 const& id, SHAMapTreeN
}
// Get a pointer to the previous item in the tree after a given item - item need not be in tree
std::shared_ptr<SHAMapItem> SHAMap::peekPrevItem (uint256 const& id)
std::shared_ptr<SHAMapItem> SHAMap::peekPrevItem (uint256 const& id) const
{
auto stack = getStack (id, true);
@@ -629,7 +629,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekPrevItem (uint256 const& id)
return no_item;
}
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id)
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id) const
{
SHAMapTreeNode* leaf = walkToPointer (id);
@@ -639,7 +639,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id)
return leaf->peekItem ();
}
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, SHAMapTreeNode::TNType& type)
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, SHAMapTreeNode::TNType& type) const
{
SHAMapTreeNode* leaf = walkToPointer (id);
@@ -650,7 +650,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, SHAMapTreeNode:
return leaf->peekItem ();
}
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, uint256& hash)
std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, uint256& hash) const
{
SHAMapTreeNode* leaf = walkToPointer (id);
@@ -662,7 +662,7 @@ std::shared_ptr<SHAMapItem> SHAMap::peekItem (uint256 const& id, uint256& hash)
}
bool SHAMap::hasItem (uint256 const& id)
bool SHAMap::hasItem (uint256 const& id) const
{
// does the tree have an item with this ID
SHAMapTreeNode* leaf = walkToPointer (id);

View File

@@ -32,7 +32,7 @@ namespace ripple {
bool SHAMap::walkBranch (SHAMapTreeNode* node,
std::shared_ptr<SHAMapItem> const& otherMapItem, bool isFirstMap,
Delta& differences, int& maxCount)
Delta& differences, int& maxCount) const
{
// Walk a branch of a SHAMap that's matched by an empty branch or single item in the other map
std::stack <SHAMapTreeNode*, std::vector<SHAMapTreeNode*>> nodeStack;
@@ -114,7 +114,7 @@ bool SHAMap::walkBranch (SHAMapTreeNode* node,
bool
SHAMap::compare (std::shared_ptr<SHAMap> const& otherMap,
Delta& differences, int maxCount)
Delta& differences, int maxCount) const
{
// compare two hash trees, add up to maxCount differences to the difference table
// return value: true=complete table of differences given, false=too many differences
@@ -219,7 +219,7 @@ SHAMap::compare (std::shared_ptr<SHAMap> const& otherMap,
return true;
}
void SHAMap::walkMap (std::vector<SHAMapMissingNode>& missingNodes, int maxMissing)
void SHAMap::walkMap (std::vector<SHAMapMissingNode>& missingNodes, int maxMissing) const
{
std::stack <std::shared_ptr<SHAMapTreeNode>,
std::vector <std::shared_ptr<SHAMapTreeNode>>> nodeStack;

View File

@@ -39,13 +39,13 @@ static bool visitLeavesHelper (
return false;
}
void SHAMap::visitLeaves (std::function<void (std::shared_ptr<SHAMapItem> const& item)> const& leafFunction)
void SHAMap::visitLeaves (std::function<void (std::shared_ptr<SHAMapItem> const& item)> const& leafFunction) const
{
visitNodes (std::bind (visitLeavesHelper,
std::cref (leafFunction), std::placeholders::_1));
}
void SHAMap::visitNodes(std::function<bool (SHAMapTreeNode&)> const& function)
void SHAMap::visitNodes(std::function<bool (SHAMapTreeNode&)> const& function) const
{
// Visit every node in a SHAMap
assert (root_->isValid ());
@@ -284,7 +284,7 @@ std::vector<uint256> SHAMap::getNeededHashes (int max, SHAMapSyncFilter* filter)
}
bool SHAMap::getNodeFat (SHAMapNodeID wanted, std::vector<SHAMapNodeID>& nodeIDs,
std::list<Blob >& rawNodes, bool fatRoot, bool fatLeaves)
std::list<Blob >& rawNodes, bool fatRoot, bool fatLeaves) const
{
// Gets a node and some of its children
@@ -540,7 +540,7 @@ SHAMap::addKnownNode (const SHAMapNodeID& node, Blob const& rawNode,
return SHAMapAddNode::duplicate ();
}
bool SHAMap::deepCompare (SHAMap& other)
bool SHAMap::deepCompare (SHAMap& other) const
{
// Intended for debug/test only
std::stack <std::pair <SHAMapTreeNode*, SHAMapTreeNode*> > stack;
@@ -615,7 +615,7 @@ bool SHAMap::deepCompare (SHAMap& other)
*/
bool
SHAMap::hasInnerNode (SHAMapNodeID const& targetNodeID,
uint256 const& targetNodeHash)
uint256 const& targetNodeHash) const
{
SHAMapTreeNode* node = root_.get ();
SHAMapNodeID nodeID;
@@ -637,7 +637,7 @@ SHAMap::hasInnerNode (SHAMapNodeID const& targetNodeID,
/** Does this map have this leaf node?
*/
bool
SHAMap::hasLeafNode (uint256 const& tag, uint256 const& targetNodeHash)
SHAMap::hasLeafNode (uint256 const& tag, uint256 const& targetNodeHash) const
{
SHAMapTreeNode* node = root_.get ();
SHAMapNodeID nodeID;
@@ -673,7 +673,7 @@ Note: a caller should set includeLeaves to false for transaction trees.
There's no point in including the leaves of transaction trees.
*/
void SHAMap::getFetchPack (SHAMap* have, bool includeLeaves, int max,
std::function<void (uint256 const&, const Blob&)> func)
std::function<void (uint256 const&, const Blob&)> func) const
{
visitDifferences (have,
[includeLeaves, &max, &func] (SHAMapTreeNode& smn) -> bool
@@ -691,7 +691,7 @@ void SHAMap::getFetchPack (SHAMap* have, bool includeLeaves, int max,
});
}
void SHAMap::visitDifferences (SHAMap* have, std::function <bool (SHAMapTreeNode&)> func)
void SHAMap::visitDifferences (SHAMap* have, std::function <bool (SHAMapTreeNode&)> func) const
{
// Visit every node in this SHAMap that is not present
// in the specified SHAMap