rippled
Livecache.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 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 #ifndef RIPPLE_PEERFINDER_LIVECACHE_H_INCLUDED
21 #define RIPPLE_PEERFINDER_LIVECACHE_H_INCLUDED
22 
23 #include <ripple/basics/Log.h>
24 #include <ripple/basics/random.h>
25 #include <ripple/beast/container/aged_map.h>
26 #include <ripple/beast/utility/maybe_const.h>
27 #include <ripple/peerfinder/PeerfinderManager.h>
28 #include <ripple/peerfinder/impl/Tuning.h>
29 #include <ripple/peerfinder/impl/iosformat.h>
30 #include <boost/intrusive/list.hpp>
31 #include <boost/iterator/transform_iterator.hpp>
32 
33 #include <algorithm>
34 
35 namespace ripple {
36 namespace PeerFinder {
37 
38 template <class>
39 class Livecache;
40 
41 namespace detail {
42 
44 {
45 public:
46  explicit LivecacheBase() = default;
47 
48 protected:
49  struct Element : boost::intrusive::list_base_hook<>
50  {
51  Element(Endpoint const& endpoint_) : endpoint(endpoint_)
52  {
53  }
54 
56  };
57 
58  using list_type = boost::intrusive::
59  make_list<Element, boost::intrusive::constant_time_size<false>>::type;
60 
61 public:
66  template <bool IsConst>
67  class Hop
68  {
69  public:
70  // Iterator transformation to extract the endpoint from Element
71  struct Transform
72  {
75 
76  explicit Transform() = default;
77 
78  Endpoint const&
79  operator()(Element const& e) const
80  {
81  return e.endpoint;
82  }
83  };
84 
85  public:
86  using iterator = boost::
87  transform_iterator<Transform, typename list_type::const_iterator>;
88 
90 
91  using reverse_iterator = boost::transform_iterator<
92  Transform,
93  typename list_type::const_reverse_iterator>;
94 
96 
97  iterator
98  begin() const
99  {
100  return iterator(m_list.get().cbegin(), Transform());
101  }
102 
103  iterator
104  cbegin() const
105  {
106  return iterator(m_list.get().cbegin(), Transform());
107  }
108 
109  iterator
110  end() const
111  {
112  return iterator(m_list.get().cend(), Transform());
113  }
114 
115  iterator
116  cend() const
117  {
118  return iterator(m_list.get().cend(), Transform());
119  }
120 
122  rbegin() const
123  {
124  return reverse_iterator(m_list.get().crbegin(), Transform());
125  }
126 
128  crbegin() const
129  {
130  return reverse_iterator(m_list.get().crbegin(), Transform());
131  }
132 
134  rend() const
135  {
136  return reverse_iterator(m_list.get().crend(), Transform());
137  }
138 
140  crend() const
141  {
142  return reverse_iterator(m_list.get().crend(), Transform());
143  }
144 
145  // move the element to the end of the container
146  void
148  {
149  auto& e(const_cast<Element&>(*pos.base()));
150  m_list.get().erase(m_list.get().iterator_to(e));
151  m_list.get().push_back(e);
152  }
153 
154  private:
155  explicit Hop(
157  : m_list(list)
158  {
159  }
160 
161  friend class LivecacheBase;
162 
166  };
167 
168 protected:
169  // Work-around to call Hop's private constructor from Livecache
170  template <bool IsConst>
171  static Hop<IsConst>
173  {
174  return Hop<IsConst>(list);
175  }
176 };
177 
178 } // namespace detail
179 
180 //------------------------------------------------------------------------------
181 
194 template <class Allocator = std::allocator<char>>
195 class Livecache : protected detail::LivecacheBase
196 {
197 private:
198  using cache_type = beast::aged_map<
200  Element,
203  Allocator>;
204 
207 
208 public:
209  using allocator_type = Allocator;
210 
212  Livecache(
213  clock_type& clock,
214  beast::Journal journal,
215  Allocator alloc = Allocator());
216 
217  //
218  // Iteration by hops
219  //
220  // The range [begin, end) provides a sequence of list_type
221  // where each list contains endpoints at a given hops.
222  //
223 
224  class hops_t
225  {
226  private:
227  // An endpoint at hops=0 represents the local node.
228  // Endpoints coming in at maxHops are stored at maxHops +1,
229  // but not given out (since they would exceed maxHops). They
230  // are used for automatic connection attempts.
231  //
234 
235  template <bool IsConst>
236  struct Transform
237  {
238  using first_argument = typename lists_type::value_type;
239  using result_type = Hop<IsConst>;
240 
241  explicit Transform() = default;
242 
243  Hop<IsConst>
245  IsConst,
246  typename lists_type::value_type>::type& list) const
247  {
248  return make_hop<IsConst>(list);
249  }
250  };
251 
252  public:
253  using iterator = boost::
254  transform_iterator<Transform<false>, typename lists_type::iterator>;
255 
256  using const_iterator = boost::transform_iterator<
258  typename lists_type::const_iterator>;
259 
260  using reverse_iterator = boost::transform_iterator<
262  typename lists_type::reverse_iterator>;
263 
264  using const_reverse_iterator = boost::transform_iterator<
266  typename lists_type::const_reverse_iterator>;
267 
268  iterator
270  {
271  return iterator(m_lists.begin(), Transform<false>());
272  }
273 
275  begin() const
276  {
278  }
279 
281  cbegin() const
282  {
284  }
285 
286  iterator
287  end()
288  {
289  return iterator(m_lists.end(), Transform<false>());
290  }
291 
293  end() const
294  {
296  }
297 
299  cend() const
300  {
302  }
303 
306  {
308  }
309 
311  rbegin() const
312  {
314  }
315 
317  crbegin() const
318  {
320  }
321 
324  {
326  }
327 
329  rend() const
330  {
332  }
333 
335  crend() const
336  {
338  }
339 
341  void
342  shuffle();
343 
345  histogram() const;
346 
347  private:
348  explicit hops_t(Allocator const& alloc);
349 
350  void
351  insert(Element& e);
352 
353  // Reinsert e at a new hops
354  void
355  reinsert(Element& e, std::uint32_t hops);
356 
357  void
358  remove(Element& e);
359 
360  friend class Livecache;
363  } hops;
364 
366  bool
367  empty() const
368  {
369  return m_cache.empty();
370  }
371 
373  typename cache_type::size_type
374  size() const
375  {
376  return m_cache.size();
377  }
378 
380  void
381  expire();
382 
384  void
385  insert(Endpoint const& ep);
386 
388  void
390 };
391 
392 //------------------------------------------------------------------------------
393 
394 template <class Allocator>
396  clock_type& clock,
397  beast::Journal journal,
398  Allocator alloc)
399  : m_journal(journal), m_cache(clock, alloc), hops(alloc)
400 {
401 }
402 
403 template <class Allocator>
404 void
406 {
407  std::size_t n(0);
408  typename cache_type::time_point const expired(
410  for (auto iter(m_cache.chronological.begin());
411  iter != m_cache.chronological.end() && iter.when() <= expired;)
412  {
413  Element& e(iter->second);
414  hops.remove(e);
415  iter = m_cache.erase(iter);
416  ++n;
417  }
418  if (n > 0)
419  {
420  JLOG(m_journal.debug()) << beast::leftw(18) << "Livecache expired " << n
421  << ((n > 1) ? " entries" : " entry");
422  }
423 }
424 
425 template <class Allocator>
426 void
428 {
429  // The caller already incremented hop, so if we got a
430  // message at maxHops we will store it at maxHops + 1.
431  // This means we won't give out the address to other peers
432  // but we will use it to make connections and hand it out
433  // when redirecting.
434  //
435  assert(ep.hops <= (Tuning::maxHops + 1));
436  auto result = m_cache.emplace(ep.address, ep);
437  Element& e(result.first->second);
438  if (result.second)
439  {
440  hops.insert(e);
441  JLOG(m_journal.debug()) << beast::leftw(18) << "Livecache insert "
442  << ep.address << " at hops " << ep.hops;
443  return;
444  }
445  else if (!result.second && (ep.hops > e.endpoint.hops))
446  {
447  // Drop duplicates at higher hops
448  std::size_t const excess(ep.hops - e.endpoint.hops);
449  JLOG(m_journal.trace()) << beast::leftw(18) << "Livecache drop "
450  << ep.address << " at hops +" << excess;
451  return;
452  }
453 
454  m_cache.touch(result.first);
455 
456  // Address already in the cache so update metadata
457  if (ep.hops < e.endpoint.hops)
458  {
459  hops.reinsert(e, ep.hops);
460  JLOG(m_journal.debug()) << beast::leftw(18) << "Livecache update "
461  << ep.address << " at hops " << ep.hops;
462  }
463  else
464  {
465  JLOG(m_journal.trace()) << beast::leftw(18) << "Livecache refresh "
466  << ep.address << " at hops " << ep.hops;
467  }
468 }
469 
470 template <class Allocator>
471 void
473 {
474  typename cache_type::time_point const expired(
476  map["size"] = size();
477  map["hist"] = hops.histogram();
478  beast::PropertyStream::Set set("entries", map);
479  for (auto iter(m_cache.cbegin()); iter != m_cache.cend(); ++iter)
480  {
481  auto const& e(iter->second);
483  item["hops"] = e.endpoint.hops;
484  item["address"] = e.endpoint.address.to_string();
486  ss << (iter.when() - expired).count();
487  item["expires"] = ss.str();
488  }
489 }
490 
491 //------------------------------------------------------------------------------
492 
493 template <class Allocator>
494 void
496 {
497  for (auto& list : m_lists)
498  {
500  v.reserve(list.size());
501  std::copy(list.begin(), list.end(), std::back_inserter(v));
502  std::shuffle(v.begin(), v.end(), default_prng());
503  list.clear();
504  for (auto& e : v)
505  list.push_back(e);
506  }
507 }
508 
509 template <class Allocator>
512 {
513  std::string s;
514  for (auto const& h : m_hist)
515  {
516  if (!s.empty())
517  s += ", ";
518  s += std::to_string(h);
519  }
520  return s;
521 }
522 
523 template <class Allocator>
525 {
526  std::fill(m_hist.begin(), m_hist.end(), 0);
527 }
528 
529 template <class Allocator>
530 void
532 {
533  assert(e.endpoint.hops <= Tuning::maxHops + 1);
534  // This has security implications without a shuffle
535  m_lists[e.endpoint.hops].push_front(e);
536  ++m_hist[e.endpoint.hops];
537 }
538 
539 template <class Allocator>
540 void
542 {
543  assert(numHops <= Tuning::maxHops + 1);
544 
545  auto& list = m_lists[e.endpoint.hops];
546  list.erase(list.iterator_to(e));
547 
548  --m_hist[e.endpoint.hops];
549 
550  e.endpoint.hops = numHops;
551  insert(e);
552 }
553 
554 template <class Allocator>
555 void
557 {
558  --m_hist[e.endpoint.hops];
559 
560  auto& list = m_lists[e.endpoint.hops];
561  list.erase(list.iterator_to(e));
562 }
563 
564 } // namespace PeerFinder
565 } // namespace ripple
566 
567 #endif
ripple::PeerFinder::Livecache::m_journal
beast::Journal m_journal
Definition: Livecache.h:205
ripple::PeerFinder::detail::LivecacheBase::Hop::reverse_iterator
boost::transform_iterator< Transform, typename list_type::const_reverse_iterator > reverse_iterator
Definition: Livecache.h:93
beast::detail::aged_ordered_container::empty
bool empty() const noexcept
Definition: aged_ordered_container.h:808
ripple::PeerFinder::Livecache::hops_t::histogram
std::string histogram() const
Definition: Livecache.h:511
ripple::PeerFinder::Livecache::hops_t::rbegin
const_reverse_iterator rbegin() const
Definition: Livecache.h:311
std::chrono::steady_clock
ripple::PeerFinder::Livecache::hops_t::Transform
Definition: Livecache.h:236
ripple::PeerFinder::Livecache::hops_t::Transform::operator()
Hop< IsConst > operator()(typename beast::maybe_const< IsConst, typename lists_type::value_type >::type &list) const
Definition: Livecache.h:244
ripple::Dir::const_iterator
Definition: Directory.h:49
std::string
STL class.
ripple::PeerFinder::detail::LivecacheBase::Element
Definition: Livecache.h:49
ripple::PeerFinder::detail::LivecacheBase
Definition: Livecache.h:43
ripple::PeerFinder::Livecache::hops_t::m_lists
lists_type m_lists
Definition: Livecache.h:361
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
beast::PropertyStream::Map
Definition: PropertyStream.h:224
ripple::PeerFinder::Livecache::hops_t::insert
void insert(Element &e)
Definition: Livecache.h:531
beast::detail::aged_container_iterator::when
time_point const & when() const
Definition: aged_container_iterator.h:149
ripple::PeerFinder::Livecache::hops_t::reverse_iterator
boost::transform_iterator< Transform< false >, typename lists_type::reverse_iterator > reverse_iterator
Definition: Livecache.h:262
std::vector::reserve
T reserve(T... args)
std::vector
STL class.
ripple::PeerFinder::detail::LivecacheBase::Hop::begin
iterator begin() const
Definition: Livecache.h:98
std::back_inserter
T back_inserter(T... args)
ripple::PeerFinder::Livecache::onWrite
void onWrite(beast::PropertyStream::Map &map)
Output statistics.
Definition: Livecache.h:472
ripple::PeerFinder::Livecache::hops_t::Transform::result_type
Hop< IsConst > result_type
Definition: Livecache.h:239
ripple::PeerFinder::Livecache::m_cache
cache_type m_cache
Definition: Livecache.h:206
ripple::PeerFinder::Livecache::hops_t::iterator
boost::transform_iterator< Transform< false >, typename lists_type::iterator > iterator
Definition: Livecache.h:254
std::stringstream
STL class.
ripple::PeerFinder::detail::LivecacheBase::Hop
A list of Endpoint at the same hops This is a lightweight wrapper around a reference to the underlyin...
Definition: Livecache.h:67
std::reference_wrapper::get
T get(T... args)
ripple::PeerFinder::Livecache::hops_t::remove
void remove(Element &e)
Definition: Livecache.h:556
ripple::PeerFinder::detail::LivecacheBase::list_type
boost::intrusive::make_list< Element, boost::intrusive::constant_time_size< false > >::type list_type
Definition: Livecache.h:59
ripple::PeerFinder::Tuning::liveCacheSecondsToLive
constexpr std::chrono::seconds liveCacheSecondsToLive(30)
ripple::PeerFinder::detail::LivecacheBase::LivecacheBase
LivecacheBase()=default
std::less
beast::PropertyStream::Set
Definition: PropertyStream.h:296
ripple::ListDisposition::expired
@ expired
List is expired, but has the largest non-pending sequence seen so far.
algorithm
beast::detail::aged_ordered_container::time_point
typename clock_type::time_point time_point
Definition: aged_ordered_container.h:86
ripple::PeerFinder::Livecache::size
cache_type::size_type size() const
Returns the number of entries in the cache.
Definition: Livecache.h:374
ripple::PeerFinder::Livecache::hops_t::Transform::Transform
Transform()=default
ripple::PeerFinder::detail::LivecacheBase::Hop::const_iterator
iterator const_iterator
Definition: Livecache.h:89
std::fill
T fill(T... args)
beast::abstract_clock::now
virtual time_point now() const =0
Returns the current time.
ripple::PeerFinder::detail::LivecacheBase::Element::Element
Element(Endpoint const &endpoint_)
Definition: Livecache.h:51
ripple::PeerFinder::Livecache::insert
void insert(Endpoint const &ep)
Creates or updates an existing Element based on a new message.
Definition: Livecache.h:427
ripple::PeerFinder::Livecache::hops_t::m_hist
Histogram m_hist
Definition: Livecache.h:362
ripple::PeerFinder::detail::LivecacheBase::Hop::Transform
Definition: Livecache.h:71
std::reference_wrapper
ripple::PeerFinder::detail::LivecacheBase::Hop::iterator
boost::transform_iterator< Transform, typename list_type::const_iterator > iterator
Definition: Livecache.h:87
ripple::PeerFinder::detail::LivecacheBase::Hop::cbegin
iterator cbegin() const
Definition: Livecache.h:104
beast::detail::aged_ordered_container::chronological_t::end
iterator end()
Definition: aged_ordered_container.h:475
ripple::PeerFinder::detail::LivecacheBase::Hop::cend
iterator cend() const
Definition: Livecache.h:116
beast::detail::aged_ordered_container::cend
const_iterator cend() const
Definition: aged_ordered_container.h:740
beast::detail::aged_ordered_container::clock
clock_type & clock()
Definition: aged_ordered_container.h:656
beast::detail::aged_ordered_container::chronological_t::begin
iterator begin()
Definition: aged_ordered_container.h:457
ripple::PeerFinder::detail::LivecacheBase::Hop::rend
reverse_iterator rend() const
Definition: Livecache.h:134
ripple::PeerFinder::Livecache::hops_t::crend
const_reverse_iterator crend() const
Definition: Livecache.h:335
ripple::PeerFinder::detail::LivecacheBase::Hop::rbegin
reverse_iterator rbegin() const
Definition: Livecache.h:122
ripple::PeerFinder::Livecache::hops_t
Definition: Livecache.h:224
ripple::PeerFinder::Livecache::hops_t::rend
const_reverse_iterator rend() const
Definition: Livecache.h:329
ripple::PeerFinder::detail::LivecacheBase::Hop::end
iterator end() const
Definition: Livecache.h:110
ripple::PeerFinder::Livecache::hops_t::crbegin
const_reverse_iterator crbegin() const
Definition: Livecache.h:317
beast::detail::aged_ordered_container::emplace
auto emplace(Args &&... args) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool >>::type
Definition: aged_ordered_container.h:1907
ripple::PeerFinder::Livecache::Livecache
Livecache(clock_type &clock, beast::Journal journal, Allocator alloc=Allocator())
Create the cache.
Definition: Livecache.h:395
ripple::PeerFinder::Livecache::hops_t::shuffle
void shuffle()
Shuffle each hop list.
Definition: Livecache.h:495
ripple::PeerFinder::Livecache::hops_t::rbegin
reverse_iterator rbegin()
Definition: Livecache.h:305
std::to_string
T to_string(T... args)
ripple::PeerFinder::detail::LivecacheBase::Hop::move_back
void move_back(const_iterator pos)
Definition: Livecache.h:147
ripple::set
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:313
std::array< int, 1+Tuning::maxHops+1 >
ripple::PeerFinder::Livecache::hops_t::const_iterator
boost::transform_iterator< Transform< true >, typename lists_type::const_iterator > const_iterator
Definition: Livecache.h:258
ripple::PeerFinder::detail::LivecacheBase::Hop::m_list
std::reference_wrapper< typename beast::maybe_const< IsConst, list_type >::type > m_list
Definition: Livecache.h:165
ripple::default_prng
beast::xor_shift_engine & default_prng()
Return the default random engine.
Definition: ripple/basics/random.h:65
ripple::PeerFinder::Endpoint::hops
std::uint32_t hops
Definition: PeerfinderManager.h:119
ripple::PeerFinder::Livecache
The Livecache holds the short-lived relayed Endpoint messages.
Definition: Livecache.h:39
std::copy
T copy(T... args)
beast::detail::aged_ordered_container::erase
beast::detail::aged_container_iterator< false, Iterator > erase(beast::detail::aged_container_iterator< is_const, Iterator > pos)
Definition: aged_ordered_container.h:1994
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::PeerFinder::Livecache::hops_t::end
const_iterator end() const
Definition: Livecache.h:293
ripple::PeerFinder::Livecache::allocator_type
Allocator allocator_type
Definition: Livecache.h:209
beast::abstract_clock< std::chrono::steady_clock >
ripple::PeerFinder::detail::LivecacheBase::Hop::crend
reverse_iterator crend() const
Definition: Livecache.h:140
std::array::rend
T rend(T... args)
ripple::PeerFinder::Livecache::hops
class ripple::PeerFinder::Livecache::hops_t hops
beast::maybe_const
Makes T const or non const depending on a bool.
Definition: maybe_const.h:29
ripple::PeerFinder::detail::LivecacheBase::Hop::Transform::Transform
Transform()=default
beast::leftw
Left justifies a field at the specified width.
Definition: iosformat.h:33
ripple::PeerFinder::Livecache::hops_t::begin
const_iterator begin() const
Definition: Livecache.h:275
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
beast::detail::aged_ordered_container::size
size_type size() const noexcept
Definition: aged_ordered_container.h:814
ripple::PeerFinder::Livecache::hops_t::end
iterator end()
Definition: Livecache.h:287
ripple::PeerFinder::Livecache::hops_t::hops_t
hops_t(Allocator const &alloc)
Definition: Livecache.h:524
ripple::PeerFinder::Livecache::hops_t::cbegin
const_iterator cbegin() const
Definition: Livecache.h:281
ripple::PeerFinder::detail::LivecacheBase::Element::endpoint
Endpoint endpoint
Definition: Livecache.h:55
beast::detail::aged_ordered_container
Associative container where each element is also indexed by time.
Definition: aged_ordered_container.h:82
beast::maybe_const::type
typename std::conditional< IsConst, typename std::remove_const< T >::type const, typename std::remove_const< T >::type >::type type
Definition: maybe_const.h:35
beast::detail::aged_ordered_container::chronological
class beast::detail::aged_ordered_container::chronological_t chronological
ripple::PeerFinder::detail::LivecacheBase::Hop::Hop
Hop(typename beast::maybe_const< IsConst, list_type >::type &list)
Definition: Livecache.h:155
std::array::begin
T begin(T... args)
ripple::PeerFinder::Livecache::cache_type
beast::aged_map< beast::IP::Endpoint, Element, std::chrono::steady_clock, std::less< beast::IP::Endpoint >, Allocator > cache_type
Definition: Livecache.h:203
ripple::PeerFinder::Livecache::expire
void expire()
Erase entries whose time has expired.
Definition: Livecache.h:405
ripple::PeerFinder::detail::LivecacheBase::Hop::Transform::operator()
Endpoint const & operator()(Element const &e) const
Definition: Livecache.h:79
ripple::PeerFinder::Livecache::hops_t::cend
const_iterator cend() const
Definition: Livecache.h:299
beast::detail::aged_ordered_container::touch
void touch(beast::detail::aged_container_iterator< is_const, Iterator > pos)
Definition: aged_ordered_container.h:989
ripple::PeerFinder::Livecache::empty
bool empty() const
Returns true if the cache is empty.
Definition: Livecache.h:367
std::string::empty
T empty(T... args)
std::stringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::size_t
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:38
ripple::PeerFinder::Livecache::hops_t::reinsert
void reinsert(Element &e, std::uint32_t hops)
Definition: Livecache.h:541
std::array::end
T end(T... args)
ripple::PeerFinder::Tuning::maxHops
constexpr std::uint32_t maxHops
Definition: peerfinder/impl/Tuning.h:110
ripple::PeerFinder::Livecache::hops_t::const_reverse_iterator
boost::transform_iterator< Transform< true >, typename lists_type::const_reverse_iterator > const_reverse_iterator
Definition: Livecache.h:266
beast::detail::aged_ordered_container::cbegin
const_iterator cbegin() const
Definition: aged_ordered_container.h:722
ripple::PeerFinder::Endpoint
Describes a connectible peer address along with some metadata.
Definition: PeerfinderManager.h:113
ripple::PeerFinder::detail::LivecacheBase::Hop::const_reverse_iterator
reverse_iterator const_reverse_iterator
Definition: Livecache.h:95
std::shuffle
T shuffle(T... args)
ripple::PeerFinder::Livecache::hops_t::rend
reverse_iterator rend()
Definition: Livecache.h:323
ripple::PeerFinder::Endpoint::address
beast::IP::Endpoint address
Definition: PeerfinderManager.h:120
ripple::PeerFinder::detail::LivecacheBase::make_hop
static Hop< IsConst > make_hop(typename beast::maybe_const< IsConst, list_type >::type &list)
Definition: Livecache.h:172
ripple::PeerFinder::detail::LivecacheBase::Hop::crbegin
reverse_iterator crbegin() const
Definition: Livecache.h:128
std::array::rbegin
T rbegin(T... args)
beast::detail::aged_ordered_container::size_type
std::size_t size_type
Definition: aged_ordered_container.h:92
ripple::PeerFinder::Livecache::hops_t::Transform::first_argument
typename lists_type::value_type first_argument
Definition: Livecache.h:238
ripple::PeerFinder::Livecache::hops_t::begin
iterator begin()
Definition: Livecache.h:269