This makes more sense. Fetch pack, phase one.

This commit is contained in:
JoelKatz
2013-04-21 16:22:13 -07:00
parent 632a4882ea
commit 4b04f74289
3 changed files with 113 additions and 37 deletions

View File

@@ -469,6 +469,81 @@ bool SHAMap::deepCompare(SHAMap& other)
return true;
}
bool SHAMap::hasNode(const SHAMapNode& nodeID, const uint256& nodeHash)
{
SHAMapTreeNode* node = root.get();
while (node->isInner() && (node->getDepth() <= nodeID.getDepth()))
{
int branch = node->selectBranch(nodeID.getNodeID());
node = getNodePointer(node->getChildNodeID(branch), node->getChildHash(branch));
}
return node->getNodeHash() == nodeHash;
}
std::list<SHAMap::fetchPackEntry_t> SHAMap::getFetchPack(SHAMap* prior, bool includeLeaves, int max)
{
std::list<fetchPackEntry_t> ret;
if (root->isLeaf())
{
if (includeLeaves &&
(!prior || !prior->hasNode(*root, root->getNodeHash())))
{
Serializer s;
root->addRaw(s, snfPREFIX);
ret.push_back(fetchPackEntry_t(root->getNodeHash(), s.peekData()));
}
return ret;
}
if (prior && (root->getNodeHash() == prior->root->getNodeHash()))
return ret;
std::stack<SHAMapTreeNode*> stack; // contains unexplored non-matching inner node entries
stack.push(root.get());
while (!stack.empty())
{
SHAMapTreeNode* node = stack.top();
stack.pop();
// 1) Add this node to the pack
Serializer s;
node->addRaw(s, snfPREFIX);
ret.push_back(fetchPackEntry_t(node->getNodeHash(), s.peekData()));
--max;
// 2) push non-matching child inner nodes
for (int i = 0; i < 16; ++i)
{
if (!node->isEmptyBranch(i))
{
const uint256& childHash = node->getChildHash(i);
SHAMapNode childID = node->getChildNodeID(i);
SHAMapTreeNode *next = getNodePointer(childID, childHash);
if (next->isInner())
{
if (!prior || !prior->hasNode(*next, childHash))
stack.push(next);
}
else if (includeLeaves && (!prior || !prior->hasNode(childID, childHash)))
{
Serializer s;
node->addRaw(s, snfPREFIX);
ret.push_back(fetchPackEntry_t(node->getNodeHash(), s.peekData()));
--max;
}
}
}
if (max <= 0)
break;
}
cLog(lsINFO) << "Fetch pack has " << ret.size() << " entries";
return ret;
}
#ifdef DEBUG
#define SMS_DEBUG
#endif