diff --git a/src/ripple/app/ledger/AcceptedLedger.cpp b/src/ripple/app/ledger/AcceptedLedger.cpp index 170788032a..1691b8ebae 100644 --- a/src/ripple/app/ledger/AcceptedLedger.cpp +++ b/src/ripple/app/ledger/AcceptedLedger.cpp @@ -35,7 +35,7 @@ AcceptedLedger::AcceptedLedger (Ledger::ref ledger) : mLedger (ledger) { for (auto const& item : ledger->txMap()) { - SerialIter sit (item->slice()); + SerialIter sit (item.slice()); insert (std::make_shared( ledger, std::ref (sit))); } diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index f55d363909..38b871b6a6 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -59,7 +59,7 @@ class Ledger::txs_iter_impl private: bool metadata_; ReadView const* view_; - SHAMap::iterator iter_; + SHAMap::const_iterator iter_; public: txs_iter_impl() = delete; @@ -68,7 +68,7 @@ public: txs_iter_impl (txs_iter_impl const&) = default; txs_iter_impl (bool metadata, - SHAMap::iterator iter, + SHAMap::const_iterator iter, ReadView const& view) : metadata_ (metadata) , view_ (&view) @@ -102,8 +102,8 @@ public: { auto const item = *iter_; if (metadata_) - return deserializeTxPlusMeta(*item); - return { deserializeTx(*item), nullptr }; + return deserializeTxPlusMeta(item); + return { deserializeTx(item), nullptr }; } }; diff --git a/src/ripple/app/ledger/LedgerHistory.cpp b/src/ripple/app/ledger/LedgerHistory.cpp index 77f34351c1..e41c8acaaf 100644 --- a/src/ripple/app/ledger/LedgerHistory.cpp +++ b/src/ripple/app/ledger/LedgerHistory.cpp @@ -275,16 +275,14 @@ log_metadata_difference(Ledger::pointer builtLedger, Ledger::pointer validLedger // Return list of leaves sorted by key static -std::vector> +std::vector leaves (SHAMap const& sm) { - std::vector> v; + std::vector v; for (auto const& item : sm) - v.push_back(item); + v.push_back(&item); std::sort(v.begin(), v.end(), - [](std::shared_ptr const& lhs, - std::shared_ptr const& rhs) + [](SHAMapItem const* lhs, SHAMapItem const* rhs) { return lhs->key() < rhs->key(); }); return v; } diff --git a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp index 0a5c89aa50..700df9c919 100644 --- a/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp +++ b/src/ripple/app/ledger/impl/LedgerConsensusImp.cpp @@ -1812,20 +1812,19 @@ void applyTransactions ( { if (set) { - for (auto const item : *set) + for (auto const& item : *set) { - if (checkLedger->txExists (item->key())) + if (checkLedger->txExists (item.key())) continue; // The transaction isn't in the check ledger, try to apply it WriteLog (lsDEBUG, LedgerConsensus) << - "Processing candidate transaction: " << item->key(); + "Processing candidate transaction: " << item.key(); std::shared_ptr txn; try { - SerialIter sit (item->slice()); - txn = std::make_shared(sit); + txn = std::make_shared(SerialIter{item.slice()}); } catch (...) { diff --git a/src/ripple/app/ledger/impl/OpenLedger.cpp b/src/ripple/app/ledger/impl/OpenLedger.cpp index 8d40f56290..d7f87c63bd 100644 --- a/src/ripple/app/ledger/impl/OpenLedger.cpp +++ b/src/ripple/app/ledger/impl/OpenLedger.cpp @@ -207,7 +207,7 @@ debugTostr (SHAMap const& set) { try { - SerialIter sit(item->slice()); + SerialIter sit(item.slice()); auto const tx = std::make_shared< STTx const>(sit); ss << debugTxstr(tx) << ", "; diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index 5f9900f819..e0c8f0a598 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -1334,16 +1334,16 @@ bool ApplicationImp::loadOldLedger ( for (auto const& item : txns) { auto const txn = - getTransaction(*replayLedger, item->key(), + getTransaction(*replayLedger, item.key(), getApp().getMasterTransaction()); if (m_journal.info) m_journal.info << txn->getJson(0); Serializer s; txn->getSTransaction()->add(s); - cur->rawTxInsert(item->key(), + cur->rawTxInsert(item.key(), std::make_shared( std::move(s)), nullptr); - getApp().getHashRouter().setFlag (item->key(), SF_SIGGOOD); + getApp().getHashRouter().setFlag (item.key(), SF_SIGGOOD); } // Switch to the mutable snapshot diff --git a/src/ripple/shamap/SHAMap.h b/src/ripple/shamap/SHAMap.h index 78a0e263ef..97574b0a88 100644 --- a/src/ripple/shamap/SHAMap.h +++ b/src/ripple/shamap/SHAMap.h @@ -33,12 +33,12 @@ #include #include #include -#include #include #include #include #include #include +#include namespace ripple { @@ -80,6 +80,8 @@ class SHAMap { private: using Family = shamap::Family; + using NodeStack = std::stack, + std::vector>>; Family& f_; beast::Journal journal_; @@ -119,10 +121,10 @@ public: This is always a const iterator. Meets the requirements of ForwardRange. */ - class iterator; + class const_iterator; - iterator begin() const; - iterator end() const; + const_iterator begin() const; + const_iterator end() const; //-------------------------------------------------------------------------- @@ -166,10 +168,12 @@ public: std::shared_ptr const& peekFirstItem () const; std::shared_ptr const& peekFirstItem (SHAMapTreeNode::TNType & type) const; + SHAMapItem const* peekFirstItem(NodeStack& stack) const; std::shared_ptr const& peekLastItem () const; std::shared_ptr const& peekNextItem (uint256 const& ) const; std::shared_ptr const& peekNextItem (uint256 const& , SHAMapTreeNode::TNType & type) const; + SHAMapItem const* peekNextItem(uint256 const& id, NodeStack& stack) const; std::shared_ptr const& peekPrevItem (uint256 const& ) const; void visitNodes (std::function const&) const; @@ -272,6 +276,7 @@ private: std::shared_ptr node) const; SHAMapTreeNode* firstBelow (SHAMapAbstractNode*) const; + SHAMapTreeNode* firstBelow (SHAMapAbstractNode*, NodeStack& stack) const; SHAMapTreeNode* lastBelow (SHAMapAbstractNode*) const; // Simple descent @@ -358,66 +363,109 @@ SHAMap::setUnbacked () //------------------------------------------------------------------------------ -class SHAMap::iterator - : public boost::iterator_facade< - SHAMap::iterator, - std::shared_ptr const, - std::forward_iterator_tag> +class SHAMap::const_iterator { -private: - friend class boost::iterator_core_access; +public: + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = SHAMapItem; + using reference = value_type const&; + using pointer = value_type const*; - SHAMap const* map_ = nullptr; - std::shared_ptr< - SHAMapItem const> item_; +private: + NodeStack stack_; + SHAMap const* map_ = nullptr; + pointer item_ = nullptr; public: - iterator() = default; - iterator (iterator const&) = default; - iterator& operator= (iterator const&) = default; + const_iterator() = default; - iterator (SHAMap const& map, - std::shared_ptr const& item) - : map_(&map) - , item_(item) - { - } + reference operator*() const; + pointer operator->() const; + + const_iterator& operator++(); + const_iterator operator++(int); private: - void - increment() - { - item_ = map_->peekNextItem( - item_->key()); - } + explicit const_iterator(SHAMap const* map); + const_iterator(SHAMap const* map, pointer item); - bool - equal (iterator const& other) const - { - assert(map_ == other.map_); - return item_ == other.item_; - } - - std::shared_ptr< - SHAMapItem const> const& - dereference() const - { - return item_; - } + friend bool operator==(const_iterator const& x, const_iterator const& y); + friend class SHAMap; }; inline -SHAMap::iterator -SHAMap::begin() const +SHAMap::const_iterator::const_iterator(SHAMap const* map) + : map_(map) + , item_(map_->peekFirstItem(stack_)) { - return iterator(*this, peekFirstItem()); } inline -SHAMap::iterator +SHAMap::const_iterator::const_iterator(SHAMap const* map, pointer item) + : map_(map) + , item_(item) +{ +} + +inline +SHAMap::const_iterator::reference +SHAMap::const_iterator::operator*() const +{ + return *item_; +} + +inline +SHAMap::const_iterator::pointer +SHAMap::const_iterator::operator->() const +{ + return item_; +} + +inline +SHAMap::const_iterator& +SHAMap::const_iterator::operator++() +{ + item_ = map_->peekNextItem(item_->key(), stack_); + return *this; +} + +inline +SHAMap::const_iterator +SHAMap::const_iterator::operator++(int) +{ + auto tmp = *this; + ++(*this); + return tmp; +} + +inline +bool +operator==(SHAMap::const_iterator const& x, SHAMap::const_iterator const& y) +{ + assert(x.map_ == y.map_); + return x.item_ == y.item_; +} + +inline +bool +operator!=(SHAMap::const_iterator const& x, SHAMap::const_iterator const& y) +{ + return !(x == y); +} + +inline +SHAMap::const_iterator +SHAMap::begin() const +{ + return const_iterator(this); +} + +inline +SHAMap::const_iterator SHAMap::end() const { - return iterator(*this, nullptr); + return const_iterator(this, nullptr); } } diff --git a/src/ripple/shamap/impl/SHAMap.cpp b/src/ripple/shamap/impl/SHAMap.cpp index 0677c7d181..666dd64ef8 100644 --- a/src/ripple/shamap/impl/SHAMap.cpp +++ b/src/ripple/shamap/impl/SHAMap.cpp @@ -445,6 +445,33 @@ SHAMap::firstBelow (SHAMapAbstractNode* node) const while (true); } +SHAMapTreeNode* +SHAMap::firstBelow(SHAMapAbstractNode* node, NodeStack& stack) const +{ + // Return the first item below this node + while (true) + { + assert(node != nullptr); + if (node->isLeaf()) + return static_cast(node); + bool foundNode = false; + auto inner = static_cast(node); + for (int i = 0; i < 16; ++i) + { + if (!inner->isEmptyBranch(i)) + { + node = descendThrow(inner, i); + assert(!stack.empty()); + stack.push({node, stack.top().second.getChildNodeID(i)}); + foundNode = true; + break; + } + } + if (!foundNode) + return nullptr; + } +} + SHAMapTreeNode* SHAMap::lastBelow (SHAMapAbstractNode* node) const { @@ -534,6 +561,17 @@ SHAMap::peekFirstItem () const return node->peekItem (); } +SHAMapItem const* +SHAMap::peekFirstItem(NodeStack& stack) const +{ + assert(stack.empty()); + stack.push({root_.get(), SHAMapNodeID{}}); + SHAMapTreeNode* node = firstBelow(root_.get(), stack); + if (!node) + return nullptr; + return node->peekItem().get(); +} + std::shared_ptr const& SHAMap::peekFirstItem (SHAMapTreeNode::TNType& type) const { @@ -597,7 +635,7 @@ SHAMap::peekNextItem (uint256 const& id, SHAMapTreeNode::TNType& type) const auto leaf = firstBelow (node); if (!leaf) - throw (std::runtime_error ("missing/corrupt node")); + throw SHAMapMissingNode(type_, id); type = leaf->getType (); return leaf->peekItem (); @@ -609,6 +647,38 @@ SHAMap::peekNextItem (uint256 const& id, SHAMapTreeNode::TNType& type) const return no_item; } +SHAMapItem const* +SHAMap::peekNextItem(uint256 const& id, NodeStack& stack) const +{ + assert(!stack.empty()); + assert(stack.top().first->isLeaf()); + stack.pop(); + while (!stack.empty()) + { + auto node = stack.top().first; + auto nodeID = stack.top().second; + assert(!node->isLeaf()); + auto inner = static_cast(node); + for (auto i = nodeID.selectBranch(id) + 1; i < 16; ++i) + { + if (!inner->isEmptyBranch(i)) + { + node = descendThrow(inner, i); + nodeID = nodeID.getChildNodeID(i); + stack.push({node, nodeID}); + auto leaf = firstBelow(node, stack); + if (!leaf) + throw SHAMapMissingNode(type_, id); + assert(leaf->isLeaf()); + return leaf->peekItem().get(); + } + } + stack.pop(); + } + // must be last item + return nullptr; +} + // Get a pointer to the previous item in the tree after a given item - item need not be in tree std::shared_ptr const& SHAMap::peekPrevItem (uint256 const& id) const @@ -697,7 +767,7 @@ bool SHAMap::delItem (uint256 const& id) auto stack = getStack (id, true); if (stack.empty ()) - throw (std::runtime_error ("missing node")); + throw SHAMapMissingNode(type_, id); auto leaf = std::dynamic_pointer_cast(stack.top ().first); stack.pop (); @@ -785,7 +855,7 @@ SHAMap::addGiveItem (std::shared_ptr const& item, auto stack = getStack (tag, true); if (stack.empty ()) - throw (std::runtime_error ("missing node")); + throw SHAMapMissingNode(type_, tag); auto node = stack.top ().first; auto nodeID = stack.top ().second; @@ -875,7 +945,7 @@ SHAMap::updateGiveItem (std::shared_ptr const& item, auto stack = getStack (tag, true); if (stack.empty ()) - throw (std::runtime_error ("missing node")); + throw SHAMapMissingNode(type_, tag); auto node = std::dynamic_pointer_cast(stack.top().first); auto nodeID = stack.top ().second;