mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 19:15:54 +00:00
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:
76
SHAMap.cpp
76
SHAMap.cpp
@@ -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)
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
64
SHAMap.h
64
SHAMap.h
@@ -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,15 +33,15 @@ 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;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user