Updates. Create a class to hold an item in a SHAMap, separating the tag from

the data (it's not always the hash of the data). Make ScopedLock's recursive.
This commit is contained in:
JoelKatz
2011-11-15 10:49:14 -08:00
parent 14988dec90
commit 55b2111fd5
3 changed files with 83 additions and 35 deletions

View File

@@ -91,41 +91,49 @@ SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& nodeID) : SHAMapNode(nodeID), m
; ;
} }
void SHAMapLeafNode::updateHash(void) bool SHAMapLeafNode::hasItem(const uint256& item) const
{ {
} BOOST_FOREACH(const SHAMapItem& nodeItem, mItems)
if(nodeItem==item) return true;
bool SHAMapLeafNode::hasHash(const uint256& hash) const
{
BOOST_FOREACH(const uint256& entry, mHashes)
if(entry==hash) return true;
return false; return false;
} }
bool SHAMapLeafNode::addHash(const uint256& hash) bool SHAMapLeafNode::addUpdateItem(const SHAMapItem& item)
{ // The node will almost never have more than one hash in it { // The node will almost never have more than one item in it
std::list<uint256>::iterator it; std::list<SHAMapItem>::iterator it;
for(it=mHashes.begin(); it!=mHashes.end(); it++) for(it=mItems.begin(); it!=mItems.end(); it++)
{ {
if(*it==hash) return false; if(*it==item)
if(*it>hash) break; {
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(); updateHash();
return true; return true;
} }
bool SHAMapLeafNode::delHash(const uint256& hash) bool SHAMapLeafNode::delItem(const uint256& tag)
{ {
std::list<uint256>::iterator it; std::list<SHAMapItem>::iterator it;
for(it=mHashes.begin(); it!=mHashes.end(); it++) for(it=mItems.begin(); it!=mItems.end(); it++)
{ {
if(*it==hash) if(*it==tag)
{ {
mHashes.erase(it); mItems.erase(it);
updateHash(); updateHash();
return true; return true;
} }
} }
return false; return false;
} }
void SHAMapLeafNode::updateHash(void)
{
}

View File

@@ -5,6 +5,7 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/bimap.hpp> #include <boost/bimap.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "uint256.h" #include "uint256.h"
#include "ScopedLock.h" #include "ScopedLock.h"
@@ -17,7 +18,7 @@ class SHAMap;
class SHAMapNode class SHAMapNode
{ // Identified a node in a SHA256 hash { // Identifies a node in a SHA256 hash
private: private:
static uint256 smMasks[11]; // AND with hash to get node id static uint256 smMasks[11]; // AND with hash to get node id
@@ -32,17 +33,17 @@ public:
SHAMapNode(int depth, const uint256 &hash); SHAMapNode(int depth, const uint256 &hash);
int getDepth() { return mDepth; } int getDepth() { return mDepth; }
const uint256 &getNodeID(); const uint256 &getNodeID() { return mNodeID; }
bool isRoot() const { return mDepth==0; } bool isRoot() const { return mDepth==0; }
bool isLeaf() const { return mDepth==leafDepth; } bool isLeaf() const { return mDepth==leafDepth; }
bool isInner() const { return !isRoot() && !isLeaf(); } bool isInner() const { return !isRoot() && !isLeaf(); }
virtual bool IsPopulated(void) const { return false; } virtual bool IsPopulated(void) const { return false; }
SHAMapNode getParentNodeID() { return SHAMapNode(mDepth-1, mNodeID); } SHAMapNode getParentNodeID() { return SHAMapNode(mDepth-1, mNodeID); }
SHAMapNode getChildNodeID(int m); SHAMapNode getChildNodeID(int m);
int selectBranch(const uint256 &hash); int selectBranch(const uint256 &hash);
bool operator<(const SHAMapNode &) const; bool operator<(const SHAMapNode &) const;
bool operator>(const SHAMapNode &) const; 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<SHAMapItem>
{ // an item stored in a SHAMap
public:
typedef boost::shared_ptr<SHAMapItem> pointer;
private:
uint256 mTag;
std::vector<unsigned char> mData;
public:
SHAMapItem(const uint256 &tag, const std::vector<unsigned char>& data);
SHAMapItem(const std::vector<unsigned char>& data); // tag by hash
const uint256& getTag(void) const { return mTag; }
std::vector<unsigned char> getData(void) const { return mData; }
const std::vector<unsigned char>& peekData(void) const { return mData; }
void updateData(const std::vector<unsigned char> &data) { mData=data; }
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 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<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; }
bool operator>=(const uint256& i) const { return mTag>=i; }
};
class SHAMapLeafNode : public SHAMapNode class SHAMapLeafNode : public SHAMapNode
{ {
friend class SHAMap; friend class SHAMap;
@@ -64,13 +99,14 @@ public:
private: private:
uint256 mHash; uint256 mHash;
std::list<uint256> mHashes; std::list<SHAMapItem> mItems;
void updateHash(); void updateHash();
protected: protected:
bool addHash(const uint256 &hash); bool addUpdateItem(const SHAMapItem&);
bool delHash(const uint256 &hash); bool delItem(const SHAMapItem& i) { delItem(i.getTag()); }
bool delItem(const uint256 &tag);
public: public:
SHAMapLeafNode(const SHAMapNode& nodeID); SHAMapLeafNode(const SHAMapNode& nodeID);
@@ -78,10 +114,12 @@ public:
virtual bool IsPopulated(void) const { return true; } virtual bool IsPopulated(void) const { return true; }
const uint256& GetNodeHash() const { return mHash; } const uint256& GetNodeHash() const { return mHash; }
bool isEmpty() const { return mHashes.empty(); } bool isEmpty() const { return mItems.empty(); }
int getHashCount() const { return mHashes.size(); } int getItemCount() const { return mItems.size(); }
const uint256& GetHash(int m) const; const uint256& getHash(int m) const;
bool hasHash(const uint256 &hash) const;
bool hasItem(const uint256 &item) const;
SHAMapItem::pointer findItem(const uint256 &tag);
}; };
@@ -104,7 +142,6 @@ protected:
public: public:
SHAMapInnerNode(int Depth, const uint256 &NodeID); SHAMapInnerNode(int Depth, const uint256 &NodeID);
virtual bool isPopulated(void) const { return true; } virtual bool isPopulated(void) const { return true; }
const uint256& getNodeHash() const { return mHash; } const uint256& getNodeHash() const { return mHash; }
const uint256& getChildHash(int m) const; const uint256& getChildHash(int m) const;
@@ -119,7 +156,7 @@ public:
typedef boost::shared_ptr<SHAMap> pointer; typedef boost::shared_ptr<SHAMap> pointer;
private: private:
mutable boost::mutex mLock; mutable boost::recursive_mutex mLock;
std::map<SHAMapNode, SHAMapLeafNode> mLeafByID; std::map<SHAMapNode, SHAMapLeafNode> mLeafByID;
std::map<SHAMapNode, SHAMapInnerNode> mInnerNodeByID; std::map<SHAMapNode, SHAMapInnerNode> mInnerNodeByID;
boost::bimap<uint256, SHAMapNode> NodeHash; boost::bimap<uint256, SHAMapNode> NodeHash;
@@ -127,6 +164,7 @@ private:
public: public:
SHAMap(); SHAMap();
// hold the map stable across operations
ScopedLock Lock() const { return ScopedLock(mLock); } ScopedLock Lock() const { return ScopedLock(mLock); }
// inner node access functions // inner node access functions
@@ -167,6 +205,8 @@ public:
virtual bool fetchNode(const uint256 &hash, std::vector<unsigned char>& rawNode); virtual bool fetchNode(const uint256 &hash, std::vector<unsigned char>& rawNode);
virtual bool writeNode(const uint256 &hash, const std::vector<unsigned char>& rawNode); virtual bool writeNode(const uint256 &hash, const std::vector<unsigned char>& rawNode);
virtual bool haveObject(const uint256 &hash); virtual bool haveObject(const uint256 &hash);
static bool TestSHAMap();
}; };
#endif #endif

View File

@@ -1,7 +1,7 @@
#ifndef __SCOPEDLOCKHOLDER__ #ifndef __SCOPEDLOCKHOLDER__
#define __SCOPEDLOCKHOLDER__ #define __SCOPEDLOCKHOLDER__
#include "boost/thread/mutex.hpp" #include "boost/thread/recursive_mutex.hpp"
// This is a returnable lock holder. // This is a returnable lock holder.
// I don't know why Boost doesn't provide a good way to do this. // I don't know why Boost doesn't provide a good way to do this.
@@ -9,13 +9,13 @@
class ScopedLock class ScopedLock
{ {
private: 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; mutable bool mValid;
ScopedLock(); // no implementation ScopedLock(); // no implementation
public: public:
ScopedLock(boost::mutex &mutex) : mMutex(&mutex), mValid(true) ScopedLock(boost::recursive_mutex &mutex) : mMutex(&mutex), mValid(true)
{ {
mMutex->lock(); mMutex->lock();
} }