First set of efficiency improvements.

This commit is contained in:
JoelKatz
2012-06-04 07:18:57 -07:00
parent 27241a9a5c
commit 0e7307200e
6 changed files with 78 additions and 14 deletions

View File

@@ -67,7 +67,7 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
}
LedgerAcquire::LedgerAcquire(const uint256& hash) : PeerSet(hash, LEDGER_ACQUIRE_TIMEOUT),
mHaveBase(false), mHaveState(false), mHaveTransactions(false)
mFilter(&theApp->getNodeCache()), mHaveBase(false), mHaveState(false), mHaveTransactions(false)
{
#ifdef DEBUG
std::cerr << "Acquiring ledger " << mHash.GetHex() << std::endl;
@@ -152,7 +152,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
{
std::vector<SHAMapNode> nodeIDs;
std::vector<uint256> nodeHashes;
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128, &mFilter);
if (nodeIDs.empty())
{
if (!mLedger->peekTransactionMap()->isValid()) mFailed = true;
@@ -204,7 +204,7 @@ void LedgerAcquire::trigger(Peer::pointer peer)
{
std::vector<SHAMapNode> nodeIDs;
std::vector<uint256> nodeHashes;
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128, &mFilter);
if (nodeIDs.empty())
{
if (!mLedger->peekAccountStateMap()->isValid()) mFailed = true;
@@ -303,7 +303,7 @@ bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait))
return false;
}
else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait))
else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
return false;
++nodeIDit;
++nodeDatait;
@@ -333,7 +333,7 @@ bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), *nodeDatait))
return false;
}
else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait))
else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
return false;
++nodeIDit;
++nodeDatait;

View File

@@ -13,6 +13,7 @@
#include "Ledger.h"
#include "Peer.h"
#include "TaggedCache.h"
#include "../obj/src/newcoin.pb.h"
class PeerSet
@@ -53,6 +54,30 @@ private:
static void TimerEntry(boost::weak_ptr<PeerSet>, const boost::system::error_code& result);
};
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
typedef std::vector<unsigned char> VUC;
class THSyncFilter : public SHAMapSyncFilter
{
protected:
NodeCache* mCache;
public:
THSyncFilter(NodeCache* cache) : mCache(cache) { ; }
virtual void gotNode(const uint256& nodeHash, const std::vector<unsigned char>& nodeData, bool)
{
boost::shared_ptr<VUC> ptr = boost::make_shared<VUC>(nodeData);
mCache->canonicalize(nodeHash, ptr);
}
virtual bool haveNode(const uint256& nodeHash, std::vector<unsigned char>& nodeData)
{
boost::shared_ptr<VUC> entry = mCache->fetch(nodeHash);
if (!entry) return false;
nodeData = *entry;
return true;
}
};
class LedgerAcquire : public PeerSet, public boost::enable_shared_from_this<LedgerAcquire>
{ // A ledger we are trying to acquire
public:
@@ -60,6 +85,7 @@ public:
protected:
Ledger::pointer mLedger;
THSyncFilter mFilter;
bool mHaveBase, mHaveState, mHaveTransactions;
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
@@ -106,4 +132,5 @@ public:
};
#endif
// vim:ts=4

View File

@@ -11,7 +11,8 @@
#define TRUST_NETWORK
TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1), mHaveRoot(false)
TransactionAcquire::TransactionAcquire(const uint256& hash)
: PeerSet(hash, 1), mFilter(&theApp->getNodeCache()), mHaveRoot(false)
{
mMap = boost::make_shared<SHAMap>();
mMap->setSynching();
@@ -48,7 +49,7 @@ void TransactionAcquire::trigger(Peer::pointer peer)
Log(lsTRACE) << "Have root";
std::vector<SHAMapNode> nodeIDs;
std::vector<uint256> nodeHashes;
mMap->getMissingNodes(nodeIDs, nodeHashes, 256);
mMap->getMissingNodes(nodeIDs, nodeHashes, 256, &mFilter);
if (nodeIDs.empty())
{
if (mMap->isValid())
@@ -100,7 +101,7 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
return false;
else mHaveRoot = true;
}
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait))
else if (!mMap->addKnownNode(*nodeIDit, *nodeDatait, &mFilter))
return false;
++nodeIDit;
++nodeDatait;

