#pragma once #include #include #include #include #include #include #include #include #include namespace xrpl { class DatabaseCon; // Value type for reservations. struct PeerReservation final { public: PublicKey nodeId; std::string description{}; auto toJson() const -> Json::Value; template friend void hash_append(Hasher& h, PeerReservation const& x) noexcept { using beast::hash_append; hash_append(h, x.nodeId); } friend bool operator<(PeerReservation const& a, PeerReservation const& b) { return a.nodeId < b.nodeId; } }; // TODO: When C++20 arrives, take advantage of "equivalence" instead of // "equality". Add an overload for `(PublicKey, PeerReservation)`, and just // pass a `PublicKey` directly to `unordered_set.find`. struct KeyEqual final { bool operator()(PeerReservation const& lhs, PeerReservation const& rhs) const { return lhs.nodeId == rhs.nodeId; } }; class PeerReservationTable final { public: explicit PeerReservationTable( beast::Journal journal = beast::Journal(beast::Journal::getNullSink())) : journal_(journal) { } std::vector list() const; bool contains(PublicKey const& nodeId) { std::lock_guard lock(this->mutex_); return table_.find({nodeId}) != table_.end(); } // Because `ApplicationImp` has two-phase initialization, so must we. // Our dependencies are not prepared until the second phase. bool load(DatabaseCon& connection); /** * @return the replaced reservation if it existed * @throw soci::soci_error */ std::optional insert_or_assign(PeerReservation const& reservation); /** * @return the erased reservation if it existed */ std::optional erase(PublicKey const& nodeId); private: beast::Journal mutable journal_; std::mutex mutable mutex_; DatabaseCon* connection_; std::unordered_set, KeyEqual> table_; }; } // namespace xrpl