Continue fleshing out these classes.

This commit is contained in:
JoelKatz
2011-11-14 17:32:05 -08:00
parent ccea015c6a
commit fbf6967d82
2 changed files with 136 additions and 79 deletions

View File

@@ -1,87 +1,131 @@
#include "BitcoinUtil.h" #include "BitcoinUtil.h"
#include "SHAMap.h" #include "SHAMap.h"
#include <boost/foreach.hpp>
bool SHAMapNodeID::operator<(const SHAMapNodeID &s) const bool SHAMapNode::operator<(const SHAMapNode &s) const
{ {
if(s.mDepth<mDepth) return true; if(s.mDepth<mDepth) return true;
if(s.mDepth>mDepth) return false; if(s.mDepth>mDepth) return false;
return mNodeID<s.mNodeID; return mNodeID<s.mNodeID;
} }
bool SHAMapNodeID::operator>(const SHAMapNodeID &s) const bool SHAMapNode::operator>(const SHAMapNode &s) const
{ {
if(s.mDepth<mDepth) return false; if(s.mDepth<mDepth) return false;
if(s.mDepth>mDepth) return true; if(s.mDepth>mDepth) return true;
return mNodeID>s.mNodeID; return mNodeID>s.mNodeID;
} }
bool SHAMapNodeID::operator<=(const SHAMapNodeID &s) const bool SHAMapNode::operator<=(const SHAMapNode &s) const
{ {
if(s.mDepth<mDepth) return true; if(s.mDepth<mDepth) return true;
if(s.mDepth>mDepth) return false; if(s.mDepth>mDepth) return false;
return mNodeID<=s.mNodeID; return mNodeID<=s.mNodeID;
} }
bool SHAMapNodeID::operator>=(const SHAMapNodeID &s) const bool SHAMapNode::operator>=(const SHAMapNode &s) const
{ {
if(s.mDepth<mDepth) return false; if(s.mDepth<mDepth) return false;
if(s.mDepth>mDepth) return true; if(s.mDepth>mDepth) return true;
return mNodeID>=s.mNodeID; return mNodeID>=s.mNodeID;
} }
bool SHAMapNodeID::operator==(const SHAMapNodeID &s) const bool SHAMapNode::operator==(const SHAMapNode &s) const
{ {
return (s.mDepth==mDepth) && (s.mNodeID==mNodeID); return (s.mDepth==mDepth) && (s.mNodeID==mNodeID);
} }
bool SHAMapNodeID::operator!=(const SHAMapNodeID &s) const bool SHAMapNode::operator!=(const SHAMapNode &s) const
{ {
return (s.mDepth!=mDepth) || (s.mNodeID!=mNodeID); return (s.mDepth!=mDepth) || (s.mNodeID!=mNodeID);
} }
void SHAMapNodeID::ClassInit() void SHAMapNode::ClassInit()
{ {
int i; int i;
char HexBuf[65]; char HexBuf[65];
for(i=0; i<64; i++) HexBuf[i]='0'; for(i=0; i<64; i++) HexBuf[i]='0';
HexBuf[64]=0; HexBuf[64]=0;
for(i=0; i<leafDepth; i++) for(i=0; i<leafDepth; i++)
{ {
smMasks[i].SetHex(HexBuf); smMasks[i].SetHex(HexBuf);
HexBuf[2*i]='1'; HexBuf[2*i]='1';
HexBuf[2*i+1]='F'; HexBuf[2*i+1]='F';
} }
} }
SHAMapNodeID::SHAMapNodeID(int depth, const uint256 &hash) SHAMapNode::SHAMapNode(int depth, const uint256 &hash)
{ {
assert(depth>=0 && depth<leafDepth); assert(depth>=0 && depth<leafDepth);
mDepth=depth; mDepth=depth;
mNodeID=getNodeID(depth, hash); mNodeID=getNodeID(depth, hash);
} }
SHAMapNodeID SHAMapNodeID::getChildNodeID(int m) SHAMapNode SHAMapNode::getChildNodeID(int m)
{ {
assert(!isLeaf()); assert(!isLeaf());
uint256 branch=m; uint256 branch=m;
branch>>=(mDepth*8); branch>>=(mDepth*8);
return SHAMapNodeID(mDepth+1, mNodeID | branch); return SHAMapNode(mDepth+1, mNodeID | branch);
} }
int SHAMapNodeID::selectBranch(const uint256 &hash) int SHAMapNode::selectBranch(const uint256 &hash)
{ {
if(isLeaf()) // no nodes under this node if(isLeaf()) // no nodes under this node
return -1; return -1;
if((hash&smMasks[mDepth])!=mNodeID) if((hash&smMasks[mDepth])!=mNodeID)
return -1; // does not go under this node return -1; // does not go under this node
uint256 selector=hash&smMasks[mDepth+1]; uint256 selector=hash&smMasks[mDepth+1];
int branch=*(selector.begin()+mDepth); int branch=*(selector.begin()+mDepth);
assert(branch>=0 && branch<32); assert(branch>=0 && branch<32);
return branch; return branch;
} }
SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& nodeID) : SHAMapNode(nodeID), mHash(0)
{
;
}
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

