mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 14:05:51 +00:00
SHAMap sync now passes its unit test with the "full below" optimization
disabled. There's a logic error in the implementation.
This commit is contained in:
@@ -39,6 +39,7 @@ CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
|||||||
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
|
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
|
||||||
const uint256& hash)
|
const uint256& hash)
|
||||||
{
|
{
|
||||||
|
if(!theApp->getHashNodeDB()) return true;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Serializer s(data);
|
Serializer s(data);
|
||||||
assert(hash==s.getSHA512Half());
|
assert(hash==s.getSHA512Half());
|
||||||
@@ -76,6 +77,7 @@ bool HashedObject::store() const
|
|||||||
|
|
||||||
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
||||||
{
|
{
|
||||||
|
if(!theApp->getHashNodeDB()) return HashedObject::pointer();
|
||||||
std::string sql="SELECT * from CommitedObjects WHERE Hash='";
|
std::string sql="SELECT * from CommitedObjects WHERE Hash='";
|
||||||
sql.append(hash.GetHex());
|
sql.append(hash.GetHex());
|
||||||
sql.append("';");
|
sql.append("';");
|
||||||
|
|||||||
37
SHAMap.cpp
37
SHAMap.cpp
@@ -16,9 +16,6 @@ void SHAMap::dirtyUp(const uint256& id)
|
|||||||
{ // walk the tree up from through the inner nodes to the root
|
{ // walk the tree up from through the inner nodes to the root
|
||||||
// update linking hashes and add nodes to dirty list
|
// update linking hashes and add nodes to dirty list
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "dirtyUp(" << id.GetHex() << ")" << std::endl;
|
|
||||||
#endif
|
|
||||||
assert(!mImmutable && !mSynching);
|
assert(!mImmutable && !mSynching);
|
||||||
SHAMapLeafNode::pointer leaf=checkCacheLeaf(SHAMapNode(SHAMapNode::leafDepth, id));
|
SHAMapLeafNode::pointer leaf=checkCacheLeaf(SHAMapNode(SHAMapNode::leafDepth, id));
|
||||||
if(!leaf) throw SHAMapException(MissingNode);
|
if(!leaf) throw SHAMapException(MissingNode);
|
||||||
@@ -79,12 +76,6 @@ SHAMapInnerNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
|
|||||||
SHAMapLeafNode::pointer SHAMap::walkToLeaf(const uint256& id, bool create, bool modify)
|
SHAMapLeafNode::pointer SHAMap::walkToLeaf(const uint256& id, bool create, bool modify)
|
||||||
{ // walk down to the leaf that would contain this ID
|
{ // walk down to the leaf that would contain this ID
|
||||||
// is leaf node in cache
|
// is leaf node in cache
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "walkToLeaf(" << id.GetHex() << ")";
|
|
||||||
if(create) std::cerr << " create";
|
|
||||||
if(modify) std::cerr << " modify";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
SHAMapLeafNode::pointer ln=checkCacheLeaf(SHAMapNode(SHAMapNode::leafDepth, id));
|
SHAMapLeafNode::pointer ln=checkCacheLeaf(SHAMapNode(SHAMapNode::leafDepth, id));
|
||||||
if(ln) return returnLeaf(ln, modify);
|
if(ln) return returnLeaf(ln, modify);
|
||||||
|
|
||||||
@@ -135,15 +126,33 @@ SHAMapInnerNode::pointer SHAMap::walkTo(const SHAMapNode& id)
|
|||||||
if(branch<0) // somehow we got on the wrong branch
|
if(branch<0) // somehow we got on the wrong branch
|
||||||
throw SHAMapException(InvalidNode);
|
throw SHAMapException(InvalidNode);
|
||||||
if (inNode->isEmptyBranch(branch)) // we know no branches below this one
|
if (inNode->isEmptyBranch(branch)) // we know no branches below this one
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Walk down empty branch" << std::endl;
|
||||||
|
#endif
|
||||||
return inNode;
|
return inNode;
|
||||||
if(!inNode->isChildLeaf()) // this is the last inner node
|
}
|
||||||
|
if(inNode->isChildLeaf()) // this is the last inner node
|
||||||
return inNode;
|
return inNode;
|
||||||
|
|
||||||
SHAMapInnerNode::pointer next=getInner(inNode->getChildNodeID(branch), inNode->getChildHash(branch), false);
|
try
|
||||||
if(!next) // we don't have the next node
|
{
|
||||||
|
SHAMapInnerNode::pointer next=getInner(inNode->getChildNodeID(branch), inNode->getChildHash(branch), false);
|
||||||
|
if(!next) // we don't have the next node
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Unable to find node " << inNode->getChildNodeID(branch).getString() << std::endl;
|
||||||
|
#endif
|
||||||
|
return inNode;
|
||||||
|
}
|
||||||
|
assert(next->getDepth() == (inNode->getDepth()+1));
|
||||||
|
inNode=next;
|
||||||
|
}
|
||||||
|
catch (const SHAMapException& x)
|
||||||
|
{
|
||||||
|
if(x!=SHAMapException(MissingNode)) throw(x);
|
||||||
return inNode;
|
return inNode;
|
||||||
assert(next->getDepth() == (inNode->getDepth()+1));
|
}
|
||||||
inNode=next;
|
|
||||||
assert(i++ < SHAMapNode::leafDepth);
|
assert(i++ < SHAMapNode::leafDepth);
|
||||||
} while(1);
|
} while(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
|||||||
std::cerr << "gMN: popped " << node->getString() << std::endl;
|
std::cerr << "gMN: popped " << node->getString() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool all_leaves=true;
|
|
||||||
for(int i=0; i<32; i++)
|
for(int i=0; i<32; i++)
|
||||||
{
|
{
|
||||||
if(!node->isEmptyBranch(i))
|
if(!node->isEmptyBranch(i))
|
||||||
@@ -44,11 +43,11 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
}
|
|
||||||
SHAMapInnerNode::pointer desc=getInner(node->getChildNodeID(i), node->getChildHash(i), false);
|
SHAMapInnerNode::pointer desc=getInner(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
assert(desc);
|
assert(desc);
|
||||||
if(!desc->isFullBelow())
|
if(!desc->isFullBelow())
|
||||||
stack.push(desc);
|
stack.push(desc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(const SHAMapException &x)
|
catch(const SHAMapException &x)
|
||||||
{
|
{
|
||||||
@@ -56,16 +55,14 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
|||||||
if(max-->0)
|
if(max-->0)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "gMN: need leaf " << i << std::endl;
|
std::cerr << "gMN: need leaf " << node->getChildNodeID(i).getString() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
nodeIDs.push_back(node->getChildNodeID(i));
|
nodeIDs.push_back(node->getChildNodeID(i));
|
||||||
hashes.push_back(node->getChildHash(i));
|
hashes.push_back(node->getChildHash(i));
|
||||||
}
|
}
|
||||||
all_leaves=false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(all_leaves) node->setFullBelow();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +161,7 @@ bool SHAMap::addRootNode(const std::vector<unsigned char>& rootNode)
|
|||||||
root=node;
|
root=node;
|
||||||
mInnerNodeByID[*node]=node;
|
mInnerNodeByID[*node]=node;
|
||||||
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[*node]=node;
|
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[*node]=node;
|
||||||
|
if(!root->getNodeHash()) root->setFullBelow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,12 +186,14 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector<unsigned char>&
|
|||||||
root=node;
|
root=node;
|
||||||
mInnerNodeByID[*node]=node;
|
mInnerNodeByID[*node]=node;
|
||||||
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[*node]=node;
|
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[*node]=node;
|
||||||
|
if(!root->getNodeHash()) root->setFullBelow();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned char>& rawNode)
|
bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned char>& rawNode)
|
||||||
{ // return value: true=okay, false=error
|
{ // return value: true=okay, false=error
|
||||||
assert(!node.isRoot());
|
assert(!node.isRoot());
|
||||||
|
assert(mSynching);
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
@@ -224,7 +224,8 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
|||||||
if(iNode->getDepth()!=(node.getDepth()-1))
|
if(iNode->getDepth()!=(node.getDepth()-1))
|
||||||
{ // Either this node is broken or we didn't request it
|
{ // Either this node is broken or we didn't request it
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "got inner node, unable to hook it" << std::endl;
|
std::cerr << "unable to hook node " << node.getString() << std::endl;
|
||||||
|
std::cerr << " stuck at " << iNode->getString() << std::endl;
|
||||||
std::cerr << "got depth=" << node.getDepth() << ", walked to= " << iNode->getDepth() << std::endl;
|
std::cerr << "got depth=" << node.getDepth() << ", walked to= " << iNode->getDepth() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
@@ -251,6 +252,9 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
|||||||
}
|
}
|
||||||
mLeafByID[node]=leaf;
|
mLeafByID[node]=leaf;
|
||||||
if(mDirtyLeafNodes) (*mDirtyLeafNodes)[node]=leaf;
|
if(mDirtyLeafNodes) (*mDirtyLeafNodes)[node]=leaf;
|
||||||
|
|
||||||
|
// WRITEME: See if our parent(s) are full below
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,11 +263,16 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
|||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "inner node fails consistency check" << std::endl;
|
std::cerr << "inner node fails consistency check" << std::endl;
|
||||||
|
std::cerr << " Built: " << newNode->getString() << " h=" << newNode->getNodeHash().GetHex() << std::endl;
|
||||||
|
std::cerr << "Expected: " << node.getString() << " h=" << hash.GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mInnerNodeByID[node]=newNode;
|
mInnerNodeByID[node]=newNode;
|
||||||
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[node]=newNode;
|
if(mDirtyInnerNodes) (*mDirtyInnerNodes)[node]=newNode;
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Hooked: " << node.getString() << std::endl;
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,6 +433,7 @@ bool SHAMap::syncTest()
|
|||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
assert(gotNodeIDs.size() == gotNodes.size());
|
||||||
nodeIDs.clear();
|
nodeIDs.clear();
|
||||||
hashes.clear();
|
hashes.clear();
|
||||||
|
|
||||||
@@ -445,7 +455,7 @@ bool SHAMap::syncTest()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodeIDs.clear();
|
gotNodeIDs.clear();
|
||||||
gotNodes.clear();
|
gotNodes.clear();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user