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

View File

@@ -5,6 +5,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/bimap.hpp>
#include <boost/enable_shared_from_this.hpp>
#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,15 +33,15 @@ 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;
@@ -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
{
friend class SHAMap;
@@ -64,13 +99,14 @@ public:
private:
uint256 mHash;
std::list<uint256> mHashes;
std::list<SHAMapItem> 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<SHAMap> pointer;
private:
mutable boost::mutex mLock;
mutable boost::recursive_mutex mLock;
std::map<SHAMapNode, SHAMapLeafNode> mLeafByID;
std::map<SHAMapNode, SHAMapInnerNode> mInnerNodeByID;
boost::bimap<uint256, SHAMapNode> 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<unsigned char>& rawNode);
virtual bool writeNode(const uint256 &hash, const std::vector<unsigned char>& rawNode);
virtual bool haveObject(const uint256 &hash);
static bool TestSHAMap();
};
#endif

View File

@@ -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();
}