diff --git a/SHAMap.cpp b/SHAMap.cpp index a9d3af94ef..16c3e8e706 100644 --- a/SHAMap.cpp +++ b/SHAMap.cpp @@ -91,41 +91,49 @@ SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& nodeID) : SHAMapNode(nodeID), m ; } -void SHAMapLeafNode::updateHash(void) +bool SHAMapLeafNode::hasItem(const uint256& item) const { -} - -bool SHAMapLeafNode::hasHash(const uint256& hash) const -{ - BOOST_FOREACH(const uint256& entry, mHashes) - if(entry==hash) return true; + BOOST_FOREACH(const SHAMapItem& nodeItem, mItems) + if(nodeItem==item) return true; return false; } -bool SHAMapLeafNode::addHash(const uint256& hash) -{ // The node will almost never have more than one hash in it - std::list::iterator it; - for(it=mHashes.begin(); it!=mHashes.end(); it++) +bool SHAMapLeafNode::addUpdateItem(const SHAMapItem& item) +{ // The node will almost never have more than one item in it + std::list::iterator it; + for(it=mItems.begin(); it!=mItems.end(); it++) { - if(*it==hash) return false; - if(*it>hash) break; + if(*it==item) + { + if(it->peekData()==item.peekData()) + return false; // no change + it->updateData(item.peekData()); + updateHash(); + return true; + } + if(*it>item) break; } - mHashes.insert(it, hash); + mItems.insert(it, item); updateHash(); return true; } -bool SHAMapLeafNode::delHash(const uint256& hash) +bool SHAMapLeafNode::delItem(const uint256& tag) { - std::list::iterator it; - for(it=mHashes.begin(); it!=mHashes.end(); it++) + std::list::iterator it; + for(it=mItems.begin(); it!=mItems.end(); it++) { - if(*it==hash) + if(*it==tag) { - mHashes.erase(it); + mItems.erase(it); updateHash(); return true; } } return false; } + +void SHAMapLeafNode::updateHash(void) +{ +} + diff --git a/SHAMap.h b/SHAMap.h index bfffd04588..27458b2db1 100644 --- a/SHAMap.h +++ b/SHAMap.h @@ -5,6 +5,7 @@ #include #include +#include #include "uint256.h" #include "ScopedLock.h" @@ -17,7 +18,7 @@ class SHAMap; class SHAMapNode -{ // Identified a node in a SHA256 hash +{ // Identifies a node in a SHA256 hash private: static uint256 smMasks[11]; // AND with hash to get node id @@ -32,17 +33,17 @@ public: SHAMapNode(int depth, const uint256 &hash); int getDepth() { return mDepth; } - const uint256 &getNodeID(); + const uint256 &getNodeID() { return mNodeID; } bool isRoot() const { return mDepth==0; } bool isLeaf() const { return mDepth==leafDepth; } bool isInner() const { return !isRoot() && !isLeaf(); } virtual bool IsPopulated(void) const { return false; } + SHAMapNode getParentNodeID() { return SHAMapNode(mDepth-1, mNodeID); } SHAMapNode getChildNodeID(int m); - int selectBranch(const uint256 &hash); - + bool operator<(const SHAMapNode &) const; bool operator>(const SHAMapNode &) const; bool operator==(const SHAMapNode &) const; @@ -55,6 +56,40 @@ public: }; +class SHAMapItem : public boost::enable_shared_from_this +{ // an item stored in a SHAMap +public: + typedef boost::shared_ptr pointer; + +private: + uint256 mTag; + std::vector mData; + +public: + SHAMapItem(const uint256 &tag, const std::vector& data); + SHAMapItem(const std::vector& data); // tag by hash + + const uint256& getTag(void) const { return mTag; } + std::vector getData(void) const { return mData; } + const std::vector& peekData(void) const { return mData; } + + void updateData(const std::vector &data) { mData=data; } + + bool operator<(const SHAMapItem& i) const { return mTag(const SHAMapItem& i) const { return mTag>i.mTag; } + bool operator==(const SHAMapItem& i) const { return mTag==i.mTag; } + bool operator!=(const SHAMapItem& i) const { return mTag!=i.mTag; } + bool operator<=(const SHAMapItem& i) const { return mTag<=i.mTag; } + bool operator>=(const SHAMapItem& i) const { return mTag>=i.mTag; } + bool operator<(const uint256& i) const { return mTag(const uint256& i) const { return mTag>i; } + bool operator==(const uint256& i) const { return mTag==i; } + bool operator!=(const uint256& i) const { return mTag!=i; } + bool operator<=(const uint256& i) const { return mTag<=i; } + bool operator>=(const uint256& i) const { return mTag>=i; } +}; + + class SHAMapLeafNode : public SHAMapNode { friend class SHAMap; @@ -64,13 +99,14 @@ public: private: uint256 mHash; - std::list mHashes; + std::list mItems; void updateHash(); protected: - bool addHash(const uint256 &hash); - bool delHash(const uint256 &hash); + bool addUpdateItem(const SHAMapItem&); + bool delItem(const SHAMapItem& i) { delItem(i.getTag()); } + bool delItem(const uint256 &tag); public: SHAMapLeafNode(const SHAMapNode& nodeID); @@ -78,10 +114,12 @@ public: virtual bool IsPopulated(void) const { return true; } const uint256& GetNodeHash() const { return mHash; } - bool isEmpty() const { return mHashes.empty(); } - int getHashCount() const { return mHashes.size(); } - const uint256& GetHash(int m) const; - bool hasHash(const uint256 &hash) const; + bool isEmpty() const { return mItems.empty(); } + int getItemCount() const { return mItems.size(); } + const uint256& getHash(int m) const; + + bool hasItem(const uint256 &item) const; + SHAMapItem::pointer findItem(const uint256 &tag); }; @@ -104,7 +142,6 @@ protected: public: SHAMapInnerNode(int Depth, const uint256 &NodeID); - virtual bool isPopulated(void) const { return true; } const uint256& getNodeHash() const { return mHash; } const uint256& getChildHash(int m) const; @@ -119,7 +156,7 @@ public: typedef boost::shared_ptr pointer; private: - mutable boost::mutex mLock; + mutable boost::recursive_mutex mLock; std::map mLeafByID; std::map mInnerNodeByID; boost::bimap NodeHash; @@ -127,6 +164,7 @@ private: public: SHAMap(); + // hold the map stable across operations ScopedLock Lock() const { return ScopedLock(mLock); } // inner node access functions @@ -167,6 +205,8 @@ public: virtual bool fetchNode(const uint256 &hash, std::vector& rawNode); virtual bool writeNode(const uint256 &hash, const std::vector& rawNode); virtual bool haveObject(const uint256 &hash); + + static bool TestSHAMap(); }; #endif diff --git a/ScopedLock.h b/ScopedLock.h index 9b19d68bbf..bcfc419c18 100644 --- a/ScopedLock.h +++ b/ScopedLock.h @@ -1,7 +1,7 @@ #ifndef __SCOPEDLOCKHOLDER__ #define __SCOPEDLOCKHOLDER__ -#include "boost/thread/mutex.hpp" +#include "boost/thread/recursive_mutex.hpp" // This is a returnable lock holder. // I don't know why Boost doesn't provide a good way to do this. @@ -9,13 +9,13 @@ class ScopedLock { private: - boost::mutex *mMutex; // parent object has greater scope, so guaranteed valid + boost::recursive_mutex *mMutex; // parent object has greater scope, so guaranteed valid mutable bool mValid; ScopedLock(); // no implementation public: - ScopedLock(boost::mutex &mutex) : mMutex(&mutex), mValid(true) + ScopedLock(boost::recursive_mutex &mutex) : mMutex(&mutex), mValid(true) { mMutex->lock(); }