xrpld
Loading...
Searching...
No Matches
Bootcache.cpp
1#include <xrpld/peerfinder/detail/Bootcache.h>
2
3#include <xrpld/peerfinder/PeerfinderManager.h>
4#include <xrpld/peerfinder/detail/Store.h>
5#include <xrpld/peerfinder/detail/Tuning.h>
6#include <xrpld/peerfinder/detail/iosformat.h>
7
8#include <xrpl/basics/Log.h>
9#include <xrpl/beast/net/IPEndpoint.h>
10#include <xrpl/beast/utility/Journal.h>
11#include <xrpl/beast/utility/PropertyStream.h>
12#include <xrpl/beast/utility/instrumentation.h>
13
14#include <algorithm>
15#include <cstdint>
16#include <cstdlib>
17#include <vector>
18
19namespace xrpl::PeerFinder {
20
22 : store_(store), clock_(clock), journal_(journal), whenUpdate_(clock_.now())
23
24{
25}
26
31
32bool
34{
35 return map_.empty();
36}
37
38Bootcache::map_type::size_type
40{
41 return map_.size();
42}
43
46{
47 return const_iterator(map_.right.begin());
48}
49
52{
53 return const_iterator(map_.right.begin());
54}
55
58{
59 return const_iterator(map_.right.end());
60}
61
64{
65 return const_iterator(map_.right.end());
66}
67
68void
70{
71 map_.clear();
72 needsUpdate_ = true;
73}
74
75//--------------------------------------------------------------------------
76
77void
79{
80 clear();
81 auto const n(store_.load([this](beast::IP::Endpoint const& endpoint, int valence) {
82 auto const result(this->map_.insert(value_type(endpoint, valence)));
83 if (!result.second)
84 {
85 JLOG(this->journal_.error()) << beast::Leftw(18) << "Bootcache discard " << endpoint;
86 }
87 }));
88
89 if (n > 0)
90 {
91 JLOG(journal_.info()) << beast::Leftw(18) << "Bootcache loaded " << n
92 << ((n > 1) ? " addresses" : " address");
93 prune();
94 }
95}
96
97bool
99{
100 auto const result(map_.insert(value_type(endpoint, 0)));
101 if (result.second)
102 {
103 JLOG(journal_.trace()) << beast::Leftw(18) << "Bootcache insert " << endpoint;
104 prune();
106 }
107 return result.second;
108}
109
110bool
112{
113 auto result(map_.insert(value_type(endpoint, kStaticValence)));
114
115 if (!result.second && (result.first->right.valence() < kStaticValence))
116 {
117 // An existing entry has too low a valence, replace it
118 map_.erase(result.first);
119 result = map_.insert(value_type(endpoint, kStaticValence));
120 }
121
122 if (result.second)
123 {
124 JLOG(journal_.trace()) << beast::Leftw(18) << "Bootcache insert " << endpoint;
125 prune();
127 }
128 return result.second;
129}
130
131void
133{
134 auto result(map_.insert(value_type(endpoint, 1)));
135 if (result.second)
136 {
137 prune();
138 }
139 else
140 {
141 Entry entry(result.first->right);
142 entry.valence() = std::max(entry.valence(), 0);
143 ++entry.valence();
144 map_.erase(result.first);
145 result = map_.insert(value_type(endpoint, entry));
146 XRPL_ASSERT(result.second, "xrpl::PeerFinder::Bootcache::onSuccess : endpoint inserted");
147 }
148 Entry const& entry(result.first->right);
149 JLOG(journal_.info()) << beast::Leftw(18) << "Bootcache connect " << endpoint << " with "
150 << entry.valence() << ((entry.valence() > 1) ? " successes" : " success");
152}
153
154void
156{
157 auto result(map_.insert(value_type(endpoint, -1)));
158 if (result.second)
159 {
160 prune();
161 }
162 else
163 {
164 Entry entry(result.first->right);
165 entry.valence() = std::min(entry.valence(), 0);
166 --entry.valence();
167 map_.erase(result.first);
168 result = map_.insert(value_type(endpoint, entry));
169 XRPL_ASSERT(result.second, "xrpl::PeerFinder::Bootcache::onFailure : endpoint inserted");
170 }
171 Entry const& entry(result.first->right);
172 auto const n(std::abs(entry.valence()));
173 JLOG(journal_.debug()) << beast::Leftw(18) << "Bootcache failed " << endpoint << " with " << n
174 << ((n > 1) ? " attempts" : " attempt");
176}
177
178void
183
184//--------------------------------------------------------------------------
185
186void
188{
189 beast::PropertyStream::Set entries("entries", map);
190 for (auto iter = map_.right.begin(); iter != map_.right.end(); ++iter)
191 {
192 beast::PropertyStream::Map entry(entries);
193 entry["endpoint"] = iter->get_left().toString();
194 entry["valence"] = std::int32_t(iter->get_right().valence());
195 }
196}
197
198// Checks the cache size and prunes if its over the limit.
199void
201{
203 return;
204
205 // Calculate the amount to remove
206 auto count((size() * Tuning::kBootcachePrunePercent) / 100);
207 decltype(count) pruned(0);
208
209 // Work backwards because bimap doesn't handle
210 // erasing using a reverse iterator very well.
211 //
212 for (auto iter(map_.right.end()); count-- > 0 && iter != map_.right.begin(); ++pruned)
213 {
214 --iter;
215 beast::IP::Endpoint const& endpoint(iter->get_left());
216 Entry const& entry(iter->get_right());
217 JLOG(journal_.trace()) << beast::Leftw(18) << "Bootcache pruned" << endpoint
218 << " at valence " << entry.valence();
219 iter = map_.right.erase(iter);
220 }
221
222 JLOG(journal_.debug()) << beast::Leftw(18) << "Bootcache pruned " << pruned << " entries total";
223}
224
225// Updates the Store with the current set of entries if needed.
226void
228{
229 if (!needsUpdate_)
230 return;
232 list.reserve(map_.size());
233 for (auto const& e : map_)
234 {
235 Store::Entry se;
236 se.endpoint = e.get_left();
237 se.valence = e.get_right().valence();
238 list.push_back(se);
239 }
240 store_.save(list);
241 // Reset the flag and cooldown timer
242 needsUpdate_ = false;
244}
245
246// Checks the clock and calls update if we are off the cooldown.
247void
249{
250 if (needsUpdate_ && whenUpdate_ < clock_.now())
251 update();
252}
253
254// Called when changes to an entry will affect the Store.
255void
257{
258 needsUpdate_ = true;
259 checkUpdate();
260}
261
262} // namespace xrpl::PeerFinder
A version-independent IP address and port combination.
Definition IPEndpoint.h:17
A generic endpoint for log messages.
Definition Journal.h:38
bool insert(beast::IP::Endpoint const &endpoint)
Add a newly-learned address to the cache.
Definition Bootcache.cpp:98
static constexpr int kStaticValence
Definition Bootcache.h:100
void periodicActivity()
Stores the cache in the persistent database on a timer.
const_iterator cbegin() const
Definition Bootcache.cpp:51
const_iterator cend() const
Definition Bootcache.cpp:63
void onFailure(beast::IP::Endpoint const &endpoint)
Called when an outbound connection attempt fails to handshake.
beast::Journal journal_
Definition Bootcache.h:91
void onWrite(beast::PropertyStream::Map &map)
Write the cache state to the property stream.
void onSuccess(beast::IP::Endpoint const &endpoint)
Called when an outbound connection handshake completes.
map_type::value_type value_type
Definition Bootcache.h:70
const_iterator begin() const
IP::Endpoint iterators that traverse in decreasing valence.
Definition Bootcache.cpp:45
void load()
Load the persisted data from the Store into the container.
Definition Bootcache.cpp:78
bool insertStatic(beast::IP::Endpoint const &endpoint)
Add a staticallyconfigured address to the cache.
clock_type::time_point whenUpdate_
Definition Bootcache.h:94
const_iterator end() const
Definition Bootcache.cpp:57
bool empty() const
Returns true if the cache is empty.
Definition Bootcache.cpp:33
map_type::size_type size() const
Returns the number of entries in the cache.
Definition Bootcache.cpp:39
Bootcache(Store &store, clock_type &clock, beast::Journal journal)
Definition Bootcache.cpp:21
Abstract persistence for PeerFinder data.
Definition Store.h:7
T max(T... args)
T min(T... args)
static std::chrono::seconds const kBootcacheCooldownTime(60)
beast::AbstractClock< std::chrono::steady_clock > clock_type
T push_back(T... args)
T reserve(T... args)
Left justifies a field at the specified width.
Definition iosformat.h:14
beast::IP::Endpoint endpoint
Definition Store.h:21