More work on the SHAMap/Serialize classes.

This commit is contained in:
JoelKatz
2011-11-17 18:11:11 -08:00
parent e7bae43261
commit 477b2df276
5 changed files with 88 additions and 24 deletions

View File

@@ -4,7 +4,12 @@
#include <boost/foreach.hpp>
SHAMap::SHAMap(int leafDataSize) : mLeafDataSize(leafDataSize)
SHAMapItem::SHAMapItem(const uint256 &tag) : mTag(tag)
{
mData.insert(mData.end(), tag.begin(), tag.end());
}
SHAMap::SHAMap(int leafDataSize, int leafDataOffset) : mLeafDataSize(leafDataSize), mLeafDataOffset(leafDataOffset)
{
;
}
@@ -86,14 +91,30 @@ SHAMapLeafNode::pointer SHAMap::walkToLeaf(const uint256& id, bool create,
SHAMapLeafNode::pointer SHAMap::getLeaf(const SHAMapNode &id, const uint256& hash)
{ // retrieve a leaf whose node hash is known
SHAMapLeafNode::pointer leaf=mLeafByID[id];
assert(!!hash);
SHAMapLeafNode::pointer leaf=mLeafByID[id]; // is the leaf in memory
if(leaf != SHAMapLeafNode::pointer()) return leaf;
std::vector<unsigned char> rawNode;
std::vector<unsigned char> rawNode; // is it in backing store
if(!fetchNode(hash, id, rawNode)) return leaf;
Serializer s(rawNode);
leaf=SHAMapLeafNode::pointer(new SHAMapLeafNode(id));
// construct leaf WRITEME
for(int i=0; i<s.getLength(); i+=mLeafDataSize)
{
uint256 tag;
if(mLeafDataOffset<0)
{
Serializer inner;
inner.addRaw(s.getRaw(i, mLeafDataSize));
tag=inner.getSHA512Half();
}
else tag=s.get256(i+mLeafDataOffset);
leaf->addUpdateItem(SHAMapItem(tag, s.getRaw(i, mLeafDataSize)));
}
leaf->updateHash();
assert(leaf->getNodeHash()==hash);
return leaf;
}

View File

@@ -106,13 +106,13 @@ public:
private:
uint256 mHash;
std::list<SHAMapItem> mItems;
std::list<SHAMapItem::pointer> mItems;
bool updateHash();
protected:
bool addUpdateItem(const SHAMapItem&);
bool delItem(const SHAMapItem& i) { delItem(i.getTag()); }
bool addUpdateItem(SHAMapItem::pointer);
bool delItem(const SHAMapItem::pointer i) { delItem(i->getTag()); }
bool delItem(const uint256 &tag);
public:
@@ -120,7 +120,7 @@ public:
virtual bool isPopulated(void) const { return true; }
const uint256& GetNodeHash() const { return mHash; }
const uint256& getNodeHash() const { return mHash; }
bool isEmpty() const { return mItems.empty(); }
int getItemCount() const { return mItems.size(); }
@@ -171,7 +171,7 @@ public:
typedef boost::shared_ptr<SHAMap> pointer;
private:
int mLeafDataSize;
int mLeafDataSize, mLeafDataOffset;
mutable boost::recursive_mutex mLock;
std::map<SHAMapNode, SHAMapLeafNode::pointer> mLeafByID;
std::map<SHAMapNode, SHAMapInnerNode::pointer> mInnerNodeByID;
@@ -195,7 +195,7 @@ protected:
SHAMapItem::pointer lastBelow(SHAMapInnerNode::pointer);
public:
SHAMap(int leafDataSize);
SHAMap(int leafDataSize=32, int leafDataOffset=-1);
// hold the map stable across operations
ScopedLock Lock() const { return ScopedLock(mLock); }

View File

@@ -96,6 +96,11 @@ int SHAMapNode::selectBranch(const uint256 &hash)
return branch;
}
void SHAMapNode::dump()
{
std::cerr << "MapNode(" << mNodeID.GetHex() << ", " << mDepth << ")" << std::endl;
}
SHAMapLeafNode::SHAMapLeafNode(const SHAMapNode& nodeID) : SHAMapNode(nodeID), mHash(0)
{
;
@@ -103,26 +108,28 @@ 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;
BOOST_FOREACH(SHAMapItem::pointer nodeItem, mItems)
if(nodeItem->getTag()==item) return true;
return false;
}
bool SHAMapLeafNode::addUpdateItem(const SHAMapItem& item)
bool SHAMapLeafNode::addUpdateItem(SHAMapItem::pointer item)
{ // The node will almost never have more than one item in it
std::list<SHAMapItem>::iterator it;
std::list<SHAMapItem::pointer>::iterator it;
for(it=mItems.begin(); it!=mItems.end(); it++)
{
if(*it==item)
SHAMapItem &nodeItem=**it;
if(nodeItem.getTag()==item->getTag())
{
if(it->peekData()==item.peekData())
if(nodeItem.peekData()==item->peekData())
return false; // no change
it->updateData(item.peekData());
nodeItem.updateData(item->peekData());
return updateHash();
}
if((*it)>item)
if(nodeItem.getTag()>item->getTag())
{
mItems.insert(it, item);
return updateHash();
}
}
mItems.push_back(item);
@@ -131,10 +138,10 @@ bool SHAMapLeafNode::addUpdateItem(const SHAMapItem& item)
bool SHAMapLeafNode::delItem(const uint256& tag)
{
std::list<SHAMapItem>::iterator it;
std::list<SHAMapItem::pointer>::iterator it;
for(it=mItems.begin(); it!=mItems.end(); it++)
{
if(*it==tag)
if((*it)->getTag()==tag)
{
mItems.erase(it);
return updateHash();
@@ -143,14 +150,27 @@ bool SHAMapLeafNode::delItem(const uint256& tag)
return false;
}
SHAMapItem::pointer SHAMapLeafNode::firstItem(void)
{
if(mItems.size()==0) return SHAMapItem::pointer();
return *(mItems.begin());
}
SHAMapItem::pointer SHAMapLeafNode::lastItem(void)
{
if(mItems.size()==0) return SHAMapItem::pointer();
return *(mItems.rbegin());
}
bool SHAMapLeafNode::updateHash(void)
{
uint256 nh;
if(mItems.size()!=0) nh=0;
{
Serializer s;
BOOST_FOREACH(const SHAMapItem &mi, mItems)
s.addRaw(mi.peekData());
BOOST_FOREACH(const SHAMapItem::pointer &mi, mItems)
s.addRaw(mi->peekData());
nh=s.getSHA512Half();
}
if(nh==mHash) return false;

View File

@@ -83,6 +83,14 @@ bool Serializer::get256(uint256& o, int offset) const
return true;
}
uint256 Serializer::get256(int offset) const
{
uint256 ret;
if((offset+sizeof(ret))>mData.size()) return ret;
memcpy(&ret, &(mData.front())+offset, sizeof(ret));
return ret;
}
bool Serializer::getRaw(std::vector<unsigned char>& o, int offset, int length) const
{
if((offset+length)>mData.size()) return false;
@@ -90,6 +98,14 @@ bool Serializer::getRaw(std::vector<unsigned char>& o, int offset, int length) c
return true;
}
std::vector<unsigned char> Serializer::getRaw(int offset, int length) const
{
std::vector<unsigned char> o;
if((offset+length)>mData.size()) return o;
o.assign(mData.begin()+offset, mData.begin()+offset+length);
return o;
}
uint160 Serializer::getRIPEMD160(int size) const
{
uint160 ret;
@@ -141,3 +157,8 @@ bool Serializer::addSignature(CKey& key)
addRaw(signature);
return true;
}
void Serializer::TestSerializer(void)
{
Serializer s(64);
}

View File

@@ -26,7 +26,9 @@ class Serializer
bool get64(uint64&, int offset) const;
bool get160(uint160&, int offset) const;
bool get256(uint256&, int offset) const;
uint256 get256(int offset) const;
bool getRaw(std::vector<unsigned char>&, int offset, int length) const;
std::vector<unsigned char> getRaw(int offset, int length) const;
// hash functions
uint160 getRIPEMD160(int size=0) const;
@@ -44,7 +46,7 @@ class Serializer
bool makeSignature(std::vector<unsigned char> &signature, CKey& rkey) const;
bool addSignature(CKey& rkey);
static void UnitTest(void);
static void TestSerializer(void);
};
#endif