summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2021-07-13 12:21:23 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2021-07-28 13:08:32 +0200
commit7e88def0548a92112f8295686c2a12379e4028be (patch)
treeda944fef2b68ec75131ed2d5523ba1a843189173 /apt-pkg
parent121ccd0e0c2612bab9ba5383d5599b54e29e4643 (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.
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/acquire.cc36
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)