diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 66accff6d0..340f09b86d 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -430,12 +430,16 @@ void Ledger::saveAcceptedLedger(bool fromConsensus) } if (!fromConsensus) + { + decPendingSaves(); return; + } theApp->getMasterLedger().setFullLedger(shared_from_this()); theApp->getOPs().pubLedger(shared_from_this()); + decPendingSaves(); } Ledger::pointer Ledger::getSQL(const std::string& sql) @@ -1022,4 +1026,28 @@ bool Ledger::assertSane() return false; } +int Ledger::sPendingSaves = 0; +boost::recursive_mutex Ledger::sPendingSaveLock; + +int Ledger::getPendingSaves() +{ + boost::recursive_mutex::scoped_lock sl(sPendingSaveLock); + return sPendingSaves; +} + +void Ledger::pendSave(bool fromConsensus) +{ + boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, shared_from_this(), fromConsensus)); + thread.detach(); + + boost::recursive_mutex::scoped_lock sl(sPendingSaveLock); + ++sPendingSaves; +} + +void Ledger::decPendingSaves() +{ + boost::recursive_mutex::scoped_lock sl(sPendingSaveLock); + --sPendingSaves; +} + // vim:ts=4 diff --git a/src/Ledger.h b/src/Ledger.h index 01ea5cd83c..f043821142 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -78,12 +78,19 @@ private: mutable boost::recursive_mutex mLock; + static int sPendingSaves; + static boost::recursive_mutex sPendingSaveLock; + Ledger(const Ledger&); // no implementation Ledger& operator=(const Ledger&); // no implementation protected: SLE::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID, LedgerEntryType let); + static void incPendingSaves(); + static void decPendingSaves(); + void saveAcceptedLedger(bool fromConsensus); + public: Ledger(const RippleAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger @@ -101,6 +108,7 @@ public: static Ledger::pointer getSQL(const std::string& sqlStatement); static Ledger::pointer getLastFullLedger(); + static int getPendingSaves(); void updateHash(); void setClosed() { mClosed = true; } @@ -157,9 +165,9 @@ public: SLE::pointer getAccountRoot(const RippleAddress& naAccountID); // database functions - void saveAcceptedLedger(bool fromConsensus); static Ledger::pointer loadByIndex(uint32 ledgerIndex); static Ledger::pointer loadByHash(const uint256& ledgerHash); + void pendSave(bool fromConsensus); // next/prev function SLE::pointer getSLE(const uint256& uHash); diff --git a/src/LedgerHistory.cpp b/src/LedgerHistory.cpp index 62c559f9a8..854fc011fd 100644 --- a/src/LedgerHistory.cpp +++ b/src/LedgerHistory.cpp @@ -38,8 +38,7 @@ void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus assert(ledger->isImmutable()); mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger)); - boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, ledger, fromConsensus)); - thread.detach(); + ledger->pendSave(fromConsensus); } Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index) diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index 73f5c47205..d229d4b724 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -125,9 +125,8 @@ void LedgerMaster::missingAcquireComplete(LedgerAcquire::pointer acq) if (!acq->isFailed()) { - boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, acq->getLedger(), false)); - thread.detach(); setFullLedger(acq->getLedger()); + acq->getLedger()->pendSave(false); } } @@ -153,6 +152,12 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger) if (mMissingLedger || !theConfig.FULL_HISTORY) return; + if (Ledger::getPendingSaves() > 2) + { + cLog(lsINFO) << "Too many pending ledger saves"; + return; + } + // see if there's a ledger gap we need to fill if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1)) {