From b7f07aed0046a4beb10bbf5bc964580b1859ac00 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 29 Jun 2015 07:34:01 -0700 Subject: [PATCH] Add BasicView::txs memberspace interface --- src/ripple/app/ledger/Ledger.cpp | 107 ++++++++ src/ripple/app/ledger/Ledger.h | 37 ++- src/ripple/app/ledger/MetaView.h | 19 +- src/ripple/app/ledger/impl/MetaView.cpp | 93 ++++++- src/ripple/ledger/View.h | 308 +++++++++++++++++++++++- 5 files changed, 546 insertions(+), 18 deletions(-) diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index f159f17237..c318747706 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -632,6 +632,39 @@ bool Ledger::saveValidatedLedger (bool current) return true; } +//------------------------------------------------------------------------------ + +std::shared_ptr +deserializeTx (SHAMapItem const& item) +{ + SerialIter sit(item.slice()); + return std::make_shared(sit); +} + +std::pair, std::shared_ptr< + STObject const>> +deserializeTxPlusMeta (SHAMapItem const& item) +{ + std::pair, std::shared_ptr< + STObject const>> result; + SerialIter sit(item.slice()); + { + SerialIter s(sit.getSlice( + sit.getVLDataLength())); + result.first = std::make_shared< + STTx const>(s); + } + { + SerialIter s(sit.getSlice( + sit.getVLDataLength())); + result.second = std::make_shared< + STObject const>(s, sfMetadata); + } + return result; +} + /* * Load a ledger from the database. * @@ -923,6 +956,80 @@ Ledger::read (Keylet const& k) const return std::move(sle); } +//------------------------------------------------------------------------------ + +class Ledger::tx_iterator_impl + : public BasicView::iterator_impl +{ +private: + SHAMap::iterator iter_; + +public: + explicit + tx_iterator_impl (SHAMap::iterator iter) + : iter_(iter) + { + } + + std::unique_ptr + copy() const override + { + return std::make_unique< + tx_iterator_impl>( + iter_); + } + + bool + equal (iterator_impl const& impl) const override + { + auto const& other = dynamic_cast< + tx_iterator_impl const&>(impl); + return iter_ == other.iter_; + } + + void + increment() override + { + ++iter_; + } + + txs_type::value_type + dereference() const override + { + return deserializeTxPlusMeta(**iter_); + } +}; + +bool +Ledger::txEmpty() const +{ + return txMap_->getHash().isZero(); +} + +auto +Ledger::txBegin() const -> + std::unique_ptr +{ + // Can't iterate open Ledger objects + // because they don't have the metadata! + assert(closed()); + return std::make_unique< + tx_iterator_impl>(txMap_->begin()); +} + +auto +Ledger::txEnd() const -> + std::unique_ptr +{ + // Can't iterate open Ledger objects + // because they don't have the metadata! + assert(closed()); + return std::make_unique< + tx_iterator_impl>(txMap_->end()); +} + +//------------------------------------------------------------------------------ + bool Ledger::unchecked_erase( uint256 const& key) diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 9a6c8493c7..38b7c54d67 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -140,6 +140,15 @@ public: std::shared_ptr read (Keylet const& k) const override; + bool + txEmpty() const override; + + std::unique_ptr + txBegin() const override; + + std::unique_ptr + txEnd() const override; + bool unchecked_erase (uint256 const& key) override; @@ -418,14 +427,15 @@ public: static std::map< std::uint32_t, std::pair > getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq); -protected: +private: + class tx_iterator_impl; + void saveValidatedLedgerAsync(Job&, bool current) { saveValidatedLedger(current); } bool saveValidatedLedger (bool current); -private: // ledger close flags static const std::uint32_t sLCF_NoConsensusTime = 1; @@ -485,6 +495,29 @@ private: // //------------------------------------------------------------------------------ +/** Deserialize a SHAMapItem containing a single STTx + + Throw: + + May throw on deserializaton error +*/ +std::shared_ptr +deserializeTx (SHAMapItem const& item); + +/** Deserialize a SHAMapItem containing STTx + STObject metadata + + The SHAMap must contain two variable length + serialization objects. + + Throw: + + May throw on deserializaton error +*/ +std::pair, std::shared_ptr< + STObject const>> +deserializeTxPlusMeta (SHAMapItem const& item); + std::tuple loadLedgerHelper(std::string const& sqlSuffix); diff --git a/src/ripple/app/ledger/MetaView.h b/src/ripple/app/ledger/MetaView.h index 544fb1bcac..ccfed404d3 100644 --- a/src/ripple/app/ledger/MetaView.h +++ b/src/ripple/app/ledger/MetaView.h @@ -84,8 +84,9 @@ private: // The SLEs and Serializers in here are // shared between copy-constructed instances using item_list = std::map; - using tx_list = hardened_hash_map< - uint256, std::pair, std::shared_ptr< Serializer const>>>; @@ -94,7 +95,7 @@ private: BasicView const& base_; ViewFlags flags_ = tapNONE; ViewInfo info_; - tx_list txs_; + tx_map txs_; item_list items_; std::uint32_t destroyedCoins_ = 0; boost::optional deliverAmount_; @@ -193,6 +194,16 @@ public: std::shared_ptr read (Keylet const& k) const override; + virtual + bool + txEmpty() const override; + + std::unique_ptr + txBegin() const override; + + std::unique_ptr + txEnd() const override; + bool unchecked_erase( uint256 const& key) override; @@ -301,6 +312,8 @@ public: } private: + class tx_iterator_impl; + static bool threadTx (TxMeta& meta, diff --git a/src/ripple/app/ledger/impl/MetaView.cpp b/src/ripple/app/ledger/impl/MetaView.cpp index c8e2ee8365..092af6f312 100644 --- a/src/ripple/app/ledger/impl/MetaView.cpp +++ b/src/ripple/app/ledger/impl/MetaView.cpp @@ -170,6 +170,93 @@ MetaView::read (Keylet const& k) const return sle; } +//------------------------------------------------------------------------------ + +class MetaView::tx_iterator_impl + : public BasicView::iterator_impl +{ +private: + bool metadata_; + tx_map::const_iterator iter_; + +public: + explicit + tx_iterator_impl (bool metadata, + tx_map::const_iterator iter) + : metadata_(metadata) + , iter_(iter) + { + } + + std::unique_ptr + copy() const override + { + return std::make_unique< + tx_iterator_impl>( + metadata_, iter_); + } + + bool + equal (iterator_impl const& impl) const override + { + auto const& other = dynamic_cast< + tx_iterator_impl const&>(impl); + return iter_ == other.iter_; + } + + void + increment() override + { + ++iter_; + } + + txs_type::value_type + dereference() const override + { + txs_type::value_type result; + { + SerialIter sit( + iter_->second.first->slice()); + result.first = std::make_shared< + STTx const>(sit); + } + if (metadata_) + { + SerialIter sit( + iter_->second.second->slice()); + result.second = std::make_shared< + STObject const>(sit, sfMetadata); + } + return result; + } +}; + +bool +MetaView::txEmpty() const +{ + return txs_.empty(); +} + +auto +MetaView::txBegin() const -> + std::unique_ptr +{ + return std::make_unique< + tx_iterator_impl>( + closed(), txs_.cbegin()); +} + +auto +MetaView::txEnd() const -> + std::unique_ptr +{ + return std::make_unique< + tx_iterator_impl>( + closed(), txs_.cend()); +} + +//------------------------------------------------------------------------------ + bool MetaView::unchecked_erase (uint256 const& key) { @@ -293,10 +380,8 @@ MetaView::txInsert (uint256 const& key, if (txs_.count(key) || base_.txExists(key)) LogicError("duplicate_tx: " + to_string(key)); - txs_.emplace(std::piecewise_construct, - std::forward_as_tuple(key), - std::forward_as_tuple( - txn, metaData)); + txs_.emplace(key, std::make_pair( + txn, metaData)); } std::vector diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h index e2fb5a2177..34ce363613 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -99,15 +101,27 @@ struct ViewInfo and transaction items. There is no checkpointing or calculation of metadata. - A raw interace is provided for mutable ledgers. + A raw interace is provided for mutable ledgers, + this is used internally by implementations and + should not be called directly. */ +// VFALCO Rename unchecked functions to raw class BasicView { +protected: + class iterator_impl; + public: using key_type = uint256; + using mapped_type = std::shared_ptr; + BasicView() + : txs(*this) + { + } + virtual ~BasicView() = default; /** Returns information about the ledger. */ @@ -191,6 +205,21 @@ public: std::shared_ptr read (Keylet const& k) const = 0; + // used by the implementation + virtual + bool + txEmpty() const = 0; + + // used by the implementation + virtual + std::unique_ptr + txBegin() const = 0; + + // used by the implementation + virtual + std::unique_ptr + txEnd() const = 0; + /** Unconditionally erase a state item. Requirements: @@ -266,7 +295,11 @@ public: std::size_t txCount() const = 0; - /** Returns `true` if a tx exists in the tx map. */ + /** Returns `true` if a tx exists in the tx map. + + A tx exists in the map if it is part of the + base ledger, or if it is a newly inserted tx. + */ virtual bool txExists (uint256 const& key) const = 0; @@ -290,9 +323,62 @@ public: //-------------------------------------------------------------------------- + // A Forward Range container + // representing the list of transactions + // + class txs_type + { + private: + friend class BasicView; + + BasicView& view_; + + explicit + txs_type (BasicView& view) + : view_ (view) + { + } + + public: + /** ForwardIterator to access transactions */ + class iterator; + using const_iterator = iterator; + + /** Transaction followed by optional metadata. */ + using value_type = std::pair< + std::shared_ptr, + std::shared_ptr>; + + txs_type() = delete; + txs_type (txs_type const&) = delete; + txs_type& operator= (txs_type const&) = delete; + + bool + empty() const; + + /** Return iterator to the beginning of the tx list. + + Meets the requirements of `ForwardIterator` + */ + iterator + begin() const; + + /** Return iterator to one past the end of the tx list. + + Meets the requirements of `ForwardIterator` + */ + iterator + end() const; + }; + + // Memberspace + // The list of transactions. + txs_type const txs; + + //-------------------------------------------------------------------------- + // Called to adjust returned balances // This is required to support PaymentView - virtual STAmount balanceHook (AccountID const& account, @@ -305,6 +391,175 @@ public: //------------------------------------------------------------------------------ +class BasicView::iterator_impl +{ +public: + iterator_impl() = default; + iterator_impl(iterator_impl const&) = delete; + iterator_impl& operator=(iterator_impl const&) = delete; + + virtual + ~iterator_impl() = default; + + virtual + std::unique_ptr + copy() const = 0; + + virtual + bool + equal (iterator_impl const& impl) const = 0; + + virtual + void + increment() = 0; + + virtual + txs_type::value_type + dereference() const = 0; +}; + +//------------------------------------------------------------------------------ + +class BasicView::txs_type::iterator +{ +public: + using value_type = + BasicView::txs_type::value_type; + + using pointer = value_type const*; + + using reference = value_type const&; + + using difference_type = + std::ptrdiff_t; + + using iterator_category = + std::forward_iterator_tag; + + iterator() = default; + + iterator (iterator const& other) + : view_ (other.view_) + , impl_ (other.impl_->copy()) + , cache_ (other.cache_) + { + } + + iterator (iterator&& other) + : view_ (other.view_) + , impl_ (std::move(other.impl_)) + , cache_ (std::move(other.cache_)) + { + } + + // Used by the implementation + explicit + iterator (BasicView const& view, + std::unique_ptr< + iterator_impl> impl) + : view_ (&view) + , impl_ (std::move(impl)) + { + } + + iterator& + operator= (iterator const& other) + { + if (this == &other) + return *this; + view_ = other.view_; + impl_ = other.impl_->copy(); + cache_ = other.cache_; + return *this; + } + + iterator& + operator= (iterator&& other) + { + view_ = other.view_; + impl_ = std::move(other.impl_); + cache_ = std::move(other.cache_); + return *this; + } + + bool + operator== (iterator const& other) const + { + assert(view_ == other.view_); + return impl_->equal(*other.impl_); + } + + bool + operator!= (iterator const& other) const + { + return ! (*this == other); + } + + // Can throw + reference + operator*() const + { + if (! cache_) + cache_ = impl_->dereference(); + return *cache_; + } + + // Can throw + pointer + operator->() const + { + return &**this; + } + + iterator& + operator++() + { + impl_->increment(); + cache_ = boost::none; + return *this; + } + + iterator + operator++(int) + { + iterator prev(*view_, + impl_->copy()); + prev.cache_ = std::move(cache_); + ++(*this); + return prev; + } + +private: + BasicView const* view_ = nullptr; + std::unique_ptr impl_; + boost::optional mutable cache_; +}; + +inline +bool +BasicView::txs_type::empty() const +{ + return view_.txEmpty(); +} + +inline +auto +BasicView::txs_type::begin() const -> + iterator +{ + return iterator(view_, view_.txBegin()); +} + +inline +auto +BasicView::txs_type::end() const -> + iterator +{ + return iterator(view_, view_.txEnd()); +} + +//------------------------------------------------------------------------------ + enum ViewFlags { tapNONE = 0x00, @@ -327,9 +582,9 @@ enum ViewFlags }; inline -ViewFlags operator|( - ViewFlags const& lhs, - ViewFlags const& rhs) +ViewFlags +operator|(ViewFlags const& lhs, + ViewFlags const& rhs) { return static_cast( static_cast(lhs) | @@ -338,9 +593,8 @@ ViewFlags operator|( inline ViewFlags -operator&( - ViewFlags const& lhs, - ViewFlags const& rhs) +operator&(ViewFlags const& lhs, + ViewFlags const& rhs) { return static_cast( static_cast(lhs) & @@ -532,6 +786,24 @@ public: return view_.read(k); } + bool + txEmpty() const override + { + return view_.txEmpty(); + } + + std::unique_ptr + txBegin() const override + { + return view_.txBegin(); + } + + std::unique_ptr + txEnd() const override + { + return view_.txEnd(); + } + bool unchecked_erase( uint256 const& key) override @@ -637,6 +909,24 @@ public: return view_.read(k); } + bool + txEmpty() const override + { + return view_.txEmpty(); + } + + std::unique_ptr + txBegin() const override + { + return view_.txBegin(); + } + + std::unique_ptr + txEnd() const override + { + return view_.txEnd(); + } + bool unchecked_erase( uint256 const& key) override