Refactor PeerFinder:

Previously, the PeerFinder manager constructed with a Callback object
provided by the owner which was used to perform operations like connecting,
disconnecting, and sending messages. This made it difficult to change the
overlay code because a single call into the PeerFinder could cause both
OverlayImpl and PeerImp to be re-entered one or more times, sometimes while
holding a recursive mutex. This change eliminates the callback by changing
PeerFinder functions to return values indicating the action the caller should
take.

As a result of this change the PeerFinder no longer needs its own dedicated
thread. OverlayImpl is changed to call into PeerFinder on a timer to perform
periodic activities. Furthermore the Checker class used to perform connectivity
checks has been refactored. It no longer uses an abstract base class, in order
to not type-erase the handler passed to async_connect (ensuring compatibility
with coroutines). To allow unit tests that don't need a network, the Logic
class is now templated on the Checker type. Currently the Manager provides its
own io_service. However, this can easily be changed so that the io_service is
provided upon construction.

Summary
* Remove unused SiteFiles dependency injection
* Remove Callback and update signatures for public APIs
* Remove obsolete functions
* Move timer to overlay
* Steps toward a shared io_service
* Templated, simplified Checker
* Tidy up Checker declaration
This commit is contained in:
Vinnie Falco
2014-10-07 18:00:14 -07:00
parent 5f59282ba1
commit 7c0c2419f7
18 changed files with 816 additions and 1120 deletions

View File

@@ -21,6 +21,7 @@
#include <ripple/overlay/impl/PeerImp.h>
#include <ripple/overlay/impl/Tuning.h>
#include <beast/streams/debug_ostream.h>
#include <functional>
namespace ripple {
@@ -86,20 +87,15 @@ PeerImp::start ()
}
void
PeerImp::activate ()
PeerImp::close()
{
assert (state_ == stateHandshaked);
state_ = stateActive;
assert(shortId_ == 0);
shortId_ = overlay_.next_id();
overlay_.onPeerActivated(shared_from_this ());
}
if (! strand_.running_in_this_thread())
return strand_.post (std::bind (
&PeerImp::close, shared_from_this()));
void
PeerImp::close (bool graceful)
{
was_canceled_ = true;
detach ("stop", graceful);
error_code ec;
timer_.cancel (ec);
socket_->close(ec);
}
//------------------------------------------------------------------------------
@@ -309,10 +305,7 @@ void PeerImp::do_connect ()
usage_ = resourceManager_.newOutboundEndpoint (remote_address_);
if (usage_.disconnect ())
{
detach ("do_connect");
return;
}
return detach ("do_connect");
boost::system::error_code ec;
timer_.expires_from_now (nodeVerifySeconds, ec);
@@ -321,8 +314,7 @@ void PeerImp::do_connect ()
if (ec)
{
journal_.error << "Failed to set verify timer.";
detach ("do_connect");
return;
return detach ("do_connect");
}
socket_->next_layer <NativeSocketType>().async_connect (
@@ -347,15 +339,15 @@ PeerImp::on_connect (error_code ec)
journal_.error <<
"Connect to " << remote_address_ <<
" failed: " << ec.message();
detach ("hc");
return;
return detach ("hc");
}
assert (state_ == stateConnecting);
state_ = stateConnected;
peerFinder_.on_connected (slot_,
beast::IPAddressConversion::from_asio (local_endpoint));
if (! peerFinder_.connected (slot_,
beast::IPAddressConversion::from_asio (local_endpoint)))
return detach("dup");
socket_->set_verify_mode (boost::asio::ssl::verify_none);
socket_->async_handshake (
@@ -895,8 +887,6 @@ PeerImp::on_message (std::shared_ptr <protocol::TMHello> const& m)
{
error_code ec;
bool bDetach (true);
timer_.cancel ();
std::uint32_t const ourTime (getApp().getOPs ().getNetworkTimeNC ());
@@ -915,6 +905,8 @@ PeerImp::on_message (std::shared_ptr <protocol::TMHello> const& m)
auto protocol = BuildInfo::make_protocol(m->protoversion());
// VFALCO TODO Report these failures in the HTTP response
if (m->has_nettime () &&
((m->nettime () < minTime) || (m->nettime () > maxTime)))
{
@@ -974,46 +966,61 @@ PeerImp::on_message (std::shared_ptr <protocol::TMHello> const& m)
"Connected to cluster node " << name_;
assert (state_ == stateConnected);
// VFALCO TODO Remove this needless state
state_ = stateHandshaked;
peerFinder_.on_handshake (slot_, RipplePublicKey (publicKey_),
clusterNode_);
auto const result = peerFinder_.activate (slot_,
RipplePublicKey (publicKey_), clusterNode_);
// XXX Set timer: connection is in grace period to be useful.
// XXX Set timer: connection idle (idle may vary depending on connection type.)
if ((hello_.has_ledgerclosed ()) && (
hello_.ledgerclosed ().size () == (256 / 8)))
if (result == PeerFinder::Result::success)
{
memcpy (closedLedgerHash_.begin (),
hello_.ledgerclosed ().data (), 256 / 8);
state_ = stateActive;
assert(shortId_ == 0);
shortId_ = overlay_.next_id();
overlay_.activate(shared_from_this ());
if ((hello_.has_ledgerprevious ()) &&
(hello_.ledgerprevious ().size () == (256 / 8)))
// XXX Set timer: connection is in grace period to be useful.
// XXX Set timer: connection idle (idle may vary depending on connection type.)
if ((hello_.has_ledgerclosed ()) && (
hello_.ledgerclosed ().size () == (256 / 8)))
{
memcpy (previousLedgerHash_.begin (),
hello_.ledgerprevious ().data (), 256 / 8);
addLedger (previousLedgerHash_);
}
else
{
previousLedgerHash_.zero ();
memcpy (closedLedgerHash_.begin (),
hello_.ledgerclosed ().data (), 256 / 8);
if ((hello_.has_ledgerprevious ()) &&
(hello_.ledgerprevious ().size () == (256 / 8)))
{
memcpy (previousLedgerHash_.begin (),
hello_.ledgerprevious ().data (), 256 / 8);
addLedger (previousLedgerHash_);
}
else
{
previousLedgerHash_.zero();
}
}
sendGetPeers();
return ec;
}
bDetach = false;
if (result == PeerFinder::Result::full)
{
// TODO Provide correct HTTP response
auto const redirects = peerFinder_.redirect (slot_);
send_endpoints (redirects.begin(), redirects.end());
}
else
{
// TODO Duplicate connection
}
}
if (bDetach)
{
//publicKey_.clear ();
//detach ("recvh");
ec = invalid_argument_error();
}
else
{
sendGetPeers ();
}
// VFALCO Commented this out because we return an error code
// to the caller, who calls detach for us.
//publicKey_.clear ();
//detach ("recvh");
ec = invalid_argument_error();
return ec;
}
@@ -2114,10 +2121,7 @@ PeerImp::detach (const char* rsn, bool graceful)
// to have PeerFinder work reliably.
detaching_ = true; // Race is ok.
if (was_canceled_)
peerFinder_.on_cancel (slot_);
else
peerFinder_.on_closed (slot_);
peerFinder_.on_closed (slot_);
if (state_ == stateActive)
overlay_.onPeerDisconnect (shared_from_this ());