diff --git a/src/ripple_app/consensus/LedgerConsensus.cpp b/src/ripple_app/consensus/LedgerConsensus.cpp index 0d496f861d..6838c004da 100644 --- a/src/ripple_app/consensus/LedgerConsensus.cpp +++ b/src/ripple_app/consensus/LedgerConsensus.cpp @@ -510,9 +510,9 @@ public: mAcquiringLedger = mPrevLedgerHash; getApp().getJobQueue().addJob (jtADVANCE, "getConsensusLedger", std::bind ( - &InboundLedgers::findCreateConsensusLedger, + &InboundLedgers::findCreate, &getApp().getInboundLedgers(), - mPrevLedgerHash)); + mPrevLedgerHash, 0, InboundLedger::fcCONSENSUS)); mHaveCorrectLCL = false; } return; diff --git a/src/ripple_app/ledger/InboundLedger.cpp b/src/ripple_app/ledger/InboundLedger.cpp index 3f2e27b5ba..748c8bae72 100644 --- a/src/ripple_app/ledger/InboundLedger.cpp +++ b/src/ripple_app/ledger/InboundLedger.cpp @@ -32,7 +32,7 @@ enum ,ledgerBecomeAggressiveThreshold = 6 }; -InboundLedger::InboundLedger (uint256 const& hash, uint32 seq, +InboundLedger::InboundLedger (uint256 const& hash, uint32 seq, fcReason reason, clock_type& clock) : PeerSet (hash, ledgerAcquireTimeoutMillis, false, clock, LogPartition::getJournal ()) @@ -43,6 +43,7 @@ InboundLedger::InboundLedger (uint256 const& hash, uint32 seq, , mSignaled (false) , mByHash (true) , mSeq (seq) + , mReason (reason) , mReceiveDispatched (false) { @@ -74,7 +75,7 @@ InboundLedger::~InboundLedger () } -void InboundLedger::init(ScopedLockType& collectionLock, bool couldBeNew) +void InboundLedger::init (ScopedLockType& collectionLock) { ScopedLockType sl (mLock, __FILE__, __LINE__); collectionLock.unlock (); @@ -83,7 +84,11 @@ void InboundLedger::init(ScopedLockType& collectionLock, bool couldBeNew) { addPeers (); setTimer (); - trigger (Peer::pointer ()); + + // For historical nodes, wait a bit since a + // fetch pack is probably coming + if (mReason != fcHISTORY) + trigger (Peer::pointer ()); } else if (!isFailed ()) { @@ -92,7 +97,9 @@ void InboundLedger::init(ScopedLockType& collectionLock, bool couldBeNew) mLedger->setClosed (); mLedger->setImmutable (); getApp ().getLedgerMaster ().storeLedger (mLedger); - if (couldBeNew) + + // Check if this could be a newer fully-validated ledger + if ((mReason == fcVALIDATION) || (mReason == fcCURRENT) || (mReason == fcCONSENSUS)) getApp ().getLedgerMaster ().checkAccept (mLedger); } } diff --git a/src/ripple_app/ledger/InboundLedger.h b/src/ripple_app/ledger/InboundLedger.h index f021be6078..eb04af846d 100644 --- a/src/ripple_app/ledger/InboundLedger.h +++ b/src/ripple_app/ledger/InboundLedger.h @@ -33,8 +33,18 @@ public: typedef boost::shared_ptr pointer; typedef std::pair < boost::weak_ptr, boost::shared_ptr > PeerDataPairType; + // These are the reasons we might acquire a ledger + enum fcReason + { + fcHISTORY, // Acquiring past ledger + fcGENERIC, // Generic other reasons + fcVALIDATION, // Validations suggest this ledger is important + fcCURRENT, // This might be the current ledger + fcCONSENSUS, // We believe the consensus round requires this ledger + }; + public: - InboundLedger (uint256 const& hash, uint32 seq, clock_type& clock); + InboundLedger (uint256 const& hash, uint32 seq, fcReason reason, clock_type& clock); ~InboundLedger (); @@ -74,7 +84,7 @@ public: bool tryLocal (); void addPeers (); bool checkLocal (); - void init(ScopedLockType& collectionLock, bool couldBeNew); + void init (ScopedLockType& collectionLock); bool gotData (boost::weak_ptr, boost::shared_ptr); @@ -125,6 +135,7 @@ private: bool mSignaled; bool mByHash; uint32 mSeq; + fcReason mReason; std::set mRecentTXNodes; std::set mRecentASNodes; diff --git a/src/ripple_app/ledger/InboundLedgers.cpp b/src/ripple_app/ledger/InboundLedgers.cpp index e52f492868..0f7b350444 100644 --- a/src/ripple_app/ledger/InboundLedgers.cpp +++ b/src/ripple_app/ledger/InboundLedgers.cpp @@ -41,16 +41,47 @@ public: // VFALCO TODO Should this be called findOrAdd ? // - InboundLedger::pointer findCreate (uint256 const& hash, uint32 seq, bool couldBeNew) + InboundLedger::pointer findCreate (uint256 const& hash, uint32 seq, InboundLedger::fcReason reason) { assert (hash.isNonZero ()); InboundLedger::pointer ret; + // Ensure that any previous IL is destroyed outside the lock + InboundLedger::pointer oldLedger; + { ScopedLockType sl (mLock, __FILE__, __LINE__); if (! isStopping ()) { + + if (reason == InboundLedger::fcCONSENSUS) + { + if (mConsensusLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mConsensusLedger)) + { + boost::unordered_map::iterator it = mLedgers.find (mConsensusLedger); + if (it != mLedgers.end ()) + { + oldLedger = it->second; + mLedgers.erase (it); + } + } + mConsensusLedger = hash; + } + else if (reason == InboundLedger::fcVALIDATION) + { + if (mValidationLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mValidationLedger)) + { + boost::unordered_map::iterator it = mLedgers.find (mValidationLedger); + if (it != mLedgers.end ()) + { + oldLedger = it->second; + mLedgers.erase (it); + } + } + mValidationLedger = hash; + } + boost::unordered_map::iterator it = mLedgers.find (hash); if (it != mLedgers.end ()) { @@ -59,10 +90,10 @@ public: } else { - ret = boost::make_shared (hash, seq, std::ref (m_clock)); + ret = boost::make_shared (hash, seq, reason, std::ref (m_clock)); assert (ret); mLedgers.insert (std::make_pair (hash, ret)); - ret->init (sl, couldBeNew); + ret->init (sl); ++mCounter; } } @@ -71,51 +102,6 @@ public: return ret; } - InboundLedger::pointer findCreateConsensusLedger (uint256 const& hash) - { - // We do not want to destroy the ledger while holding the collection lock - InboundLedger::pointer oldLedger; - - { - // If there was an old consensus inbound ledger, remove it - ScopedLockType sl (mLock, __FILE__, __LINE__); - if (mConsensusLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mConsensusLedger)) - { - boost::unordered_map::iterator it = mLedgers.find (mConsensusLedger); - if (it != mLedgers.end ()) - { - oldLedger = it->second; - mLedgers.erase (it); - } - } - mConsensusLedger = hash; - } - - return findCreate (hash, 0, true); - } - - InboundLedger::pointer findCreateValidationLedger (uint256 const& hash) - { - InboundLedger::pointer oldLedger; - - { - // If there was an old validation inbound ledger, remove it - ScopedLockType sl (mLock, __FILE__, __LINE__); - if (mValidationLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mValidationLedger)) - { - boost::unordered_map::iterator it = mLedgers.find (mValidationLedger); - if (it != mLedgers.end ()) - { - oldLedger = it->second; - mLedgers.erase (it); - } - } - mValidationLedger = hash; - } - - return findCreate (hash, 0, true); - } - InboundLedger::pointer find (uint256 const& hash) { assert (hash.isNonZero ()); diff --git a/src/ripple_app/ledger/InboundLedgers.h b/src/ripple_app/ledger/InboundLedgers.h index cd841d21ac..1352f985db 100644 --- a/src/ripple_app/ledger/InboundLedgers.h +++ b/src/ripple_app/ledger/InboundLedgers.h @@ -37,20 +37,16 @@ public: static InboundLedgers* New (clock_type& clock, Stoppable& parent, insight::Collector::ptr const& collector); + // VFALCO TODO Should this be called findOrAdd ? // virtual InboundLedger::pointer findCreate (uint256 const& hash, - uint32 seq, bool bCouldBeNew) = 0; + uint32 seq, InboundLedger::fcReason) = 0; virtual InboundLedger::pointer find (LedgerHash const& hash) = 0; virtual bool hasLedger (LedgerHash const& ledgerHash) = 0; - virtual InboundLedger::pointer findCreateConsensusLedger ( - LedgerHash const& hash) = 0; - virtual InboundLedger::pointer findCreateValidationLedger ( - LedgerHash const& hash) = 0; - virtual void dropLedger (LedgerHash const& ledgerHash) = 0; // VFALCO TODO Why is hash passed by value? diff --git a/src/ripple_app/ledger/Ledger.cpp b/src/ripple_app/ledger/Ledger.cpp index 7bb68884c8..c57104e8a8 100644 --- a/src/ripple_app/ledger/Ledger.cpp +++ b/src/ripple_app/ledger/Ledger.cpp @@ -1255,7 +1255,7 @@ void Ledger::visitStateItems (std::function function) catch (SHAMapMissingNode&) { if (mHash.isNonZero ()) - getApp().getInboundLedgers().findCreate(mHash, mLedgerSeq, false); + getApp().getInboundLedgers().findCreate(mHash, mLedgerSeq, InboundLedger::fcGENERIC); throw; } } diff --git a/src/ripple_app/ledger/LedgerCleaner.cpp b/src/ripple_app/ledger/LedgerCleaner.cpp index ed62ca849f..983cc2011e 100644 --- a/src/ripple_app/ledger/LedgerCleaner.cpp +++ b/src/ripple_app/ledger/LedgerCleaner.cpp @@ -245,7 +245,7 @@ public: m_journal.warning << "Node missing from ledger " << ledger->getLedgerSeq(); getApp().getInboundLedgers().findCreate ( - ledger->getHash(), ledger->getLedgerSeq(), false); + ledger->getHash(), ledger->getLedgerSeq(), InboundLedger::fcGENERIC); } return hash; } @@ -290,7 +290,7 @@ public: if (doNodes && !nodeLedger->walkLedger()) { m_journal.debug << "Ledger " << ledgerIndex << " is missing nodes"; - getApp().getInboundLedgers().findCreate(ledgerHash, ledgerIndex, false); + getApp().getInboundLedgers().findCreate(ledgerHash, ledgerIndex, InboundLedger::fcGENERIC); return false; } diff --git a/src/ripple_app/ledger/LedgerMaster.cpp b/src/ripple_app/ledger/LedgerMaster.cpp index 8b3b2a720c..4c1b832516 100644 --- a/src/ripple_app/ledger/LedgerMaster.cpp +++ b/src/ripple_app/ledger/LedgerMaster.cpp @@ -619,7 +619,7 @@ public: void failedSave(uint32 seq, uint256 const& hash) { clearLedger(seq); - getApp().getInboundLedgers().findCreate(hash, seq, true); + getApp().getInboundLedgers().findCreate(hash, seq, InboundLedger::fcGENERIC); } void checkAccept (uint256 const& hash, uint32 seq) @@ -634,7 +634,8 @@ public: // FIXME: We should really only fetch if the ledger //has sufficient validations to accept it - InboundLedger::pointer l = getApp().getInboundLedgers().findCreateValidationLedger(hash); + InboundLedger::pointer l = + getApp().getInboundLedgers().findCreate(hash, 0, InboundLedger::fcGENERIC); if (l && l->isComplete() && !l->isFailed()) ledger = l->getLedger(); else @@ -767,7 +768,8 @@ public: { InboundLedger::pointer acq = getApp().getInboundLedgers().findCreate(nextLedger->getParentHash(), - nextLedger->getLedgerSeq() - 1, false); + nextLedger->getLedgerSeq() - 1, + InboundLedger::fcHISTORY); if (acq->isComplete() && !acq->isFailed()) ledger = acq->getLedger(); else if ((missing > 40000) && getApp().getOPs().shouldFetchPack(missing)) @@ -804,7 +806,8 @@ public: uint32 seq = missing - i; uint256 hash = nextLedger->getLedgerHash(seq); if (hash.isNonZero()) - getApp().getInboundLedgers().findCreate(hash, seq, false); + getApp().getInboundLedgers().findCreate(hash, + seq, InboundLedger::fcHISTORY); } } catch (...) @@ -911,7 +914,8 @@ public: if (!ledger && (++acqCount < 4)) { // We can try to acquire the ledger we need - InboundLedger::pointer acq = getApp().getInboundLedgers ().findCreate (hash, seq, false); + InboundLedger::pointer acq = + getApp().getInboundLedgers ().findCreate (hash, seq, InboundLedger::fcGENERIC); if (!acq->isDone ()) { @@ -925,7 +929,7 @@ public: { WriteLog (lsWARNING, LedgerMaster) << "Failed to acquire a published ledger"; getApp().getInboundLedgers().dropLedger(hash); - acq = getApp().getInboundLedgers().findCreate(hash, seq, false); + acq = getApp().getInboundLedgers().findCreate(hash, seq, InboundLedger::fcGENERIC); if (acq->isComplete()) { if (acq->isFailed()) @@ -1053,7 +1057,8 @@ public: catch (SHAMapMissingNode&) { WriteLog (lsINFO, LedgerMaster) << "Missing node detected during pathfinding"; - getApp().getInboundLedgers().findCreate(lastLedger->getHash (), lastLedger->getLedgerSeq (), false); + getApp().getInboundLedgers().findCreate(lastLedger->getHash (), lastLedger->getLedgerSeq (), + InboundLedger::fcGENERIC); } } } @@ -1149,7 +1154,8 @@ public: Ledger::pointer ledger (getLedgerByHash (hash)); if (!ledger) { - InboundLedger::pointer inboundLedger = getApp().getInboundLedgers().findCreate (hash, index, false); + InboundLedger::pointer inboundLedger = + getApp().getInboundLedgers().findCreate (hash, index, InboundLedger::fcGENERIC); if (inboundLedger && inboundLedger->isComplete() && !inboundLedger->isFailed()) ledger = inboundLedger->getLedger(); } diff --git a/src/ripple_app/misc/NetworkOPs.cpp b/src/ripple_app/misc/NetworkOPs.cpp index f96bb3e809..9083adf9fc 100644 --- a/src/ripple_app/misc/NetworkOPs.cpp +++ b/src/ripple_app/misc/NetworkOPs.cpp @@ -1343,7 +1343,7 @@ bool NetworkOPsImp::checkLastClosedLedger (const Peers::PeerSequence& peerList, m_journal.info << "Acquiring consensus ledger " << closedLedger; if (!mAcquiringLedger || (mAcquiringLedger->getHash () != closedLedger)) - mAcquiringLedger = getApp().getInboundLedgers ().findCreate (closedLedger, 0, true); + mAcquiringLedger = getApp().getInboundLedgers ().findCreate (closedLedger, 0, InboundLedger::fcCONSENSUS); if (!mAcquiringLedger || mAcquiringLedger->isFailed ()) { @@ -3226,7 +3226,7 @@ void NetworkOPsImp::missingNodeInLedger (uint32 seq) else { m_journal.warning << "Missing a node in ledger " << seq << " fetching"; - getApp().getInboundLedgers ().findCreate (hash, seq, false); + getApp().getInboundLedgers ().findCreate (hash, seq, InboundLedger::fcGENERIC); } }