View File

@@ -21,6 +21,7 @@ public:
protected:
SHAMap::pointer mMap;
THSyncFilter mFilter; // FIXME: Should use transaction master too
bool mHaveRoot;
void onTimer() { trigger(Peer::pointer()); }

View File

@@ -219,6 +219,17 @@ enum SHAMapState
Invalid = 4, // Map is known not to be valid (usually synching a corrupt ledger)
};
class SHAMapSyncFilter
{
public:
SHAMapSyncFilter() { ; }
virtual ~SHAMapSyncFilter() { ; }
virtual void gotNode(const uint256& nodeHash, const std::vector<unsigned char>& nodeData, bool isLeaf)
{ ; }
virtual bool haveNode(const uint256&nodeHash, std::vector<unsigned char>& nodeData)
{ return false; }
};
class SHAMap
{
public:
@@ -293,12 +304,14 @@ public:
SHAMapItem::pointer peekPrevItem(const uint256&);
// comparison/sync functions
void getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max);
void getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
SHAMapSyncFilter* filter);
bool getNodeFat(const SHAMapNode& node, std::vector<SHAMapNode>& nodeIDs,
std::list<std::vector<unsigned char> >& rawNode, bool fatLeaves);
bool addRootNode(const uint256& hash, const std::vector<unsigned char>& rootNode);
bool addRootNode(const std::vector<unsigned char>& rootNode);
bool addKnownNode(const SHAMapNode& nodeID, const std::vector<unsigned char>& rawNode);
bool addKnownNode(const SHAMapNode& nodeID, const std::vector<unsigned char>& rawNode,
SHAMapSyncFilter* filter);
// status functions
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }

View File

@@ -11,7 +11,8 @@
#include "Log.h"
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max)
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
SHAMapSyncFilter* filter)
{
boost::recursive_mutex::scoped_lock sl(mLock);
@@ -44,6 +45,24 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
if (!node->isEmptyBranch(branch))
{
SHAMapTreeNode::pointer d = getNode(node->getChildNodeID(branch), node->getChildHash(branch), false);
if ((!d) && (filter != NULL))
{
std::vector<unsigned char> nodeData;
if (filter->haveNode(node->getChildHash(branch), nodeData))
{
d = boost::make_shared<SHAMapTreeNode>(node->getChildNodeID(branch), nodeData, mSeq);
if (node->getChildHash(branch) != d->getNodeHash())
{
Log(lsERROR) << "Wrong hash from cached object";
d = SHAMapTreeNode::pointer();
}
else
{
Log(lsTRACE) << "Got sync node from cache";
mTNByID[*d] = d;
}
}
}
if (!d)
{
nodeIDs.push_back(node->getChildNodeID(branch));
@@ -153,7 +172,8 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector<unsigned char>&
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,
SHAMapSyncFilter* filter)
{ // return value: true=okay, false=error
assert(!node.isRoot());
if (!isSynching()) return false;
@@ -199,6 +219,8 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
if (hash != newNode->getNodeHash()) // these aren't the droids we're looking for
return false;
if (filter) filter->gotNode(hash, rawNode, newNode->isLeaf());
mTNByID[*newNode] = newNode;
if (!newNode->isLeaf())
return true; // only a leaf can fill a branch
@@ -416,7 +438,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
hashes.clear();
// get the list of nodes we know we need
destination.getMissingNodes(nodeIDs, hashes, 2048);
destination.getMissingNodes(nodeIDs, hashes, 2048, NULL);
if(nodeIDs.empty()) break;
Log(lsINFO) << nodeIDs.size() << " needed nodes";
@@ -446,7 +468,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
#ifdef SMS_DEBUG
bytes += rawNodeIterator->size();
#endif
if (!destination.addKnownNode(*nodeIDIterator, *rawNodeIterator))
if (!destination.addKnownNode(*nodeIDIterator, *rawNodeIterator, NULL))
{
Log(lsTRACE) << "AddKnownNode fails";
BOOST_FAIL("AddKnownNode");