From 66a762d504c7739d17589e2b2a57d1f0ef03d4f0 Mon Sep 17 00:00:00 2001 From: David Schwartz Date: Thu, 8 May 2014 10:49:21 -0700 Subject: [PATCH] Rework handling of modified ledger nodes: * Track dirty nodes in a set * Make flushDirty a member function * Don't write deleted nodes * Make sure new nodes are shareable * Put new nodes in the treeNodeCache --- src/ripple_app/consensus/LedgerConsensus.cpp | 12 +++--- src/ripple_app/ledger/Ledger.cpp | 3 +- src/ripple_app/shamap/SHAMap.cpp | 45 +++++++++++++------- src/ripple_app/shamap/SHAMap.h | 7 +-- 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/ripple_app/consensus/LedgerConsensus.cpp b/src/ripple_app/consensus/LedgerConsensus.cpp index dd1267b269..06c882238e 100644 --- a/src/ripple_app/consensus/LedgerConsensus.cpp +++ b/src/ripple_app/consensus/LedgerConsensus.cpp @@ -898,23 +898,23 @@ private: applyTransactions (set, newLCL, newLCL, failedTransactions, false); newLCL->updateSkipList (); newLCL->setClosed (); - boost::shared_ptr acctNodes + boost::shared_ptr acctNodes = newLCL->peekAccountStateMap ()->disarmDirty (); - boost::shared_ptr txnNodes + boost::shared_ptr txnNodes = newLCL->peekTransactionMap ()->disarmDirty (); // write out dirty nodes (temporarily done here) int fc; - while ((fc = SHAMap::flushDirty (*acctNodes, 256 - , hotACCOUNT_NODE, newLCL->getLedgerSeq ())) > 0) + while ((fc = newLCL->peekAccountStateMap()->flushDirty ( + *acctNodes, 256, hotACCOUNT_NODE, newLCL->getLedgerSeq ())) > 0) { WriteLog (lsTRACE, LedgerConsensus) << "Flushed " << fc << " dirty state nodes"; } - while ((fc = SHAMap::flushDirty (*txnNodes, 256 - , hotTRANSACTION_NODE, newLCL->getLedgerSeq ())) > 0) + while ((fc = newLCL->peekTransactionMap()->flushDirty ( + *txnNodes, 256, hotTRANSACTION_NODE, newLCL->getLedgerSeq ())) > 0) { WriteLog (lsTRACE, LedgerConsensus) << "Flushed " << fc << " dirty transaction nodes"; diff --git a/src/ripple_app/ledger/Ledger.cpp b/src/ripple_app/ledger/Ledger.cpp index 6b0df61235..c01cf554bb 100644 --- a/src/ripple_app/ledger/Ledger.cpp +++ b/src/ripple_app/ledger/Ledger.cpp @@ -59,7 +59,8 @@ Ledger::Ledger (const RippleAddress& masterID, std::uint64_t startAmount) writeBack (lepCREATE, startAccount->getSLE ()); - SHAMap::flushDirty (*mAccountStateMap->disarmDirty (), 256, hotACCOUNT_NODE, mLedgerSeq); + mAccountStateMap->flushDirty (*mAccountStateMap->disarmDirty (), 256, + hotACCOUNT_NODE, mLedgerSeq); initializeFees (); } diff --git a/src/ripple_app/shamap/SHAMap.cpp b/src/ripple_app/shamap/SHAMap.cpp index 54ab748d3b..eb0893f7b5 100644 --- a/src/ripple_app/shamap/SHAMap.cpp +++ b/src/ripple_app/shamap/SHAMap.cpp @@ -381,7 +381,7 @@ void SHAMap::returnNode (SHAMapTreeNode::pointer& node, bool modify) root = node; if (mDirtyNodes) - (*mDirtyNodes)[*node] = node; + mDirtyNodes->insert (*node); } } @@ -389,7 +389,7 @@ void SHAMap::trackNewNode (SHAMapTreeNode::pointer& node) { assert (node->getSeq() == mSeq); if (mDirtyNodes) - (*mDirtyNodes)[*node] = node; + mDirtyNodes->insert (*node); } SHAMapTreeNode* SHAMap::firstBelow (SHAMapTreeNode* node) @@ -1093,38 +1093,51 @@ bool SHAMap::fetchRoot (uint256 const& hash, SHAMapSyncFilter* filter) return true; } +/** Begin saving dirty nodes to be written later */ int SHAMap::armDirty () { - // begin saving dirty nodes - mDirtyNodes = boost::make_shared< ripple::unordered_map > (); + mDirtyNodes = boost::make_shared (); return ++mSeq; } -int SHAMap::flushDirty (NodeMap& map, int maxNodes, NodeObjectType t, std::uint32_t seq) +/** Write all modified nodes to the node store */ +int SHAMap::flushDirty (DirtySet& set, int maxNodes, NodeObjectType t, std::uint32_t seq) { int flushed = 0; Serializer s; - for (NodeMap::iterator it = map.begin (); it != map.end (); it = map.erase (it)) + ScopedWriteLockType sl (mLock); + + for (DirtySet::iterator it = set.begin (); it != set.end (); it = set.erase (it)) { - // tLog(t == hotTRANSACTION_NODE, lsDEBUG) << "TX node write " << it->first; - // tLog(t == hotACCOUNT_NODE, lsDEBUG) << "STATE node write " << it->first; + SHAMapTreeNode::pointer node = checkCacheNode (*it); + + // Check if node was deleted + if (!node) + continue; + + uint256 const nodeHash = node->getNodeHash(); + s.erase (); - it->second->addRaw (s, snfPREFIX); + node->addRaw (s, snfPREFIX); #ifdef BEAST_DEBUG - if (s.getSHA512Half () != it->second->getNodeHash ()) + if (s.getSHA512Half () != nodeHash) { - WriteLog (lsFATAL, SHAMap) << * (it->second); + WriteLog (lsFATAL, SHAMap) << *node; WriteLog (lsFATAL, SHAMap) << beast::lexicalCast (s.getDataLength ()); - WriteLog (lsFATAL, SHAMap) << s.getSHA512Half () << " != " << it->second->getNodeHash (); + WriteLog (lsFATAL, SHAMap) << s.getSHA512Half () << " != " << nodeHash; assert (false); } #endif - getApp().getNodeStore ().store (t, seq, std::move (s.modData ()), it->second->getNodeHash ()); + 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 (flushed++ >= maxNodes) return flushed; @@ -1133,12 +1146,12 @@ int SHAMap::flushDirty (NodeMap& map, int maxNodes, NodeObjectType t, std::uint3 return flushed; } -boost::shared_ptr SHAMap::disarmDirty () +/** Stop saving dirty nodes */ +boost::shared_ptr SHAMap::disarmDirty () { - // stop saving dirty nodes ScopedWriteLockType sl (mLock); - boost::shared_ptr ret; + boost::shared_ptr ret; ret.swap (mDirtyNodes); return ret; } diff --git a/src/ripple_app/shamap/SHAMap.h b/src/ripple_app/shamap/SHAMap.h index 6a3d86015a..ea63faad48 100644 --- a/src/ripple_app/shamap/SHAMap.h +++ b/src/ripple_app/shamap/SHAMap.h @@ -112,6 +112,7 @@ public: typedef std::pair DeltaRef; typedef std::map Delta; typedef ripple::unordered_map NodeMap; + typedef std::unordered_set DirtySet; typedef boost::shared_mutex LockType; typedef boost::shared_lock ScopedReadLockType; @@ -229,9 +230,9 @@ public: bool compare (SHAMap::ref otherMap, Delta & differences, int maxCount); int armDirty (); - static int flushDirty (NodeMap & dirtyMap, int maxNodes, NodeObjectType t, + int flushDirty (DirtySet & dirtySet, int maxNodes, NodeObjectType t, std::uint32_t seq); - boost::shared_ptr disarmDirty (); + boost::shared_ptr disarmDirty (); void setSeq (std::uint32_t seq) { @@ -347,7 +348,7 @@ private: std::uint32_t mSeq; std::uint32_t mLedgerSeq; // sequence number of ledger this is part of SyncUnorderedMapType< SHAMapNode, SHAMapTreeNode::pointer, SHAMapNode_hash > mTNByID; - boost::shared_ptr mDirtyNodes; + boost::shared_ptr mDirtyNodes; SHAMapTreeNode::pointer root; SHAMapState mState; SHAMapType mType;