rippled
PeerSet.cpp
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 #include <ripple/app/main/Application.h>
21 #include <ripple/core/JobQueue.h>
22 #include <ripple/overlay/Overlay.h>
23 #include <ripple/overlay/PeerSet.h>
24 
25 namespace ripple {
26 
27 class PeerSetImpl : public PeerSet
28 {
29 public:
31 
32  void
33  addPeers(
34  std::size_t limit,
35  std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
36  std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override;
37 
39  void
41  ::google::protobuf::Message const& message,
42  protocol::MessageType type,
43  std::shared_ptr<Peer> const& peer) override;
44 
46  getPeerIds() const override;
47 
48 private:
49  // Used in this class for access to boost::asio::io_service and
50  // ripple::Overlay.
53 
56 };
57 
59  : app_(app), journal_(app.journal("PeerSet"))
60 {
61 }
62 
63 void
65  std::size_t limit,
66  std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
67  std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded)
68 {
69  using ScoredPeer = std::pair<int, std::shared_ptr<Peer>>;
70 
71  auto const& overlay = app_.overlay();
72 
74  pairs.reserve(overlay.size());
75 
76  overlay.foreach([&](auto const& peer) {
77  auto const score = peer->getScore(hasItem(peer));
78  pairs.emplace_back(score, std::move(peer));
79  });
80 
81  std::sort(
82  pairs.begin(),
83  pairs.end(),
84  [](ScoredPeer const& lhs, ScoredPeer const& rhs) {
85  return lhs.first > rhs.first;
86  });
87 
89  for (auto const& pair : pairs)
90  {
91  auto const peer = pair.second;
92  if (!peers_.insert(peer->id()).second)
93  continue;
94  onPeerAdded(peer);
95  if (++accepted >= limit)
96  break;
97  }
98 }
99 
100 void
102  ::google::protobuf::Message const& message,
103  protocol::MessageType type,
104  std::shared_ptr<Peer> const& peer)
105 {
106  auto packet = std::make_shared<Message>(message, type);
107  if (peer)
108  {
109  peer->send(packet);
110  return;
111  }
112 
113  for (auto id : peers_)
114  {
115  if (auto p = app_.overlay().findPeerByShortID(id))
116  p->send(packet);
117  }
118 }
119 
122 {
123  return peers_;
124 }
125 
127 {
128 public:
130  {
131  }
132 
134  build() override
135  {
136  return std::make_unique<PeerSetImpl>(app_);
137  }
138 
139 private:
141 };
142 
145 {
146  return std::make_unique<PeerSetBuilderImpl>(app);
147 }
148 
149 class DummyPeerSet : public PeerSet
150 {
151 public:
152  DummyPeerSet(Application& app) : j_(app.journal("DummyPeerSet"))
153  {
154  }
155 
156  void
158  std::size_t limit,
159  std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
160  std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override
161  {
162  JLOG(j_.error()) << "DummyPeerSet addPeers should not be called";
163  }
164 
165  void
167  ::google::protobuf::Message const& message,
168  protocol::MessageType type,
169  std::shared_ptr<Peer> const& peer) override
170  {
171  JLOG(j_.error()) << "DummyPeerSet sendRequest should not be called";
172  }
173 
174  const std::set<Peer::id_t>&
175  getPeerIds() const override
176  {
177  static std::set<Peer::id_t> emptyPeers;
178  JLOG(j_.error()) << "DummyPeerSet getPeerIds should not be called";
179  return emptyPeers;
180  }
181 
182 private:
184 };
185 
188 {
189  return std::make_unique<DummyPeerSet>(app);
190 }
191 
192 } // namespace ripple
ripple::make_DummyPeerSet
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
Definition: PeerSet.cpp:187
ripple::Application
Definition: Application.h:115
ripple::DummyPeerSet::j_
beast::Journal j_
Definition: PeerSet.cpp:183
ripple::PeerSetImpl::peers_
std::set< Peer::id_t > peers_
The identifiers of the peers we are tracking.
Definition: PeerSet.cpp:55
std::shared_ptr
STL class.
ripple::DummyPeerSet::sendRequest
void sendRequest(::google::protobuf::Message const &message, protocol::MessageType type, std::shared_ptr< Peer > const &peer) override
Definition: PeerSet.cpp:166
std::pair
std::vector::reserve
T reserve(T... args)
ripple::PeerSetBuilderImpl::app_
Application & app_
Definition: PeerSet.cpp:140
std::vector
STL class.
ripple::PeerSetBuilderImpl::PeerSetBuilderImpl
PeerSetBuilderImpl(Application &app)
Definition: PeerSet.cpp:129
ripple::PeerSetImpl::app_
Application & app_
Definition: PeerSet.cpp:51
std::function
ripple::PeerSetBuilderImpl::build
virtual std::unique_ptr< PeerSet > build() override
Definition: PeerSet.cpp:134
ripple::PeerSetBuilderImpl
Definition: PeerSet.cpp:126
std::sort
T sort(T... args)
ripple::PeerSetBuilder
Definition: PeerSet.h:80
ripple::PeerSetImpl::addPeers
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> hasItem, std::function< void(std::shared_ptr< Peer > const &)> onPeerAdded) override
Try add more peers.
Definition: PeerSet.cpp:64
ripple::DummyPeerSet::addPeers
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> hasItem, std::function< void(std::shared_ptr< Peer > const &)> onPeerAdded) override
Try add more peers.
Definition: PeerSet.cpp:157
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::PeerSetImpl
Definition: PeerSet.cpp:27
ripple::DummyPeerSet::getPeerIds
const std::set< Peer::id_t > & getPeerIds() const override
get the set of ids of previously added peers
Definition: PeerSet.cpp:175
ripple::ManifestDisposition::accepted
@ accepted
Manifest is valid.
ripple::DummyPeerSet::DummyPeerSet
DummyPeerSet(Application &app)
Definition: PeerSet.cpp:152
std::vector::emplace_back
T emplace_back(T... args)
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::make_PeerSetBuilder
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition: PeerSet.cpp:144
std::vector::begin
T begin(T... args)
ripple::PeerSet
Supports data retrieval by managing a set of peers.
Definition: PeerSet.h:44
ripple::Application::overlay
virtual Overlay & overlay()=0
ripple::PeerSetImpl::journal_
beast::Journal journal_
Definition: PeerSet.cpp:52
ripple::Overlay::findPeerByShortID
virtual std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) const =0
Returns the peer with the matching short id, or null.
std::size_t
std::vector::end
T end(T... args)
ripple::DummyPeerSet
Definition: PeerSet.cpp:149
ripple::PeerSetImpl::PeerSetImpl
PeerSetImpl(Application &app)
Definition: PeerSet.cpp:58
std::unique_ptr
STL class.
ripple::PeerSetImpl::sendRequest
void sendRequest(::google::protobuf::Message const &message, protocol::MessageType type, std::shared_ptr< Peer > const &peer) override
Send a message to one or all peers.
Definition: PeerSet.cpp:101
std::set
STL class.
ripple::PeerSetImpl::getPeerIds
const std::set< Peer::id_t > & getPeerIds() const override
get the set of ids of previously added peers
Definition: PeerSet.cpp:121