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