Temporarily pause the request loop in extreme situations (#2900)

* Pause request loop to process queued votes

* Delay requests for 250ms minimum in between loops
This commit is contained in:
Guilherme Lawless 2020-09-02 08:53:13 +01:00 committed by GitHub
commit 697b351401
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 3 deletions

View file

@ -341,17 +341,25 @@ void nano::active_transactions::request_loop ()
while (!stopped && !node.flags.disable_request_loop)
{
// Account for the time spent in request_confirm by defining the wakeup point beforehand
const auto wakeup_l (std::chrono::steady_clock::now () + std::chrono::milliseconds (node.network_params.network.request_interval_ms));
// If many votes are queued, ensure at least the currently active ones finish processing
lock.unlock ();
if (node.vote_processor.half_full ())
{
node.vote_processor.flush_active ();
}
lock.lock ();
const auto stamp_l = std::chrono::steady_clock::now ();
// frontiers_confirmation should be above update_active_multiplier to ensure new sorted roots are updated
frontiers_confirmation (lock);
update_active_multiplier (lock);
request_confirm (lock);
// Sleep until all broadcasts are done, plus the remaining loop time
if (!stopped)
{
constexpr auto min_sleep_l = std::chrono::milliseconds (250);
const auto wakeup_l = std::max (stamp_l + std::chrono::milliseconds (node.network_params.network.request_interval_ms), std::chrono::steady_clock::now () + min_sleep_l);
condition.wait_until (lock, wakeup_l, [&wakeup_l, &stopped = stopped] { return stopped || std::chrono::steady_clock::now () >= wakeup_l; });
}
}

View file

@ -222,6 +222,15 @@ void nano::vote_processor::flush ()
}
}
void nano::vote_processor::flush_active ()
{
nano::unique_lock<std::mutex> lock (mutex);
while (is_active)
{
condition.wait (lock);
}
}
size_t nano::vote_processor::size ()
{
nano::lock_guard<std::mutex> guard (mutex);
@ -234,6 +243,11 @@ bool nano::vote_processor::empty ()
return votes.empty ();
}
bool nano::vote_processor::half_full ()
{
return size () >= max_votes / 2;
}
void nano::vote_processor::calculate_weights ()
{
nano::unique_lock<std::mutex> lock (mutex);

View file

@ -40,8 +40,11 @@ public:
nano::vote_code vote_blocking (std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>, bool = false);
void verify_votes (std::deque<std::pair<std::shared_ptr<nano::vote>, std::shared_ptr<nano::transport::channel>>> const &);
void flush ();
/** Block until the currently active processing cycle finishes */
void flush_active ();
size_t size ();
bool empty ();
bool half_full ();
void calculate_weights ();
void stop ();