diff options
author | Julian Andres Klode <julian.klode@canonical.com> | 2021-07-13 12:21:23 +0200 |
---|---|---|
committer | Julian Andres Klode <julian.klode@canonical.com> | 2021-07-28 13:08:32 +0200 |
commit | 7e88def0548a92112f8295686c2a12379e4028be (patch) | |
tree | da944fef2b68ec75131ed2d5523ba1a843189173 | |
parent | 121ccd0e0c2612bab9ba5383d5599b54e29e4643 (diff) |
acquire: Automatically reduce select() timeout as needed
If there is an item with fetchAfter at the top of a queue,
reduce sleep() timeout so we can detect it and start it,
by calling Cycle() on the queue in the next iteration.
For some reasons we have to call select() with a 0s timeout
if we just marked an item as ready. Oh well.
Previous versions of this patch only called global Bump() after a timeout
from select(); this was unfortunately incorrect - it meant that we
never bumped a queue that did not start yet while other queues were
running, potentially significantly delaying retries.
-rw-r--r-- | apt-pkg/acquire.cc | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 806f8e212..5b3d5906b 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -34,6 +34,7 @@ #include <tuple> #include <vector> +#include <assert.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> @@ -714,7 +715,38 @@ pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) FD_ZERO(&RFds); FD_ZERO(&WFds); SetFds(Highest,&RFds,&WFds); - + + // Shorten the select() cycle in case we have items about to become ready + time_t now = time(nullptr); + time_t fetchAfter = 0; + for (Queue *I = Queues; I != nullptr; I = I->Next) + { + if (I->Items == nullptr) + continue; + + auto f = I->Items->GetFetchAfter(); + + if (f == 0 || I->Items->Owner->Status != pkgAcquire::Item::StatIdle) + continue; + + if (f <= now) + { + I->Cycle(); // Queue got stuck, unstuck it. + fetchAfter = now; // need to time out in select() below + assert(I->Items->Owner->Status != pkgAcquire::Item::StatIdle); + } + else if (f < fetchAfter || fetchAfter == 0) + { + fetchAfter = f; + } + } + + if (fetchAfter && (fetchAfter - now) < (tv.tv_sec + tv.tv_usec / 1e6)) + { + tv.tv_sec = fetchAfter - now; + tv.tv_usec = 0; + } + int Res; do { @@ -734,7 +766,9 @@ pkgAcquire::RunResult pkgAcquire::Run(int PulseIntervall) // Timeout, notify the log class if (Res == 0 || (Log != 0 && Log->Update == true)) { + tv.tv_sec = 0; tv.tv_usec = PulseIntervall; + for (Worker *I = Workers; I != 0; I = I->NextAcquire) I->Pulse(); if (Log != 0 && Log->Pulse(this) == false) |