@@ -15,7 +15,7 @@ class SHAMap;
// The trees are designed for rapid synchronization and compression of differences // The trees are designed for rapid synchronization and compression of differences
class SHAMapNodeID class SHAMapNode
{ // Identified a node in a SHA256 hash { // Identified 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
@@ -29,32 +29,33 @@ public:
static const int rootDepth=0; static const int rootDepth=0;
static const int leafDepth=10; static const int leafDepth=10;
SHAMapNodeID(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();
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(); }
SHAMapNodeID getParentNodeID() { return SHAMapNodeID(mDepth-1, mNodeID); } virtual bool IsPopulated(void) const { return false; }
SHAMapNodeID getChildNodeID(int m); SHAMapNode getParentNodeID() { return SHAMapNode(mDepth-1, mNodeID); }
SHAMapNode getChildNodeID(int m);
int selectBranch(const uint256 &hash); int selectBranch(const uint256 &hash);
static uint256 getNodeID(int depth, const uint256 &hash); static uint256 getNodeID(int depth, const uint256 &hash);
bool operator<(const SHAMapNodeID &) const; bool operator<(const SHAMapNode &) const;
bool operator>(const SHAMapNodeID &) const; bool operator>(const SHAMapNode &) const;
bool operator==(const SHAMapNodeID &) const; bool operator==(const SHAMapNode &) const;
bool operator!=(const SHAMapNodeID &) const; bool operator!=(const SHAMapNode &) const;
bool operator<=(const SHAMapNodeID &) const; bool operator<=(const SHAMapNode &) const;
bool operator>=(const SHAMapNodeID &) const; bool operator>=(const SHAMapNode &) const;
static void ClassInit(void); static void ClassInit();
}; };
class SHAMapLeafNode class SHAMapLeafNode : public SHAMapNode
{ {
friend class SHAMap; friend class SHAMap;
@@ -62,26 +63,29 @@ public:
typedef boost::shared_ptr<SHAMapLeafNode> pointer; typedef boost::shared_ptr<SHAMapLeafNode> pointer;
private: private:
SHAMapNodeID mNodeID;
uint256 mHash; uint256 mHash;
std::list<uint256> mHashes; std::list<uint256> mHashes;
void updateHash(void); void updateHash();
protected: protected:
bool hasHash(const uint256 &hash) const;
bool addHash(const uint256 &hash); bool addHash(const uint256 &hash);
bool delHash(const uint256 &hash); bool delHash(const uint256 &hash);
public: public:
SHAMapLeafNode(const uint256& NodeID); SHAMapLeafNode(const SHAMapNode& nodeID);
virtual bool IsPopulated(void) const { return true; }
const SHAMapNodeID& GetNodeID(void) const { return mNodeID; }
const uint256& GetNodeHash() const { return mHash; } 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;
}; };
class SHAMapInnerNode class SHAMapInnerNode : public SHAMapNode
{ {
friend class SHAMap; friend class SHAMap;
@@ -89,20 +93,22 @@ public:
typedef boost::shared_ptr<SHAMapInnerNode> pointer; typedef boost::shared_ptr<SHAMapInnerNode> pointer;
private: private:
SHAMapNodeID mNodeID;
uint256 mHash; uint256 mHash;
uint256 mHashes[32]; uint256 mHashes[32];
void updateHash(void); void updateHash();
protected: protected:
void SetChildHash(int m, const uint256 &hash); void SetChildHash(int m, const uint256 &hash);
public: public:
SHAMapInnerNode(int Depth, const uint256 &NodeID); SHAMapInnerNode(int Depth, const uint256 &NodeID);
const SHAMapNodeID& GetNodeID() const { return mNodeID; }
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;
bool isEmpty() const;
}; };
@@ -114,8 +120,9 @@ public:
private: private:
mutable boost::mutex mLock; mutable boost::mutex mLock;
std::map<SHAMapNodeID, SHAMapLeafNode> mLeaves; std::map<SHAMapNode, SHAMapLeafNode> mLeafByID;
std::multimap<SHAMapNodeID, SHAMapInnerNode> mInnerNodes; std::map<SHAMapNode, SHAMapInnerNode> mInnerNodeByID;
std::map<uint256, SHAMapNode> mNodeByHash; // includes nodes not present
public: public:
SHAMap(); SHAMap();
@@ -123,18 +130,18 @@ public:
ScopedLock Lock() const { return ScopedLock(mLock); } ScopedLock Lock() const { return ScopedLock(mLock); }
// inner node access functions // inner node access functions
bool HasInnerNode(const SHAMapNodeID &id); bool HasInnerNode(const SHAMapNode &id);
bool GiveInnerNode(SHAMapInnerNode::pointer); bool GiveInnerNode(SHAMapInnerNode::pointer);
SHAMapInnerNode::pointer GetInnerNode(const SHAMapNodeID &); SHAMapInnerNode::pointer GetInnerNode(const SHAMapNode &);
// leaf node access functions // leaf node access functions
bool HasLeafNode(const SHAMapNodeID &id); bool HasLeafNode(const SHAMapNode &id);
bool GiveLeafNode(SHAMapLeafNode::pointer); bool GiveLeafNode(SHAMapLeafNode::pointer);
SHAMapLeafNode::pointer GetLeafNode(const SHAMapNodeID &); SHAMapLeafNode::pointer GetLeafNode(const SHAMapNode &);
// generic node functions // generic node functions
std::vector<unsigned char> getRawNode(const SHAMapNodeID &id); std::vector<unsigned char> getRawNode(const SHAMapNode &id);
bool addRawNode(const SHAMapNodeID& nodeID, std::vector<unsigned char> rawNode); bool addRawNode(const SHAMapNode& nodeID, std::vector<unsigned char> rawNode);
// normal hash access functions // normal hash access functions
bool hasHash(const uint256 &hash); bool hasHash(const uint256 &hash);
@@ -145,9 +152,15 @@ public:
bool nextHash(uint256 &hash); bool nextHash(uint256 &hash);
bool prevHash(uint256 &hash); bool prevHash(uint256 &hash);
// special overloads for backed maps // comparison/sync functions
void getMissingNodes(std::vector<SHAMapNode> &nodeHashes, int max);
void getMissingObjects(std::vector<uint256> &objectHashes, int max);
bool addKnownNode(const std::vector<unsigned char>& rawNode);
// overloads for backed maps
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);
}; };
#endif #endif