rippled
PeerReservationTable.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2019 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/overlay/PeerReservationTable.h>
21 
22 #include <ripple/app/rdb/RelationalDatabase.h>
23 #include <ripple/app/rdb/Wallet.h>
24 #include <ripple/basics/Log.h>
25 #include <ripple/json/json_value.h>
26 #include <ripple/protocol/PublicKey.h>
27 #include <ripple/protocol/jss.h>
28 
29 #include <boost/optional.hpp>
30 
31 #include <algorithm>
32 #include <iterator>
33 #include <mutex>
34 #include <string>
35 #include <vector>
36 
37 namespace ripple {
38 
39 auto
40 PeerReservation::toJson() const -> Json::Value
41 {
43  result[jss::node] = toBase58(TokenType::NodePublic, nodeId);
44  if (!description.empty())
45  {
46  result[jss::description] = description;
47  }
48  return result;
49 }
50 
51 auto
53 {
55  {
56  std::lock_guard lock(mutex_);
57  list.reserve(table_.size());
58  std::copy(table_.begin(), table_.end(), std::back_inserter(list));
59  }
60  std::sort(list.begin(), list.end());
61  return list;
62 }
63 
64 // See `ripple/app/main/DBInit.cpp` for the `CREATE TABLE` statement.
65 // It is unfortunate that we do not get to define a function for it.
66 
67 // We choose a `bool` return type to fit in with the error handling scheme
68 // of other functions called from `ApplicationImp::setup`, but we always
69 // return "no error" (`true`) because we can always return an empty table.
70 bool
72 {
73  std::lock_guard lock(mutex_);
74 
75  connection_ = &connection;
76  auto db = connection.checkoutDb();
77  auto table = getPeerReservationTable(*db, journal_);
78  table_.insert(table.begin(), table.end());
79 
80  return true;
81 }
82 
85 {
87 
88  std::lock_guard lock(mutex_);
89 
90  auto hint = table_.find(reservation);
91  if (hint != table_.end())
92  {
93  // The node already has a reservation. Remove it.
94  // `std::unordered_set` does not have an `insert_or_assign` method,
95  // and sadly makes it impossible for us to implement one efficiently:
96  // https://stackoverflow.com/q/49651835/618906
97  // Regardless, we don't expect this function to be called often, or
98  // for the table to be very large, so this less-than-ideal
99  // remove-then-insert is acceptable in order to present a better API.
100  previous = *hint;
101  // We should pick an adjacent location for the insertion hint.
102  // Decrementing may be illegal if the found reservation is at the
103  // beginning. Incrementing is always legal; at worst we'll point to
104  // the end.
105  auto const deleteme = hint;
106  ++hint;
107  table_.erase(deleteme);
108  }
109  table_.insert(hint, reservation);
110 
111  auto db = connection_->checkoutDb();
112  insertPeerReservation(*db, reservation.nodeId, reservation.description);
113 
114  return previous;
115 }
116 
119 {
121 
122  std::lock_guard lock(mutex_);
123 
124  auto const it = table_.find({nodeId});
125  if (it != table_.end())
126  {
127  previous = *it;
128  table_.erase(it);
129  auto db = connection_->checkoutDb();
130  deletePeerReservation(*db, nodeId);
131  }
132 
133  return previous;
134 }
135 
136 } // namespace ripple
ripple::PeerReservationTable::erase
std::optional< PeerReservation > erase(PublicKey const &nodeId)
Definition: PeerReservationTable.cpp:118
ripple::PeerReservationTable::table_
std::unordered_set< PeerReservation, beast::uhash<>, KeyEqual > table_
Definition: PeerReservationTable.h:120
vector
std::back_inserter
T back_inserter(T... args)
iterator
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
std::lock_guard
STL class.
ripple::PeerReservationTable::connection_
DatabaseCon * connection_
Definition: PeerReservationTable.h:119
ripple::PeerReservation::toJson
auto toJson() const -> Json::Value
Definition: PeerReservationTable.cpp:40
std::sort
T sort(T... args)
algorithm
Json
JSON (JavaScript Object Notation).
Definition: json_reader.cpp:27
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::PeerReservation::nodeId
PublicKey nodeId
Definition: PeerReservationTable.h:46
ripple::PeerReservationTable::journal_
beast::Journal journal_
Definition: PeerReservationTable.h:117
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::insertPeerReservation
void insertPeerReservation(soci::session &session, PublicKey const &nodeId, std::string const &description)
insertPeerReservation Adds an entry to the peer reservation table.
Definition: Wallet.cpp:203
ripple::deletePeerReservation
void deletePeerReservation(soci::session &session, PublicKey const &nodeId)
deletePeerReservation Deletes an entry from the peer reservation table.
Definition: Wallet.cpp:217
std::copy
T copy(T... args)
ripple::PeerReservation
Definition: PeerReservationTable.h:43
ripple::getPeerReservationTable
std::unordered_set< PeerReservation, beast::uhash<>, KeyEqual > getPeerReservationTable(soci::session &session, beast::Journal j)
getPeerReservationTable Returns the peer reservation table.
Definition: Wallet.cpp:166
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::PeerReservationTable::mutex_
std::mutex mutex_
Definition: PeerReservationTable.h:118
ripple::PeerReservationTable::list
std::vector< PeerReservation > list() const
Definition: PeerReservationTable.cpp:52
std
STL namespace.
ripple::DatabaseCon
Definition: DatabaseCon.h:81
std::string::empty
T empty(T... args)
ripple::TokenType::NodePublic
@ NodePublic
std::optional
mutex
ripple::PeerReservationTable::insert_or_assign
std::optional< PeerReservation > insert_or_assign(PeerReservation const &reservation)
Definition: PeerReservationTable.cpp:84
ripple::PeerReservation::description
std::string description
Definition: PeerReservationTable.h:47
ripple::PeerReservationTable::load
bool load(DatabaseCon &connection)
Definition: PeerReservationTable.cpp:71
Json::Value
Represents a JSON value.
Definition: json_value.h:145
string