diff -ru /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/acquire-item.cc apt-0.3.19cnc53/apt-pkg/acquire-item.cc --- /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/acquire-item.cc Mon Nov 12 14:34:00 2001 +++ apt-0.3.19cnc53/apt-pkg/acquire-item.cc Tue Nov 13 16:26:27 2001 @@ -480,6 +480,119 @@ Item::Failed(Message,Cnf); } + + /*}}}*/ +// AcqMirrors::AcqMirrors - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* The package file is added to the queue */ +pkgAcqMirrors::pkgAcqMirrors(pkgAcquire *Owner, + pkgSourceList::RepositoryItem *Location) : + Item(Owner), Location(Location) +{ + Retries = _config->FindI("Acquire::Retries",0); + + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(Location->MirrorsURI()); + + // If we're verifying authentication, check whether the size and + // MD5 matches, if not, delete the cached files and force redownload + string fname = Location->MirrorsURI(); + string hash; + unsigned int size; + + if (Location->MD5HashForFile(fname, hash, size) + && !hash.empty() && size != 0) + { + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(Location->MirrorsURI()); + + if (!RecheckFile(FinalFile, hash, size)) + { + unlink(FinalFile.c_str()); + unlink(DestFile.c_str()); + } + } + + // Create the item + Desc.URI = Location->MirrorsURI(); + Desc.Description = Location->MirrorsInfo(); + Desc.Owner = this; + + Desc.ShortDesc = Location->Dist; + + QueueURI(Desc); +} + + /*}}}*/ +// AcqMirrors::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqMirrors::Custom600Headers() +{ + string Final = _config->FindDir("Dir::State::lists"); + Final += URItoFileName(Location->MirrorsURI()); + + struct stat Buf; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true"; + + return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); +} + /*}}}*/ +// AcqMirrors::Done - Finished a fetch /*{{{*/ +// --------------------------------------------------------------------- +void pkgAcqMirrors::Done(string Message,unsigned long Size,string MD5, + pkgAcquire::MethodConfig *Cfg) +{ + Item::Done(Message,Size,MD5,Cfg); + + // The files timestamp matches + if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) + return; + + // Done, move it into position + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(Location->MirrorsURI()); + Rename(DestFile,FinalFile); + + /* We restore the original name to DestFile so that the clean operation + will work OK */ + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(Location->MirrorsURI()); +} + + /*}}}*/ +// AcqMirrors::Failed - Failure handler /*{{{*/ +// --------------------------------------------------------------------- +/* Here we try other sources */ +void pkgAcqMirrors::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +{ + ErrorText = LookupTag(Message,"Message"); + + // This is the retry counter + if (Retries != 0 && + Cnf->LocalOnly == false && + StringToBool(LookupTag(Message,"Transient-Failure"),false) == true) + { + Retries--; + // wait a little before retrying + sleep(1); + QueueURI(Desc); + return; + } + + if (Cnf->LocalOnly == true || + StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + { + // Ignore this + Status = StatDone; + Complete = false; + Dequeue(); + return; + } + + Item::Failed(Message,Cnf); +} /*}}}*/ // AcqIndexRel::pkgAcqIndexRel - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -660,6 +773,8 @@ StoreFilename(StoreFilename), Vf(Version.FileList()) { Retries = _config->FindI("Acquire::Retries",0); + MirrorRetries = _config->FindI("Acquire::MirrorRetries",3); + UsingMirror = false; if (Version.Arch() == 0) { @@ -790,8 +905,20 @@ } // Create the item - Desc.URI = Location->ArchiveURI(PkgFile); - Desc.Description = Location->ArchiveInfo(Version); + const pkgSourceList::Item *MirrorLocation = Location->NextMirror(!UsingMirror); + if (MirrorLocation != NULL && MirrorRetries != 0) + { + UsingMirror = true; + Desc.URI = MirrorLocation->ArchiveURI(PkgFile); + Desc.Description = MirrorLocation->ArchiveInfo(Version); + } + else + { + /* Do not set UsingMirror to false here. Once it is used, it must + * stay true, so NextMirror() (above) will reset just once */ + Desc.URI = Location->ArchiveURI(PkgFile); + Desc.Description = Location->ArchiveInfo(Version); + } Desc.Owner = this; Desc.ShortDesc = Version.ParentPkg().Name(); QueueURI(Desc); @@ -866,12 +993,16 @@ ErrorText = LookupTag(Message,"Message"); if (QueueNext() == false) { - // This is the retry counter - if (Retries != 0 && - Cnf->LocalOnly == false && - StringToBool(LookupTag(Message,"Transient-Failure"),false) == true) + if (((UsingMirror && MirrorRetries != 0) || + (Retries != 0 && + StringToBool(LookupTag(Message,"Transient-Failure"),false) == true)) && + Cnf->LocalOnly == false) { - Retries--; + if (UsingMirror && MirrorRetries != 0) + MirrorRetries--; + else + Retries--; + // wait a little before retrying sleep(1); Vf = Version.FileList(); diff -ru /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/acquire-item.h apt-0.3.19cnc53/apt-pkg/acquire-item.h --- /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/acquire-item.h Mon Nov 12 14:34:00 2001 +++ apt-0.3.19cnc53/apt-pkg/acquire-item.h Tue Nov 13 16:26:27 2001 @@ -136,6 +136,9 @@ pkgCache::VerFileIterator Vf; unsigned int Retries; + bool UsingMirror; + unsigned int MirrorRetries; + // Queue the next available file for download. bool QueueNext(); @@ -175,6 +178,27 @@ pkgAcqHashes(pkgAcquire *Owner, pkgSourceList::RepositoryItem *Location); +}; + +// Item class for mirrors files +class pkgAcqMirrors : public pkgAcquire::Item +{ + protected: + + pkgSourceList::RepositoryItem *Location; + pkgAcquire::ItemDesc Desc; + unsigned int Retries; + + public: + + virtual void Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf); + virtual string DescURI() {return Location->MirrorsURI();}; + virtual string Custom600Headers(); + virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + + pkgAcqMirrors(pkgAcquire *Owner, + pkgSourceList::RepositoryItem *Location); }; // Fetch a generic file to the current directory diff -ru /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/sourcelist.cc apt-0.3.19cnc53/apt-pkg/sourcelist.cc --- /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/sourcelist.cc Mon Nov 12 14:34:00 2001 +++ apt-0.3.19cnc53/apt-pkg/sourcelist.cc Tue Nov 13 16:26:27 2001 @@ -1,3 +1,4 @@ + // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ // $Id$ @@ -183,6 +184,20 @@ List.push_back(Itm); } while (ParseQuoteWord(C, Section) == true); + + // Parse mirrors file + string MirrorsFile = _config->FindDir("Dir::State::lists"); + MirrorsFile += URItoFileName(Rep->MirrorsURI()); + static bool recursion = false; + if (!recursion && FileExists(MirrorsFile) && _config->FindB("APT::Use-Mirrors",true)) + { + recursion = true; + Rep->Mirrors = new pkgSourceList(); + Rep->Mirrors->Read(MirrorsFile); + recursion = false; + } else { + Rep->Mirrors = NULL; + } Repositories.push_back(Rep); @@ -345,6 +360,47 @@ } +string pkgSourceList::RepositoryItem::MirrorsURI() +{ + string Res; + switch (Type) + { + case Deb: + break; + + case DebSrc: + break; + + case Rpm: + case RpmSrc: + Res = URI + Dist + "/base/mirrors"; + break; + }; + return Res; +} + +string pkgSourceList::RepositoryItem::MirrorsInfo() +{ + string Res; + switch (Type) + { + case Deb: + break; + + case DebSrc: + break; + + case Rpm: + case RpmSrc: + Res = SiteOnly(URI) + ' '; + Res += Dist + "/"; + Res += "base/mirrors"; + break; + }; + return Res; +} + + bool pkgSourceList::RepositoryItem::UpdateHashes(string File) { // Open the stream for reading @@ -721,3 +777,35 @@ }; return Res; } + + /*}}}*/ +// SourceList::Item::NextMirror - Returns an info line for next mirror to try /*{{{*/ +// --------------------------------------------------------------------- +/* */ +const pkgSourceList::Item *pkgSourceList::Item::NextMirror(bool reset) const +{ + pkgSourceList *Mirrors = Repository->Mirrors; + if (Mirrors != NULL && !Mirrors->empty()) + { + if (reset) + { + I = Mirrors->begin(); + I += random() % Mirrors->size(); + EndI = I; + } + while (I != EndI || reset) + { + if (reset) + reset = false; + else + I++; + if (I == Mirrors->end()) + I = Mirrors->begin(); + if ((*I).Section == Section) + return &(*I); + } + } + return NULL; +} + + diff -ru /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/sourcelist.h apt-0.3.19cnc53/apt-pkg/sourcelist.h --- /home/kojima/rapt/tmp/apt-0.3.19cnc53/apt-pkg/sourcelist.h Mon Nov 12 14:34:00 2001 +++ apt-0.3.19cnc53/apt-pkg/sourcelist.h Tue Nov 13 16:26:27 2001 @@ -58,6 +58,8 @@ map HashIndex; // filename -> filedata VendorItem *Vendor; + + pkgSourceList *Mirrors; string URI; string Dist; @@ -74,6 +76,9 @@ string HashesURI(); string HashesInfo(); + + string MirrorsURI(); + string MirrorsInfo(); bool UpdateHashes(string File); @@ -89,6 +94,10 @@ { RepositoryItem *Repository; string Section; + + mutable vector::const_iterator I; + mutable vector::const_iterator EndI; + inline RepositoryType Type() const { return Repository->Type; }; inline string URI() const { return Repository->URI; }; @@ -104,6 +113,8 @@ string ArchiveInfo(pkgCache::VerIterator Ver) const; string ArchiveURI(string File) const; + + const Item *NextMirror(bool reset = false) const; }; typedef vector::const_iterator const_iterator; diff -ru /home/kojima/rapt/tmp/apt-0.3.19cnc53/cmdline/apt-get.cc apt-0.3.19cnc53/cmdline/apt-get.cc --- /home/kojima/rapt/tmp/apt-0.3.19cnc53/cmdline/apt-get.cc Tue Nov 13 16:00:07 2001 +++ apt-0.3.19cnc53/cmdline/apt-get.cc Tue Nov 13 18:39:27 2001 @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id$ +// $Id$ /* ###################################################################### apt-get - Cover for dpkg and rpm @@ -1206,6 +1217,17 @@ if (_error->PendingError() == true) return false; } + + // Add mirrors files + if (_config->FindB("APT::Use-Mirrors",true)) + { + for (R = List.rep_begin(); R != List.rep_end(); R++) + { + new pkgAcqMirrors(&Fetcher,*R); + if (_error->PendingError() == true) + return false; + } + } // Run it if (Fetcher.Run() == pkgAcquire::Failed) @@ -2045,6 +2067,8 @@ setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + + srandom((unsigned int)time(NULL)); // Parse the command line and initialize the package library CommandLine CmdL(Args,_config);