diff --git a/nano/lib/stats_enums.hpp b/nano/lib/stats_enums.hpp index c2fec6a159..23c7e819d2 100644 --- a/nano/lib/stats_enums.hpp +++ b/nano/lib/stats_enums.hpp @@ -127,6 +127,7 @@ enum class detail erased, request, request_failed, + request_success, broadcast, cleanup, top, diff --git a/nano/node/bootstrap/bootstrap_service.cpp b/nano/node/bootstrap/bootstrap_service.cpp index e6a2295cb8..f8af5e3777 100644 --- a/nano/node/bootstrap/bootstrap_service.cpp +++ b/nano/node/bootstrap/bootstrap_service.cpp @@ -153,6 +153,8 @@ bool nano::bootstrap_service::send (std::shared_ptr co { nano::lock_guard lock{ mutex }; debug_assert (tags.get ().count (tag.id) == 0); + // Give extra time for the request to be processed by the channel + tag.cutoff = std::chrono::steady_clock::now () + config.request_timeout * 4; tags.get ().insert (tag); } @@ -202,10 +204,25 @@ bool nano::bootstrap_service::send (std::shared_ptr co stats.inc (nano::stat::type::bootstrap, nano::stat::detail::request, nano::stat::dir::out); stats.inc (nano::stat::type::bootstrap_request, to_stat_detail (tag.type)); - // TODO: There is no feedback mechanism if bandwidth limiter starts dropping our requests channel->send ( - request, nullptr, - nano::transport::buffer_drop_policy::limiter, nano::transport::traffic_type::bootstrap); + request, [this, id = tag.id] (auto const & ec, auto size) { + nano::lock_guard lock{ mutex }; + if (auto it = tags.get ().find (id); it != tags.get ().end ()) + { + if (!ec) + { + stats.inc (nano::stat::type::bootstrap, nano::stat::detail::request_success, nano::stat::dir::out); + tags.get ().modify (it, [&] (auto & tag) { + // After the request has been sent, the peer has a limited time to respond + tag.cutoff = std::chrono::steady_clock::now () + config.request_timeout; + }); + } + else + { + stats.inc (nano::stat::type::bootstrap, nano::stat::detail::request_failed, nano::stat::dir::out); + tags.get ().erase (it); + } + } }, nano::transport::buffer_drop_policy::limiter, nano::transport::traffic_type::bootstrap); return true; // TODO: Return channel send result } @@ -674,9 +691,9 @@ void nano::bootstrap_service::cleanup_and_sync () throttle.resize (compute_throttle_size ()); - auto const cutoff = std::chrono::steady_clock::now () - config.request_timeout; - auto should_timeout = [cutoff] (async_tag const & tag) { - return tag.timestamp < cutoff; + auto const now = std::chrono::steady_clock::now (); + auto should_timeout = [&] (async_tag const & tag) { + return tag.cutoff < now; }; auto & tags_by_order = tags.get (); diff --git a/nano/node/bootstrap/bootstrap_service.hpp b/nano/node/bootstrap/bootstrap_service.hpp index 1959df41e1..d77b048d44 100644 --- a/nano/node/bootstrap/bootstrap_service.hpp +++ b/nano/node/bootstrap/bootstrap_service.hpp @@ -90,9 +90,9 @@ class bootstrap_service nano::account account{ 0 }; nano::block_hash hash{ 0 }; size_t count{ 0 }; - - id_t id{ nano::bootstrap::generate_id () }; + std::chrono::steady_clock::time_point cutoff{}; std::chrono::steady_clock::time_point timestamp{ std::chrono::steady_clock::now () }; + id_t id{ nano::bootstrap::generate_id () }; }; private: