diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index e3decf3b5b..26fcaefb01 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -2353,6 +2353,10 @@ True True + + True + True + True True diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 23fdcf303c..de0eeddb12 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -3078,6 +3078,9 @@ ripple\ledger\impl + + ripple\ledger\impl + ripple\ledger\impl diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 6e9c157898..5448d56c72 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -61,6 +61,59 @@ create_genesis_t const create_genesis {}; //------------------------------------------------------------------------------ +class Ledger::sles_iter_impl + : public sles_type::iter_base +{ +private: + ReadView const* view_; + SHAMap::const_iterator iter_; + +public: + sles_iter_impl() = delete; + sles_iter_impl& operator= (sles_iter_impl const&) = delete; + + sles_iter_impl (sles_iter_impl const&) = default; + + sles_iter_impl (SHAMap::const_iterator iter, + ReadView const& view) + : view_ (&view) + , iter_ (iter) + { + } + + std::unique_ptr + copy() const override + { + return std::make_unique< + sles_iter_impl>(*this); + } + + bool + equal (base_type const& impl) const override + { + auto const& other = dynamic_cast< + sles_iter_impl const&>(impl); + return iter_ == other.iter_; + } + + void + increment() override + { + ++iter_; + } + + sles_type::value_type + dereference() const override + { + auto const item = *iter_; + SerialIter sit(item.slice()); + return std::make_shared( + sit, item.key()); + } +}; + +//------------------------------------------------------------------------------ + class Ledger::txs_iter_impl : public txs_type::iter_base { @@ -870,6 +923,24 @@ Ledger::read (Keylet const& k) const //------------------------------------------------------------------------------ +auto +Ledger::slesBegin() const -> + std::unique_ptr +{ + return std::make_unique< + sles_iter_impl>( + stateMap_->begin(), *this); +} + +auto +Ledger::slesEnd() const -> + std::unique_ptr +{ + return std::make_unique< + sles_iter_impl>( + stateMap_->end(), *this); +} + auto Ledger::txsBegin() const -> std::unique_ptr diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 2c053415a9..182bd32d08 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -152,6 +152,12 @@ public: std::shared_ptr read (Keylet const& k) const override; + std::unique_ptr + slesBegin() const override; + + std::unique_ptr + slesEnd() const override; + std::unique_ptr txsBegin() const override; @@ -363,6 +369,7 @@ public: getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq); private: + class sles_iter_impl; class txs_iter_impl; void saveValidatedLedgerAsync(Job&, bool current) diff --git a/src/ripple/app/ledger/impl/LedgerToJson.cpp b/src/ripple/app/ledger/impl/LedgerToJson.cpp index 725ec4da64..54ca621f2b 100644 --- a/src/ripple/app/ledger/impl/LedgerToJson.cpp +++ b/src/ripple/app/ledger/impl/LedgerToJson.cpp @@ -131,20 +131,20 @@ void fillJsonState(Object& json, LedgerFill const& fill) auto expanded = isExpanded(fill); auto binary = isBinary(fill); - forEachSLE(ledger, [&] (SLE const& sle) { + for(auto const& sle : ledger.sles) + { count.yield(); if (binary) { auto&& obj = appendObject(array); - obj[jss::hash] = to_string(sle.key()); - obj[jss::tx_blob] = serializeHex(sle); + obj[jss::hash] = to_string(sle->key()); + obj[jss::tx_blob] = serializeHex(*sle); } else if (expanded) - array.append(sle.getJson(0)); + array.append(sle->getJson(0)); else - array.append(to_string(sle.key())); - return true; - }); + array.append(to_string(sle->key())); + } } template diff --git a/src/ripple/ledger/CachedView.h b/src/ripple/ledger/CachedView.h index 27d4b69a23..8825e16f6e 100644 --- a/src/ripple/ledger/CachedView.h +++ b/src/ripple/ledger/CachedView.h @@ -84,6 +84,18 @@ public: return base_.succ(key, last); } + std::unique_ptr + slesBegin() const override + { + return base_.slesBegin(); + } + + std::unique_ptr + slesEnd() const override + { + return base_.slesEnd(); + } + std::unique_ptr txsBegin() const override { diff --git a/src/ripple/ledger/OpenView.h b/src/ripple/ledger/OpenView.h index a267fc0ff0..c8e74bb974 100644 --- a/src/ripple/ledger/OpenView.h +++ b/src/ripple/ledger/OpenView.h @@ -164,6 +164,12 @@ public: std::shared_ptr read (Keylet const& k) const override; + std::unique_ptr + slesBegin() const override; + + std::unique_ptr + slesEnd() const override; + std::unique_ptr txsBegin() const override; diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index 0d21b422e5..d4135ee345 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -136,11 +136,22 @@ public: using mapped_type = std::shared_ptr; - using sles_type = detail::ReadViewFwdRange< - std::shared_ptr>; + struct sles_type : detail::ReadViewFwdRange< + std::shared_ptr> + { + explicit sles_type (ReadView const& view); + iterator begin() const; + iterator const& end() const; + }; - using txs_type = - detail::ReadViewFwdRange; + struct txs_type + : detail::ReadViewFwdRange + { + explicit txs_type (ReadView const& view); + bool empty() const; + iterator begin() const; + iterator const& end() const; + }; virtual ~ReadView() = default; @@ -148,17 +159,20 @@ public: ReadView& operator= (ReadView const& other) = delete; ReadView() - : txs(*this) + : sles(*this) + , txs(*this) { } ReadView (ReadView const&) - : txs(*this) + : sles(*this) + , txs(*this) { } ReadView (ReadView&& other) - : txs(*this) + : sles(*this) + , txs(*this) { } @@ -254,6 +268,16 @@ public: return amount; } + // used by the implementation + virtual + std::unique_ptr + slesBegin() const = 0; + + // used by the implementation + virtual + std::unique_ptr + slesEnd() const = 0; + // used by the implementation virtual std::unique_ptr @@ -289,8 +313,14 @@ public: // Memberspaces // - // The range of ledger entries - //sles_type sles; + /** Iterable range of ledger state items. + + Visiting each state entry in the ledger can be + quite expensive. This will only visit entries in + the base ledger. Entries in open views, apply + views, or sandboxes will not be visited. + */ + sles_type sles; // The range of transactions txs_type txs; diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h index 1c84248757..0265ce5364 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -169,18 +169,6 @@ getCandidateLedger (LedgerIndex requested) return (requested + 255) & (~255); } -/** Run a functor on each SLE in a ReadView starting from the key start, - as long as the functor returns true. - */ -template -void forEachSLE(ReadView const& view, Functor func, uint256 const& start = {}) -{ - for (auto k = view.succ(start); k; k = view.succ(*k)) - if (auto sle = view.read(keylet::unchecked(*k))) - if (! func(*sle)) - break; -} - //------------------------------------------------------------------------------ // // Modifiers diff --git a/src/ripple/ledger/detail/ApplyViewBase.h b/src/ripple/ledger/detail/ApplyViewBase.h index 04c7fd7651..4165e8a4b5 100644 --- a/src/ripple/ledger/detail/ApplyViewBase.h +++ b/src/ripple/ledger/detail/ApplyViewBase.h @@ -73,6 +73,12 @@ public: std::shared_ptr read (Keylet const& k) const override; + std::unique_ptr + slesBegin() const override; + + std::unique_ptr + slesEnd() const override; + std::unique_ptr txsBegin() const override; diff --git a/src/ripple/ledger/detail/ReadViewFwdRange.h b/src/ripple/ledger/detail/ReadViewFwdRange.h index 4e2f667455..10ca162751 100644 --- a/src/ripple/ledger/detail/ReadViewFwdRange.h +++ b/src/ripple/ledger/detail/ReadViewFwdRange.h @@ -139,18 +139,6 @@ public: ReadViewFwdRange (ReadViewFwdRange const&) = default; ReadViewFwdRange& operator= (ReadViewFwdRange const&) = default; - /** Returns `true` if the range is empty. */ - bool - empty() const; - - /** Return iterator to the beginning of the range. */ - iterator - begin() const; - - /** Return iterator to one past the end of the range. */ - iterator const& - end() const; - // VFALCO Otherwise causes errors on clang //private: // friend class ReadView; @@ -161,7 +149,7 @@ public: { } -private: +protected: ReadView const* view_; boost::optional mutable end_; }; diff --git a/src/ripple/ledger/detail/ReadViewFwdRange.ipp b/src/ripple/ledger/detail/ReadViewFwdRange.ipp index 49843e635f..0062fb2c67 100644 --- a/src/ripple/ledger/detail/ReadViewFwdRange.ipp +++ b/src/ripple/ledger/detail/ReadViewFwdRange.ipp @@ -27,7 +27,8 @@ template ReadViewFwdRange::iterator::iterator( iterator const& other) : view_ (other.view_) - , impl_ (other.impl_->copy()) + , impl_ (other.impl_ ? + other.impl_->copy() : nullptr) , cache_ (other.cache_) { } @@ -59,7 +60,8 @@ ReadViewFwdRange::iterator::operator=( if (this == &other) return *this; view_ = other.view_; - impl_ = other.impl_->copy(); + impl_ = other.impl_ ? + other.impl_->copy() : nullptr; cache_ = other.cache_; return *this; } @@ -133,33 +135,6 @@ ReadViewFwdRange::iterator::operator++(int) -> return prev; } -//------------------------------------------------------------------------------ - -template -bool -ReadViewFwdRange::empty() const -{ - return begin() == end(); -} - -template -auto -ReadViewFwdRange::begin() const -> - iterator -{ - return iterator(view_, view_->txsBegin()); -} - -template -auto -ReadViewFwdRange::end() const -> - iterator const& -{ - if (! end_) - end_.emplace(view_, view_->txsEnd()); - return *end_; -} - } // detail } // ripple diff --git a/src/ripple/ledger/impl/ApplyViewBase.cpp b/src/ripple/ledger/impl/ApplyViewBase.cpp index 1133c58765..14853ec122 100644 --- a/src/ripple/ledger/impl/ApplyViewBase.cpp +++ b/src/ripple/ledger/impl/ApplyViewBase.cpp @@ -66,6 +66,20 @@ ApplyViewBase::read (Keylet const& k) const return items_.read(*base_, k); } +auto +ApplyViewBase::slesBegin() const -> + std::unique_ptr +{ + return base_->slesBegin(); +} + +auto +ApplyViewBase::slesEnd() const -> + std::unique_ptr +{ + return base_->slesEnd(); +} + auto ApplyViewBase::txsBegin() const -> std::unique_ptr diff --git a/src/ripple/ledger/impl/OpenView.cpp b/src/ripple/ledger/impl/OpenView.cpp index fd377d7457..659f6de6c2 100644 --- a/src/ripple/ledger/impl/OpenView.cpp +++ b/src/ripple/ledger/impl/OpenView.cpp @@ -158,6 +158,20 @@ OpenView::read (Keylet const& k) const return items_.read(*base_, k); } +auto +OpenView::slesBegin() const -> + std::unique_ptr +{ + return base_->slesBegin(); +} + +auto +OpenView::slesEnd() const -> + std::unique_ptr +{ + return base_->slesEnd(); +} + auto OpenView::txsBegin() const -> std::unique_ptr diff --git a/src/ripple/ledger/impl/ReadView.cpp b/src/ripple/ledger/impl/ReadView.cpp new file mode 100644 index 0000000000..884ef4dacb --- /dev/null +++ b/src/ripple/ledger/impl/ReadView.cpp @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include + +namespace ripple { + +ReadView::sles_type::sles_type( + ReadView const& view) + : ReadViewFwdRange(view) +{ +} + +auto +ReadView::sles_type::begin() const -> + iterator +{ + return iterator(view_, view_->slesBegin()); +} + +auto +ReadView::sles_type::end() const -> + iterator const& +{ + if (! end_) + end_ = iterator(view_, view_->slesEnd()); + return *end_; +} + +ReadView::txs_type::txs_type( + ReadView const& view) + : ReadViewFwdRange(view) +{ +} + +bool +ReadView::txs_type::empty() const +{ + return begin() == end(); +} + +auto +ReadView::txs_type::begin() const -> + iterator +{ + return iterator(view_, view_->txsBegin()); +} + +auto +ReadView::txs_type::end() const -> + iterator const& +{ + if (! end_) + end_ = iterator(view_, view_->txsEnd()); + return *end_; +} + +} // ripple diff --git a/src/ripple/rpc/handlers/LedgerData.cpp b/src/ripple/rpc/handlers/LedgerData.cpp index cd03532064..e0a0153d06 100644 --- a/src/ripple/rpc/handlers/LedgerData.cpp +++ b/src/ripple/rpc/handlers/LedgerData.cpp @@ -80,28 +80,27 @@ Json::Value doLedgerData (RPC::Context& context) Json::Value& nodes = (jvResult[jss::state] = Json::arrayValue); - forEachSLE(*lpLedger, [&] (SLE const& sle) { + for(auto const& sle : lpLedger->sles) + { if (limit-- <= 0) { - auto marker = sle.key(); + auto marker = sle->key(); jvResult[jss::marker] = to_string (--marker); - return false; + break; } if (isBinary) { Json::Value& entry = nodes.append (Json::objectValue); - entry[jss::data] = serializeHex(sle); - entry[jss::index] = to_string (sle.key()); + entry[jss::data] = serializeHex(*sle); + entry[jss::index] = to_string (sle->key()); } else { - Json::Value& entry = nodes.append (sle.getJson (0)); - entry[jss::index] = to_string (sle.key()); + Json::Value& entry = nodes.append (sle->getJson (0)); + entry[jss::index] = to_string (sle->key()); } - - return true; - }); + } return jvResult; } diff --git a/src/ripple/unity/ledger.cpp b/src/ripple/unity/ledger.cpp index fe25d9271c..3d3422c206 100644 --- a/src/ripple/unity/ledger.cpp +++ b/src/ripple/unity/ledger.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include