From d57b5a9797e2ec4f510ecccdc38e795f9007b36a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 4 Jan 2013 15:21:31 -0800 Subject: [PATCH] Track failed acquires. Fix a case where an acquire both succeeds and fails. --- src/cpp/ripple/LedgerAcquire.cpp | 54 ++++++++++++++++++++++++++++++-- src/cpp/ripple/LedgerAcquire.h | 6 ++++ src/cpp/ripple/LedgerMaster.cpp | 5 +++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp index 55c539be1b..6312d61c4c 100644 --- a/src/cpp/ripple/LedgerAcquire.cpp +++ b/src/cpp/ripple/LedgerAcquire.cpp @@ -175,18 +175,21 @@ void LedgerAcquire::done() #endif std::vector< boost::function > triggers; - setComplete(); + assert(isComplete() || isFailed()); + mLock.lock(); triggers = mOnComplete; mOnComplete.clear(); mLock.unlock(); - if (mLedger) + if (isComplete() && mLedger) { if (mAccept) mLedger->setAccepted(); theApp->getLedgerMaster().storeLedger(mLedger); } + else if (isFailed()) + theApp->getMasterLedgerAcquire().logFailure(mHash); for (unsigned int i = 0; i < triggers.size(); ++i) triggers[i](shared_from_this()); @@ -528,6 +531,21 @@ LedgerAcquire::pointer LedgerAcquireMaster::find(const uint256& hash) return LedgerAcquire::pointer(); } +std::vector LedgerAcquire::getNeededHashes() +{ + std::vector ret; + if (!mHaveBase) + { + ret.push_back(mHash); + return ret; + } + if (!mHaveState) + mLedger->peekAccountStateMap()->getNeededHashes(ret, 16); + if (!mHaveTransactions) + mLedger->peekTransactionMap()->getNeededHashes(ret, 16); + return ret; +} + bool LedgerAcquireMaster::hasLedger(const uint256& hash) { assert(hash.isNonZero()); @@ -621,4 +639,36 @@ SMAddNode LedgerAcquireMaster::gotLedgerData(ripple::TMLedgerData& packet, Peer: return SMAddNode::invalid(); } +void LedgerAcquireMaster::logFailure(const uint256& hash) +{ + time_t now = time(NULL); + boost::mutex::scoped_lock sl(mLock); + + std::map::iterator it = mRecentFailures.begin(); + while (it != mRecentFailures.end()) + { + if (it->first == hash) + { + it->second = now; + return; + } + if (it->second > now) + { // time jump or discontinuity + it->second = now; + ++it; + } + else if ((it->second + 180) < now) + mRecentFailures.erase(it++); + else + ++it; + } + mRecentFailures[hash] = now; +} + +bool LedgerAcquireMaster::isFailure(const uint256& hash) +{ + boost::mutex::scoped_lock sl(mLock); + return mRecentFailures.find(hash) != mRecentFailures.end(); +} + // vim:ts=4 diff --git a/src/cpp/ripple/LedgerAcquire.h b/src/cpp/ripple/LedgerAcquire.h index 68753afab6..a4b54a3ae4 100644 --- a/src/cpp/ripple/LedgerAcquire.h +++ b/src/cpp/ripple/LedgerAcquire.h @@ -108,6 +108,8 @@ public: void trigger(Peer::ref, bool timer); bool tryLocal(); void addPeers(); + + std::vector getNeededHashes(); }; class LedgerAcquireMaster @@ -115,6 +117,7 @@ class LedgerAcquireMaster protected: boost::mutex mLock; std::map mLedgers; + std::map mRecentFailures; public: LedgerAcquireMaster() { ; } @@ -124,6 +127,9 @@ public: bool hasLedger(const uint256& ledgerHash); void dropLedger(const uint256& ledgerHash); SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref); + + void logFailure(const uint256&); + bool isFailure(const uint256&); }; #endif diff --git a/src/cpp/ripple/LedgerMaster.cpp b/src/cpp/ripple/LedgerMaster.cpp index 25a856cd1a..aa63876d10 100644 --- a/src/cpp/ripple/LedgerMaster.cpp +++ b/src/cpp/ripple/LedgerMaster.cpp @@ -170,6 +170,11 @@ void LedgerMaster::acquireMissingLedger(const uint256& ledgerHash, uint32 ledger mMissingLedger.reset(); return; } + else if (mMissingLedger->isDone()) + { + mMissingLedger.reset(); + return; + } mMissingSeq = ledgerSeq; if (mMissingLedger->setAccept()) mMissingLedger->addOnComplete(boost::bind(&LedgerMaster::missingAcquireComplete, this, _1));