tag 668111 patch thanks Attached version sort of restores the redirection limits. It adds a new setting that limits the number of queues that may exist for a given method that uses a QueueHost mode. Whenever the limit is reached, only one more queue will be created: one without the host name (as in QueueAccess mode).
Under the normal circumstances of a loop on the same host, the loop will still be caught at the method process. Under a loop of external redirections, it will take a little longer to detect it, but it will eventually be found. Comments? I'd really like to see it included some time soon. Thanks in advance. Cheers, -- Raphael Geissert - Debian Developer www.debian.org - get.debian.net
diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index 294d78f..eddf443 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -417,26 +417,19 @@ void pkgAcqMethod::Status(const char *Format,...) /*}}}*/ // AcqMethod::Redirect - Send a redirect message /*{{{*/ // --------------------------------------------------------------------- -/* This method sends the redirect message and also manipulates the queue - to keep the pipeline synchronized. */ +/* This method sends the redirect message and dequeues the item. */ void pkgAcqMethod::Redirect(const string &NewURI) { std::cout << "103 Redirect\nURI: " << Queue->Uri << "\n" << "New-URI: " << NewURI << "\n" << "\n" << std::flush; - // Change the URI for the request. - Queue->Uri = NewURI; - - /* To keep the pipeline synchronized, move the current request to - the end of the queue, past the end of the current pipeline. */ - FetchItem *I; - for (I = Queue; I->Next != 0; I = I->Next) ; - I->Next = Queue; + // Dequeue + FetchItem *Tmp = Queue; Queue = Queue->Next; - I->Next->Next = 0; - if (QueueBack == 0) - QueueBack = I->Next; + delete Tmp; + if (Tmp == QueueBack) + QueueBack = Queue; } /*}}}*/ // AcqMethod::FetchResult::FetchResult - Constructor /*{{{*/ diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 75e0323..54c8005 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -242,6 +242,21 @@ bool pkgAcquire::Worker::RunMessages() string NewURI = LookupTag(Message,"New-URI",URI.c_str()); Itm->URI = NewURI; + + ItemDone(); + + pkgAcquire::Item *Owner = Itm->Owner; + pkgAcquire::ItemDesc Desc = *Itm; + + // Change the status so that it can be dequeued + Owner->Status = pkgAcquire::Item::StatIdle; + // Mark the item as done (taking care of all queues) + // and then put it in the main queue again + OwnerQ->ItemDone(Itm); + OwnerQ->Owner->Enqueue(Desc); + + if (Log != 0) + Log->Done(Desc); break; } diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index ef120d8..318a0bb 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -46,6 +46,7 @@ pkgAcquire::pkgAcquire() : Queues(0), Workers(0), Configs(0), Log(NULL), ToFetch QueueMode = QueueHost; if (strcasecmp(Mode.c_str(),"access") == 0) QueueMode = QueueAccess; + QueueHostLimit = _config->FindI("Acquire::QueueHost::Limit",10); } pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : Queues(0), Workers(0), Configs(0), Log(Progress), ToFetch(0), @@ -57,6 +58,7 @@ pkgAcquire::pkgAcquire(pkgAcquireStatus *Progress) : Queues(0), Workers(0), QueueMode = QueueHost; if (strcasecmp(Mode.c_str(),"access") == 0) QueueMode = QueueAccess; + QueueHostLimit = _config->FindI("Acquire::QueueHost::Limit",10); Setup(Progress, ""); } /*}}}*/ @@ -242,11 +244,19 @@ void pkgAcquire::Dequeue(Item *Itm) { Queue *I = Queues; bool Res = false; - for (; I != 0; I = I->Next) - Res |= I->Dequeue(Itm); - if (Debug == true) clog << "Dequeuing " << Itm->DestFile << endl; + + for (; I != 0; I = I->Next) + { + if (I->Dequeue(Itm)) + { + Res = true; + if (Debug == true) + clog << "Dequeued from " << I->Name << endl; + } + } + if (Res == true) ToFetch--; } @@ -269,7 +279,28 @@ string pkgAcquire::QueueName(string Uri,MethodConfig const *&Config) if (Config->SingleInstance == true || QueueMode == QueueAccess) return U.Access; - return U.Access + ':' + U.Host; + string AccessSchema = U.Access + ':', + FullQueueName = AccessSchema + U.Host; + unsigned int Instances = 0, SchemaLength = AccessSchema.length(); + + Queue *I = Queues; + for (; I != 0; I = I->Next) { + // if the queue already exists, re-use it + if (I->Name == FullQueueName) + return FullQueueName; + + if (I->Name.compare(0, SchemaLength, AccessSchema) == 0) + Instances++; + } + + if (Debug) { + clog << "Found " << Instances << " instances of " << U.Access << endl; + } + + if (Instances >= QueueHostLimit) + return U.Access; + + return FullQueueName; } /*}}}*/ // Acquire::GetConfig - Fetch the configuration information /*{{{*/ diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index 9fe0e8a..8b20b6a 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -163,6 +163,12 @@ class pkgAcquire */ QueueAccess} QueueMode; + /** \brief If non-zero, limit the number of instances of a method in + * QueueHost mode. I.e. after the limit is reached, a given method + * is switched to a behaviour like QueueAccess mode. + */ + unsigned long QueueHostLimit; + /** \brief If \b true, debugging information will be dumped to std::clog. */ bool const Debug; /** \brief If \b true, a download is currently in progress. */ diff --git a/methods/http.cc b/methods/http.cc index 65a0cbb..cbc6c69 100644 --- a/methods/http.cc +++ b/methods/http.cc @@ -967,7 +967,10 @@ HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv) else { NextURI = DeQuoteString(Srv->Location); - return TRY_AGAIN_OR_REDIRECT; + URI tmpURI = NextURI; + // Do not allow a redirection to switch protocol + if (tmpURI.Access == "http") + return TRY_AGAIN_OR_REDIRECT; } /* else pass through for error message */ }