From 13a9e774c65fe2ec04e0fe499bb57248d41790f3 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Wed, 23 May 2012 19:18:59 -0700 Subject: [PATCH] Rather than working around using SHAMap::hasItem so much, let's just make it efficient. --- src/SHAMap.cpp | 52 +++++++++++++++++++++++++++++++++++--------------- src/SHAMap.h | 1 + 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index 919b467805..9ccbb2981d 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -108,7 +108,6 @@ SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify) int branch = inNode->selectBranch(id); if (inNode->isEmptyBranch(branch)) return inNode; uint256 childHash = inNode->getChildHash(branch); - if (childHash.isZero()) return inNode; SHAMapTreeNode::pointer nextNode = getNode(inNode->getChildNodeID(branch), childHash, false); if (!nextNode) throw SHAMapException(MissingNode); @@ -150,6 +149,24 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has return node; } +SHAMapTreeNode* SHAMap::getNodePointer(const SHAMapNode& id, const uint256& hash) +{ // fast, but you do not hold a reference + boost::unordered_map::iterator it = mTNByID.find(id); + if (it != mTNByID.end()) + return &*it->second; + + SHAMapTreeNode::pointer node; + std::vector nodeData; + if (!fetchNode(hash, nodeData)) return NULL; + + node = boost::make_shared(id, nodeData, mSeq); + if (node->getNodeHash() != hash) throw SHAMapException(InvalidNode); + + if (!mTNByID.insert(std::make_pair(id, node)).second) + assert(false); + return &*node; +} + void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify) { // make sure the node is suitable for the intended operation (copy on write) assert(node->isValid()); @@ -259,7 +276,7 @@ void SHAMap::eraseChildren(SHAMapTreeNode::pointer node) for(int i=0; i<16; i++) if(!node->isEmptyBranch(i)) { - SHAMapTreeNode::pointer nextNode=getNode(node->getChildNodeID(i), node->getChildHash(i), false); + SHAMapTreeNode::pointer nextNode = getNode(node->getChildNodeID(i), node->getChildHash(i), false); if(erase) { returnNode(node, true); @@ -272,7 +289,7 @@ void SHAMap::eraseChildren(SHAMapTreeNode::pointer node) } } returnNode(node, true); - if(mTNByID.erase(*node)==0) + if(mTNByID.erase(*node) == 0) assert(false); return; } @@ -293,10 +310,10 @@ SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id) { // Get a pointer to the next item in the tree after a given item - item must be in tree boost::recursive_mutex::scoped_lock sl(mLock); - std::stack stack=getStack(id, true); + std::stack stack = getStack(id, true); while(!stack.empty()) { - SHAMapTreeNode::pointer node=stack.top(); + SHAMapTreeNode::pointer node = stack.top(); stack.pop(); if(node->isLeaf()) @@ -304,13 +321,13 @@ SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id) if(node->peekItem()->getTag()>id) return node->peekItem(); } - else for(int i=node->selectBranch(id)+1; i<16; i++) + else for(int i = node->selectBranch(id) + 1; i < 16; ++i) if(!node->isEmptyBranch(i)) { - node=getNode(node->getChildNodeID(i), node->getChildHash(i), false); - if(!node) throw SHAMapException(MissingNode); - SHAMapItem::pointer item=firstBelow(node); - if(!item) throw SHAMapException(MissingNode); + node = getNode(node->getChildNodeID(i), node->getChildHash(i), false); + if (!node) throw SHAMapException(MissingNode); + SHAMapItem::pointer item = firstBelow(node); + if (!item) throw SHAMapException(MissingNode); return item; } } @@ -358,11 +375,16 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id) bool SHAMap::hasItem(const uint256& id) { // does the tree have an item with this ID boost::recursive_mutex::scoped_lock sl(mLock); - SHAMapTreeNode::pointer leaf = walkTo(id, false); - if (!leaf) return false; - SHAMapItem::pointer item = leaf->peekItem(); - if (!item || item->getTag() != id) return false; - return true; + + SHAMapTreeNode* inNode = &*root; + while (!inNode->isLeaf()) + { + int branch = inNode->selectBranch(id); + if (inNode->isEmptyBranch(branch)) return false; + inNode = getNodePointer(inNode->getChildNodeID(branch), inNode->getChildHash(branch)); + if (!inNode) throw SHAMapException(MissingNode); + } + return inNode->getTag() == id; } bool SHAMap::delItem(const uint256& id) diff --git a/src/SHAMap.h b/src/SHAMap.h index 182a54a5ec..8d9a1c3804 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -244,6 +244,7 @@ protected: SHAMapTreeNode::pointer getNode(const SHAMapNode& id); SHAMapTreeNode::pointer getNode(const SHAMapNode& id, const uint256& hash, bool modify); + SHAMapTreeNode* getNodePointer(const SHAMapNode& id, const uint256& hash); SHAMapItem::pointer firstBelow(SHAMapTreeNode::pointer); SHAMapItem::pointer lastBelow(SHAMapTreeNode::pointer);