diff --git a/src/ripple_app/consensus/LedgerConsensus.cpp b/src/ripple_app/consensus/LedgerConsensus.cpp index 06c882238e..e6b91921c2 100644 --- a/src/ripple_app/consensus/LedgerConsensus.cpp +++ b/src/ripple_app/consensus/LedgerConsensus.cpp @@ -1785,7 +1785,7 @@ private: mCloseTime = getApp().getOPs ().getCloseTimeNC (); getApp().getOPs ().setLastCloseTime (mCloseTime); statusChange (protocol::neCLOSING_LEDGER, *mPreviousLedger); - getApp().getLedgerMaster().closeLedger (true); + getApp().getLedgerMaster().applyHeldTransactions (); takeInitialPosition (*getApp().getLedgerMaster ().getCurrentLedger ()); } diff --git a/src/ripple_app/ledger/Ledger.cpp b/src/ripple_app/ledger/Ledger.cpp index c01cf554bb..a51f6762be 100644 --- a/src/ripple_app/ledger/Ledger.cpp +++ b/src/ripple_app/ledger/Ledger.cpp @@ -59,8 +59,8 @@ Ledger::Ledger (const RippleAddress& masterID, std::uint64_t startAmount) writeBack (lepCREATE, startAccount->getSLE ()); - mAccountStateMap->flushDirty (*mAccountStateMap->disarmDirty (), 256, - hotACCOUNT_NODE, mLedgerSeq); + auto dirtyNodes = mAccountStateMap->disarmDirty(); + mAccountStateMap->flushDirty (*dirtyNodes, 256, hotACCOUNT_NODE, mLedgerSeq); initializeFees (); } diff --git a/src/ripple_app/ledger/LedgerMaster.cpp b/src/ripple_app/ledger/LedgerMaster.cpp index 14104a2adf..359150695a 100644 --- a/src/ripple_app/ledger/LedgerMaster.cpp +++ b/src/ripple_app/ledger/LedgerMaster.cpp @@ -44,8 +44,6 @@ public: LockType m_mutex; - TransactionEngine mEngine; - LedgerHolder mCurrentLedger; // The ledger we are currently processiong LedgerHolder mClosedLedger; // The ledger that most recently closed LedgerHolder mValidLedger; // The highest-sequence ledger we have fully accepted @@ -212,7 +210,6 @@ public: } mCurrentLedger.set (newLedger); - mEngine.setLedger (newLedger); } if (getConfig().RUN_STANDALONE) @@ -234,7 +231,6 @@ public: ScopedLockType ml (m_mutex); mClosedLedger.set (newLCL); mCurrentLedger.set (newOL); - mEngine.setLedger (newOL); } if (getConfig().RUN_STANDALONE) @@ -263,7 +259,6 @@ public: mClosedLedger.set (lastClosed); assert (!current->isClosed ()); - mEngine.setLedger (current); } checkAccept (lastClosed); } @@ -285,50 +280,51 @@ public: setFullLedger(ledger, true, false); } - void closeLedger (bool recover) + /** Apply held transactions to the open ledger + This is normally called as we close the ledger. + The open ledger remains open to handle new transactions + until a new open ledger is built. + */ + void applyHeldTransactions () { ScopedLockType sl (m_mutex); - Ledger::pointer closingLedger = mCurrentLedger.getMutable (); - if (recover) + // Start with a mutable snapshot of the open ledger + TransactionEngine engine (mCurrentLedger.getMutable ()); + + int recovers = 0; + + for (auto const& it : mHeldTransactions) { - int recovers = 0; - - for (CanonicalTXSet::iterator it = mHeldTransactions.begin (), end = mHeldTransactions.end (); it != end; ++it) + try { - try - { - TransactionEngineParams tepFlags = tapOPEN_LEDGER; + TransactionEngineParams tepFlags = tapOPEN_LEDGER; - if (getApp().getHashRouter ().addSuppressionFlags (it->first.getTXID (), SF_SIGGOOD)) - tepFlags = static_cast (tepFlags | tapNO_CHECK_SIGN); + if (getApp().getHashRouter ().addSuppressionFlags (it.first.getTXID (), SF_SIGGOOD)) + tepFlags = static_cast (tepFlags | tapNO_CHECK_SIGN); - bool didApply; - mEngine.applyTransaction (*it->second, tepFlags, didApply); + bool didApply; + engine.applyTransaction (*it.second, tepFlags, didApply); - if (didApply) - ++recovers; + if (didApply) + ++recovers; - // If a transaction is recovered but hasn't been relayed, - // it will become disputed in the consensus process, which - // will cause it to be relayed. + // If a transaction is recovered but hasn't been relayed, + // it will become disputed in the consensus process, which + // will cause it to be relayed. - } - catch (...) - { - // CHECKME: We got a few of these - WriteLog (lsWARNING, LedgerMaster) << "Held transaction throws"; - } } - - CondLog (recovers != 0, lsINFO, LedgerMaster) << "Recovered " << recovers << " held transactions"; - - // VFALCO TODO recreate the CanonicalTxSet object instead of resetting it - mHeldTransactions.reset (closingLedger->getHash ()); + catch (...) + { + WriteLog (lsWARNING, LedgerMaster) << "Held transaction throws"; + } } - mCurrentLedger.set (closingLedger); - mEngine.setLedger (mCurrentLedger.getMutable ()); + CondLog (recovers != 0, lsINFO, LedgerMaster) << "Recovered " << recovers << " held transactions"; + + // VFALCO TODO recreate the CanonicalTxSet object instead of resetting it + mHeldTransactions.reset (engine.getLedger()->getHash ()); + mCurrentLedger.set (engine.getLedger ()); } LedgerIndex getBuildingLedger () @@ -345,12 +341,15 @@ public: TER doTransaction (SerializedTransaction::ref txn, TransactionEngineParams params, bool& didApply) { Ledger::pointer ledger; + TransactionEngine engine; TER result; + didApply = false; { ScopedLockType sl (m_mutex); - result = mEngine.applyTransaction (*txn, params, didApply); - ledger = mEngine.getLedger (); + ledger = mCurrentLedger.getMutable (); + engine.setLedger (ledger); + result = engine.applyTransaction (*txn, params, didApply); } if (didApply) { diff --git a/src/ripple_app/ledger/LedgerMaster.h b/src/ripple_app/ledger/LedgerMaster.h index ac1b751dc5..4694cc9db2 100644 --- a/src/ripple_app/ledger/LedgerMaster.h +++ b/src/ripple_app/ledger/LedgerMaster.h @@ -91,7 +91,7 @@ public: virtual std::string getCompleteLedgers () = 0; - virtual void closeLedger (bool recoverHeldTransactions) = 0; + virtual void applyHeldTransactions () = 0; /** Get a ledger's hash by sequence number using the cache */ diff --git a/src/ripple_app/shamap/SHAMap.cpp b/src/ripple_app/shamap/SHAMap.cpp index eb0893f7b5..af215439fc 100644 --- a/src/ripple_app/shamap/SHAMap.cpp +++ b/src/ripple_app/shamap/SHAMap.cpp @@ -1135,9 +1135,12 @@ int SHAMap::flushDirty (DirtySet& set, int maxNodes, NodeObjectType t, std::uint getApp().getNodeStore ().store (t, seq, std::move (s.modData ()), nodeHash); - // Put the canonical version into the SHAMap and the treeNodeCache - mTNByID.erase (*node); - fetchNodeExternal (*node, nodeHash); + if (getApp().running ()) + { + // Put the canonical version into the SHAMap and the treeNodeCache + mTNByID.erase (*node); + fetchNodeExternal (*node, nodeHash); + } if (flushed++ >= maxNodes) return flushed;