X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/fb193b1cd43f0e8c3b7e5f69f183b9abe7e83761..2e2865ae53a65c00dd55a892d5b48458f3110366:/apt-pkg/acquire.cc diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 757fab057..affc0c791 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -269,6 +269,42 @@ void pkgAcquire::Remove(Worker *Work) it is constructed which creates a queue (based on the current queue mode) and puts the item in that queue. If the system is running then the queue might be started. */ +static bool DoesAcquireResultInInstantFailure(pkgAcquire::Item * const Item, + pkgAcquire::MethodConfig const * const Config, pkgAcquireStatus * const Log) +{ + auto SavedDesc = Item->GetItemDesc(); + if (Item->IsRedirectionLoop(SavedDesc.URI)) + { + std::string const Message = "400 URI Failure" + "\nURI: " + SavedDesc.URI + + "\nFilename: " + Item->DestFile + + "\nFailReason: RedirectionLoop"; + + Item->Status = pkgAcquire::Item::StatError; + Item->Failed(Message, Config); + if (Log != nullptr) + Log->Fail(SavedDesc); + return true; + } + + HashStringList const hsl = Item->GetExpectedHashes(); + if (hsl.usable() == false && Item->HashesRequired() && + _config->Exists("Acquire::ForceHash") == false) + { + std::string const Message = "400 URI Failure" + "\nURI: " + SavedDesc.URI + + "\nFilename: " + Item->DestFile + + "\nFailReason: WeakHashSums"; + + auto SavedDesc = Item->GetItemDesc(); + Item->Status = pkgAcquire::Item::StatAuthError; + Item->Failed(Message, Config); + if (Log != nullptr) + Log->Fail(SavedDesc); + return true; + } + return false; +} void pkgAcquire::Enqueue(ItemDesc &Item) { // Determine which queue to put the item in @@ -277,6 +313,13 @@ void pkgAcquire::Enqueue(ItemDesc &Item) if (Name.empty() == true) return; + /* the check for running avoids that we produce errors + in logging before we actually have started, which would + be easier to implement but would confuse users/implementations + so we check the items skipped here in #Startup */ + if (Running && DoesAcquireResultInInstantFailure(Item.Owner, Config, Log)) + return; + // Find the queue structure Queue *I = Queues; for (; I != 0 && I->Name != Name; I = I->Next); @@ -352,23 +395,37 @@ string pkgAcquire::QueueName(string Uri,MethodConfig const *&Config) return U.Access; string AccessSchema = U.Access + ':'; - string FullQueueName; + string FullQueueName; if (U.Host.empty()) { - long randomQueue = random(); + long existing = 0; + // check how many queues exist already and reuse empty ones + for (Queue const *I = Queues; I != 0; I = I->Next) + if (I->Name.compare(0, AccessSchema.length(), AccessSchema) == 0) + { + if (I->Items == nullptr) + return I->Name; + ++existing; + } + #ifdef _SC_NPROCESSORS_ONLN long cpuCount = sysconf(_SC_NPROCESSORS_ONLN) * 2; #else - long cpuCount = _config->FindI("Acquire::QueueHost::Limit",10); + long cpuCount = 10; #endif - if (cpuCount > 0) - randomQueue %= cpuCount; + cpuCount = _config->FindI("Acquire::QueueHost::Limit", cpuCount); - strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), randomQueue); - if (Debug) { - clog << "Chose random queue " << FullQueueName << " for " << Uri << endl; + if (cpuCount <= 0 || existing < cpuCount) + strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), existing); + else + { + long const randomQueue = random() % cpuCount; + strprintf(FullQueueName, "%s%ld", AccessSchema.c_str(), randomQueue); } + + if (Debug) + clog << "Chose random queue " << FullQueueName << " for " << Uri << endl; } else { FullQueueName = AccessSchema + U.Host; @@ -452,7 +509,7 @@ void pkgAcquire::SetFds(int &Fd,fd_set *RSet,fd_set *WSet) void pkgAcquire::RunFds(fd_set *RSet,fd_set *WSet) { RunFdsSane(RSet, WSet); -}; +} /*}}}*/ // Acquire::RunFdsSane - Deal with active FDs /*{{{*/ // --------------------------------------------------------------------- @@ -898,10 +955,20 @@ bool pkgAcquire::Queue::Startup() if (Workers == 0) { URI U(Name); - pkgAcquire::MethodConfig *Cnf = Owner->GetConfig(U.Access); - if (Cnf == 0) + pkgAcquire::MethodConfig * const Cnf = Owner->GetConfig(U.Access); + if (unlikely(Cnf == nullptr)) return false; - + + // now-running twin of the pkgAcquire::Enqueue call + for (QItem *I = Items; I != 0; ) + { + bool pointless = false; + for (auto &&O: I->Owners) + if (DoesAcquireResultInInstantFailure(O, Cnf, Owner->Log)) + pointless = true; + I = pointless ? Items : I->Next; + } + Workers = new Worker(this,Cnf,Owner->Log); Owner->Add(Workers); if (Workers->Start() == false) @@ -1133,7 +1200,7 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) // Compute the total number of bytes to fetch unsigned int Unknown = 0; unsigned int Count = 0; - bool UnfetchedReleaseFiles = false; + bool ExpectAdditionalItems = false; for (pkgAcquire::ItemCIterator I = Owner->ItemsBegin(); I != Owner->ItemsEnd(); ++I, ++Count) @@ -1142,12 +1209,9 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) if ((*I)->Status == pkgAcquire::Item::StatDone) ++CurrentItems; - // see if the method tells us to expect more - TotalItems += (*I)->ExpectedAdditionalItems; - - // check if there are unfetched Release files - if ((*I)->Status != pkgAcquire::Item::StatDone && (*I)->ExpectedAdditionalItems > 0) - UnfetchedReleaseFiles = true; + // do we expect to acquire more files than we know of yet? + if ((*I)->ExpectedAdditionalItems > 0) + ExpectAdditionalItems = true; TotalBytes += (*I)->FileSize; if ((*I)->Complete == true) @@ -1204,7 +1268,7 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) double const OldPercent = Percent; // calculate the percentage, if we have too little data assume 1% - if (TotalBytes > 0 && UnfetchedReleaseFiles) + if (ExpectAdditionalItems) Percent = 0; else // use both files and bytes because bytes can be unreliable @@ -1247,13 +1311,12 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems); // build the status str - status << "dlstatus:" << i - << ":" << std::setprecision(3) << Percent - << ":" << msg - << endl; - - std::string const dlstatus = status.str(); - FileFd::Write(fd, dlstatus.c_str(), dlstatus.size()); + std::ostringstream str; + str.imbue(std::locale("C.UTF-8")); + str.precision(4); + str << "dlstatus" << ':' << std::fixed << i << ':' << Percent << ':' << msg << '\n'; + auto const dlstatus = str.str(); + FileFd::Write(fd, dlstatus.data(), dlstatus.size()); } return true;