diff --git a/src/txrequest.h b/src/txrequest.h --- a/src/txrequest.h +++ b/src/txrequest.h @@ -117,9 +117,47 @@ * announcements, plus the number of announcements affected by an operation * (amortized O(1) per announcement). */ + +// Avoid littering this header file with implementation details. +class Impl { + friend class TxRequestTracker; + + // The base class is responsible for building the child implementation. + // This is a hack that allows for hiding the concrete implementation details + // from the callsite. + static std::unique_ptr BuildImpl(bool deterministic); + +protected: + using clearExpiredFun = const std::function &; + using emplaceExpiredFun = + const std::function &; + + virtual void ReceivedInv(NodeId peer, const uint256 &txid, bool preferred, + std::chrono::microseconds reqtime) = 0; + virtual void DisconnectedPeer(NodeId peer) = 0; + virtual void ForgetTxId(const uint256 &txid) = 0; + virtual std::vector + GetRequestable(NodeId peer, std::chrono::microseconds now, + clearExpiredFun clearExpired, + emplaceExpiredFun emplaceExpired) = 0; + virtual void RequestedTx(NodeId peer, const uint256 &txid, + std::chrono::microseconds expiry) = 0; + virtual void ReceivedResponse(NodeId peer, const uint256 &txid) = 0; + virtual size_t CountInFlight(NodeId peer) const = 0; + virtual size_t CountCandidates(NodeId peer) const = 0; + virtual size_t Count(NodeId peer) const = 0; + virtual size_t Size() const = 0; + virtual uint64_t ComputePriority(const uint256 &txid, NodeId peer, + bool preferred) const = 0; + virtual void SanityCheck() const = 0; + virtual void + PostGetRequestableSanityCheck(std::chrono::microseconds now) const = 0; + +public: + virtual ~Impl() = default; +}; + class TxRequestTracker { - // Avoid littering this header file with implementation details. - class Impl; const std::unique_ptr m_impl; public: diff --git a/src/txrequest.cpp b/src/txrequest.cpp --- a/src/txrequest.cpp +++ b/src/txrequest.cpp @@ -351,14 +351,10 @@ return ret; } -using clearExpiredFun = const std::function &; -using emplaceExpiredFun = - const std::function &; - } // namespace /** Actual implementation for TxRequestTracker's data structure. */ -class TxRequestTracker::Impl { +class ImplConcrete : public Impl { //! The current sequence number. Increases for every announcement. This is //! used to sort txid returned by GetRequestable in announcement order. SequenceNumber m_current_sequence{0}; @@ -624,7 +620,7 @@ } public: - Impl(bool deterministic) + ImplConcrete(bool deterministic) : m_computer(deterministic), // Explicitly initialize m_index as we need to pass a reference to // m_computer to ByTxHashViewExtractor. @@ -637,8 +633,8 @@ // Disable copying and assigning (a default copy won't work due the stateful // ByTxIdViewExtractor). - Impl(const Impl &) = delete; - Impl &operator=(const Impl &) = delete; + ImplConcrete(const ImplConcrete &) = delete; + ImplConcrete &operator=(const ImplConcrete &) = delete; void DisconnectedPeer(NodeId peer) { auto &index = m_index.get(); @@ -861,8 +857,12 @@ } }; +std::unique_ptr Impl::BuildImpl(bool deterministic) { + return std::unique_ptr(new ImplConcrete(deterministic)); +} + TxRequestTracker::TxRequestTracker(bool deterministic) - : m_impl{std::make_unique(deterministic)} {} + : m_impl{Impl::BuildImpl(deterministic)} {} TxRequestTracker::~TxRequestTracker() = default; @@ -911,13 +911,13 @@ std::vector TxRequestTracker::GetRequestable( NodeId peer, std::chrono::microseconds now, std::vector> *expired) { - clearExpiredFun clearExpired = [expired]() { + Impl::clearExpiredFun clearExpired = [expired]() { if (expired) { expired->clear(); } }; - emplaceExpiredFun emplaceExpired = [expired](const NodeId &nodeid, - const uint256 &txid) { + Impl::emplaceExpiredFun emplaceExpired = [expired](const NodeId &nodeid, + const uint256 &txid) { if (expired) { expired->emplace_back(nodeid, TxId(txid)); }