diff options
-rw-r--r-- | apt-pkg/acquire-item.cc | 7 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 1 | ||||
-rw-r--r-- | apt-pkg/acquire-method.cc | 1 | ||||
-rw-r--r-- | apt-pkg/acquire-method.h | 1 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 1 | ||||
-rw-r--r-- | methods/mirror.cc | 123 | ||||
-rw-r--r-- | methods/mirror.h | 5 |
7 files changed, 95 insertions, 44 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index bb8a01db8..8973eedde 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -830,6 +830,13 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, { } /*}}}*/ +// AcqIndexTrans::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +string pkgAcqIndexTrans::Custom600Headers() +{ + return "\nFail-Ignore: true"; +} + /*}}}*/ // AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 332df5a6b..8f35c0dbf 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -579,6 +579,7 @@ class pkgAcqIndexTrans : public pkgAcqIndex public: virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + virtual string Custom600Headers(); /** \brief Create a pkgAcqIndexTrans. * diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index 3008c8d1a..6e021a445 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -381,6 +381,7 @@ int pkgAcqMethod::Run(bool Single) if (StrToTime(LookupTag(Message,"Last-Modified"),Tmp->LastModified) == false) Tmp->LastModified = 0; Tmp->IndexFile = StringToBool(LookupTag(Message,"Index-File"),false); + Tmp->FailIgnore = StringToBool(LookupTag(Message,"Fail-Ignore"),false); Tmp->Next = 0; // Append it to the list diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 99a4605b1..03851e823 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -37,6 +37,7 @@ class pkgAcqMethod string DestFile; time_t LastModified; bool IndexFile; + bool FailIgnore; }; struct FetchResult diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index c724c69a9..95e3bafdc 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -21,6 +21,7 @@ #include <stdlib.h> #include <fcntl.h> #include <sys/select.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> diff --git a/methods/mirror.cc b/methods/mirror.cc index b3a956b95..b2b6b2ecf 100644 --- a/methods/mirror.cc +++ b/methods/mirror.cc @@ -25,6 +25,8 @@ using namespace std; +#include<sstream> + #include "mirror.h" #include "http.h" #include "apti18n.h" @@ -104,7 +106,7 @@ bool MirrorMethod::Clean(string Dir) for(I=list.begin(); I != list.end(); I++) { string uri = (*I)->GetURI(); - if(uri.substr(0,strlen("mirror://")) != string("mirror://")) + if(uri.find("mirror://") != 0) continue; string BaseUri = uri.substr(0,uri.size()-1); if (URItoFileName(BaseUri) == Dir->d_name) @@ -126,28 +128,6 @@ bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str) if(Debug) clog << "MirrorMethod::DownloadMirrorFile(): " << endl; - // check the file, if it is not older than RefreshInterval just use it - // otherwise try to get a new one - if(FileExists(MirrorFile)) - { - struct stat buf; - time_t t,now,refresh; - if(stat(MirrorFile.c_str(), &buf) != 0) - return false; - t = std::max(buf.st_mtime, buf.st_ctime); - now = time(NULL); - refresh = 60*_config->FindI("Acquire::Mirror::RefreshInterval",360); - if(t + refresh > now) - { - if(Debug) - clog << "Mirror file is in RefreshInterval" << endl; - DownloadedMirrorFile = true; - return true; - } - if(Debug) - clog << "Mirror file " << MirrorFile << " older than " << refresh << "min, re-download it" << endl; - } - // not that great to use pkgAcquire here, but we do not have // any other way right now string fetch = BaseUri; @@ -162,7 +142,50 @@ bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str) return res; } -bool MirrorMethod::SelectMirror() +/* convert a the Queue->Uri back to the mirror base uri and look + * at all mirrors we have for this, this is needed as queue->uri + * may point to different mirrors (if TryNextMirror() was run) + */ +void MirrorMethod::CurrentQueueUriToMirror() +{ + // already in mirror:// style so nothing to do + if(Queue->Uri.find("mirror://") == 0) + return; + + // find current mirror and select next one + for (int i=0; i < AllMirrors.size(); i++) + { + if (Queue->Uri.find(AllMirrors[i]) == 0) + { + Queue->Uri.replace(0, AllMirrors[i].size(), BaseUri); + return; + } + } + _error->Error("Internal error: Failed to convert %s back to %s", + Queue->Uri.c_str(), BaseUri.c_str()); +} + +bool MirrorMethod::TryNextMirror() +{ + // find current mirror and select next one + for (int i=0; i < AllMirrors.size()-1; i++) + { + if (Queue->Uri.find(AllMirrors[i]) == 0) + { + Queue->Uri.replace(0, AllMirrors[i].size(), AllMirrors[i+1]); + if (Debug) + clog << "TryNextMirror: " << Queue->Uri << endl; + return true; + } + } + + if (Debug) + clog << "TryNextMirror could not find another mirror to try" << endl; + + return false; +} + +bool MirrorMethod::InitMirrors() { // if we do not have a MirrorFile, fallback if(!FileExists(MirrorFile)) @@ -179,10 +202,14 @@ bool MirrorMethod::SelectMirror() // get into sync issues (got indexfiles from mirror A, // but packages from mirror B - one might be out of date etc) ifstream in(MirrorFile.c_str()); - getline(in, Mirror); - if(Debug) - cerr << "Using mirror: " << Mirror << endl; - + string s; + while (!in.eof()) + { + getline(in, s); + if (s.size() > 0) + AllMirrors.push_back(s); + } + Mirror = AllMirrors[0]; UsedMirror = Mirror; return true; } @@ -274,23 +301,20 @@ bool MirrorMethod::Fetch(FetchItem *Itm) DownloadMirrorFile(Itm->Uri); } - if(Mirror.empty()) { - if(!SelectMirror()) { + if(AllMirrors.empty()) { + if(!InitMirrors()) { // no valid mirror selected, something went wrong downloading // from the master mirror site most likely and there is // no old mirror file availalbe return false; } } - if(Debug) - clog << "selected mirror: " << Mirror << endl; + if(Itm->Uri.find("mirror://") != string::npos) + Itm->Uri.replace(0,BaseUri.size(), Mirror); - for (FetchItem *I = Queue; I != 0; I = I->Next) - { - if(I->Uri.find("mirror://") != string::npos) - I->Uri.replace(0,BaseUri.size(), Mirror); - } + if(Debug) + clog << "Fetch: " << Itm->Uri << endl << endl; // now run the real fetcher return HttpMethod::Fetch(Itm); @@ -298,22 +322,35 @@ bool MirrorMethod::Fetch(FetchItem *Itm) void MirrorMethod::Fail(string Err,bool Transient) { - if(Queue->Uri.find("http://") != string::npos) - Queue->Uri.replace(0,Mirror.size(), BaseUri); + // FIXME: TryNextMirror is not ideal for indexfile as we may + // run into auth issues + + if (Debug) + clog << "Failure to get " << Queue->Uri << endl; + + // try the next mirror on fail (if its not a expected failure, + // e.g. translations are ok to ignore) + if (!Queue->FailIgnore && TryNextMirror()) + return; + + // all mirrors failed, so bail out + string s; + strprintf(s, _("[Mirror: %s]"), Mirror.c_str()); + SetIP(s); + + CurrentQueueUriToMirror(); pkgAcqMethod::Fail(Err, Transient); } void MirrorMethod::URIStart(FetchResult &Res) { - if(Queue->Uri.find("http://") != string::npos) - Queue->Uri.replace(0,Mirror.size(), BaseUri); + CurrentQueueUriToMirror(); pkgAcqMethod::URIStart(Res); } void MirrorMethod::URIDone(FetchResult &Res,FetchResult *Alt) { - if(Queue->Uri.find("http://") != string::npos) - Queue->Uri.replace(0,Mirror.size(), BaseUri); + CurrentQueueUriToMirror(); pkgAcqMethod::URIDone(Res, Alt); } diff --git a/methods/mirror.h b/methods/mirror.h index ed817806b..0a3ea6e92 100644 --- a/methods/mirror.h +++ b/methods/mirror.h @@ -26,6 +26,7 @@ class MirrorMethod : public HttpMethod // we simply transform between BaseUri and Mirror string BaseUri; // the original mirror://... url string Mirror; // the selected mirror uri (http://...) + vector<string> AllMirrors; // all available mirrors string MirrorFile; // the file that contains the list of mirrors bool DownloadedMirrorFile; // already downloaded this session @@ -34,7 +35,9 @@ class MirrorMethod : public HttpMethod protected: bool DownloadMirrorFile(string uri); string GetMirrorFileName(string uri); - bool SelectMirror(); + bool InitMirrors(); + bool TryNextMirror(); + void CurrentQueueUriToMirror(); bool Clean(string dir); // we need to overwrite those to transform the url back |