#include <stdio.h>
/*}}}*/
typedef vector<pkgIndexFile *>::iterator FileIterator;
+template <typename Iter> std::vector<Iter*> pkgCacheGenerator::Dynamic<Iter>::toReMap;
// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
// ---------------------------------------------------------------------
// Starting header
*Cache.HeaderP = pkgCache::Header();
- Cache.HeaderP->VerSysName = Map.WriteString(_system->VS->Label);
- Cache.HeaderP->Architecture = Map.WriteString(_config->Find("APT::Architecture"));
+ map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+ Cache.HeaderP->VerSysName = idxVerSysName;
+ map_ptrloc const idxArchitecture = WriteStringInMap(_config->Find("APT::Architecture"));
+ Cache.HeaderP->Architecture = idxArchitecture;
+ if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+ return;
Cache.ReMap();
}
else
Map.Sync(0,sizeof(pkgCache::Header));
}
/*}}}*/
+void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/
+ if (oldMap == newMap)
+ return;
+
+ if (_config->FindB("Debug::pkgCacheGen", false))
+ std::clog << "Remaping from " << oldMap << " to " << newMap << std::endl;
+
+ Cache.ReMap(false);
+
+ CurrentFile += (pkgCache::PackageFile*) newMap - (pkgCache::PackageFile*) oldMap;
+
+ for (size_t i = 0; i < _count(UniqHash); ++i)
+ if (UniqHash[i] != 0)
+ UniqHash[i] += (pkgCache::StringItem*) newMap - (pkgCache::StringItem*) oldMap;
+
+ for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::PkgIterator*>::const_iterator i = Dynamic<pkgCache::PkgIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::PkgIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::VerIterator*>::const_iterator i = Dynamic<pkgCache::VerIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::VerIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::DepIterator*>::const_iterator i = Dynamic<pkgCache::DepIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::DepIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::DescIterator*>::const_iterator i = Dynamic<pkgCache::DescIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::DescIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::PrvIterator*>::const_iterator i = Dynamic<pkgCache::PrvIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::PrvIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
+} /*}}}*/
+// CacheGenerator::WriteStringInMap /*{{{*/
+map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String,
+ const unsigned long &Len) {
+ void const * const oldMap = Map.Data();
+ map_ptrloc const index = Map.WriteString(String, Len);
+ if (index != 0)
+ ReMap(oldMap, Map.Data());
+ return index;
+}
+ /*}}}*/
+// CacheGenerator::WriteStringInMap /*{{{*/
+map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) {
+ void const * const oldMap = Map.Data();
+ map_ptrloc const index = Map.WriteString(String);
+ if (index != 0)
+ ReMap(oldMap, Map.Data());
+ return index;
+}
+ /*}}}*/
+map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
+ void const * const oldMap = Map.Data();
+ map_ptrloc const index = Map.Allocate(size);
+ if (index != 0)
+ ReMap(oldMap, Map.Data());
+ return index;
+}
+ /*}}}*/
// CacheGenerator::MergeList - Merge the package list /*{{{*/
// ---------------------------------------------------------------------
/* This provides the generation of the entries in the cache. Each loop
if (PackageName.empty() == true)
return false;
- /* As we handle Arch all packages as architecture bounded
- we add all information to every (simulated) arch package */
- std::vector<string> genArch;
- if (List.ArchitectureAll() == true) {
- genArch = APT::Configuration::getArchitectures();
- if (genArch.size() != 1)
- genArch.push_back("all");
- } else
- genArch.push_back(List.Architecture());
-
- for (std::vector<string>::const_iterator arch = genArch.begin();
- arch != genArch.end(); ++arch)
- {
+ string const Arch = List.Architecture();
+
// Get a pointer to the package structure
pkgCache::PkgIterator Pkg;
- if (NewPackage(Pkg, PackageName, *arch) == false)
+ Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
+ if (NewPackage(Pkg, PackageName, Arch) == false)
return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str());
Counter++;
if (Counter % 100 == 0 && Progress != 0)
// we first process the package, then the descriptions
// (this has the bonus that we get MMap error when we run out
// of MMap space)
- if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
+ pkgCache::VerIterator Ver(Cache);
+ Dynamic<pkgCache::VerIterator> DynVer(Ver);
+ if (List.UsePackage(Pkg, Ver) == false)
return _error->Error(_("Error occurred while processing %s (UsePackage1)"),
PackageName.c_str());
// Find the right version to write the description
MD5SumValue CurMd5 = List.Description_md5();
- pkgCache::VerIterator Ver = Pkg.VersionList();
- map_ptrloc *LastVer = &Pkg->VersionList;
+ Ver = Pkg.VersionList();
- for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; ++Ver)
{
pkgCache::DescIterator Desc = Ver.DescriptionList();
+ Dynamic<pkgCache::DescIterator> DynDesc(Desc);
map_ptrloc *LastDesc = &Ver->DescriptionList;
bool duplicate=false;
// don't add a new description if we have one for the given
// md5 && language
- for ( ; Desc.end() == false; Desc++)
+ for ( ; Desc.end() == false; ++Desc)
if (MD5SumValue(Desc.md5()) == CurMd5 &&
Desc.LanguageCode() == List.DescriptionLanguage())
duplicate=true;
for (Desc = Ver.DescriptionList();
Desc.end() == false;
- LastDesc = &Desc->NextDesc, Desc++)
+ LastDesc = &Desc->NextDesc, ++Desc)
{
if (MD5SumValue(Desc.md5()) == CurMd5)
{
// Add new description
- *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+ void const * const oldMap = Map.Data();
+ map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+ if (oldMap != Map.Data())
+ LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ *LastDesc = descindex;
Desc->ParentPkg = Pkg.Index();
if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
}
pkgCache::VerIterator Ver = Pkg.VersionList();
+ Dynamic<pkgCache::VerIterator> DynVer(Ver);
map_ptrloc *LastVer = &Pkg->VersionList;
+ void const * oldMap = Map.Data();
int Res = 1;
unsigned long const Hash = List.VersionHash();
for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
}
// Add a new version
- *LastVer = NewVersion(Ver,Version,*LastVer);
+ map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer);
+ if (verindex == 0 && _error->PendingError())
+ return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+ PackageName.c_str(), 1);
+
+ if (oldMap != Map.Data())
+ LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ *LastVer = verindex;
Ver->ParentPkg = Pkg.Index();
Ver->Hash = Hash;
- if ((*LastVer == 0 && _error->PendingError()) || List.NewVersion(Ver) == false)
- return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
- PackageName.c_str());
+ if (List.NewVersion(Ver) == false)
+ return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+ PackageName.c_str(), 2);
if (List.UsePackage(Pkg,Ver) == false)
return _error->Error(_("Error occurred while processing %s (UsePackage3)"),
PackageName.c_str());
if (NewFileVer(Ver,List) == false)
- return _error->Error(_("Error occurred while processing %s (NewVersion2)"),
- PackageName.c_str());
+ return _error->Error(_("Error occurred while processing %s (NewVersion%d)"),
+ PackageName.c_str(), 3);
// Read only a single record and return
if (OutVer != 0)
/* Record the Description data. Description data always exist in
Packages and Translation-* files. */
pkgCache::DescIterator Desc = Ver.DescriptionList();
+ Dynamic<pkgCache::DescIterator> DynDesc(Desc);
map_ptrloc *LastDesc = &Ver->DescriptionList;
-
+
// Skip to the end of description set
for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++);
// Add new description
- *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+ oldMap = Map.Data();
+ map_ptrloc const descindex = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc);
+ if (oldMap != Map.Data())
+ LastDesc += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ *LastDesc = descindex;
Desc->ParentPkg = Pkg.Index();
if ((*LastDesc == 0 && _error->PendingError()) || NewFileDesc(Desc,List) == false)
return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
- }
}
FoundFileDeps |= List.HasFileDeps();
continue;
pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName);
+ Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
if (Pkg.end() == true)
return _error->Error(_("Error occurred while processing %s (FindPkg)"),
PackageName.c_str());
unsigned long Hash = List.VersionHash();
pkgCache::VerIterator Ver = Pkg.VersionList();
- for (; Ver.end() == false; Ver++)
+ Dynamic<pkgCache::VerIterator> DynVer(Ver);
+ for (; Ver.end() == false; ++Ver)
{
if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr())
{
return true;
// Get a structure
- unsigned long const Group = Map.Allocate(sizeof(pkgCache::Group));
+ map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group));
if (unlikely(Group == 0))
return false;
Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
- Grp->Name = Map.WriteString(Name);
- if (unlikely(Grp->Name == 0))
+ map_ptrloc const idxName = WriteStringInMap(Name);
+ if (unlikely(idxName == 0))
return false;
+ Grp->Name = idxName;
// Insert it into the hash table
unsigned long const Hash = Cache.Hash(Name);
bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
const string &Arch) {
pkgCache::GrpIterator Grp;
+ Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
if (unlikely(NewGroup(Grp, Name) == false))
return false;
return true;
// Get a structure
- unsigned long const Package = Map.Allocate(sizeof(pkgCache::Package));
+ map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package));
if (unlikely(Package == 0))
return false;
Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
// Set the name, arch and the ID
Pkg->Name = Grp->Name;
Pkg->Group = Grp.Index();
- Pkg->Arch = WriteUniqString(Arch.c_str());
- if (unlikely(Pkg->Arch == 0))
+ // all is mapped to the native architecture
+ map_ptrloc const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : WriteUniqString(Arch.c_str());
+ if (unlikely(idxArch == 0))
return false;
+ Pkg->Arch = idxArch;
Pkg->ID = Cache.HeaderP->PackageCount++;
return true;
return true;
// Get a structure
- unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
+ map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
if (VerFile == 0)
return 0;
// Link it to the end of the list
map_ptrloc *Last = &Ver->FileList;
- for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; V++)
+ for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; ++V)
Last = &V->NextFile;
VF->NextFile = *Last;
*Last = VF.Index();
unsigned long Next)
{
// Get a structure
- unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
+ map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version));
if (Version == 0)
return 0;
Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
Ver->NextVer = Next;
Ver->ID = Cache.HeaderP->VersionCount++;
- Ver->VerStr = Map.WriteString(VerStr);
- if (Ver->VerStr == 0)
+ map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
+ if (unlikely(idxVerStr == 0))
return 0;
+ Ver->VerStr = idxVerStr;
return Version;
}
return true;
// Get a structure
- unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
+ map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
if (DescFile == 0)
return false;
// Link it to the end of the list
map_ptrloc *Last = &Desc->FileList;
- for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++)
+ for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; ++D)
Last = &D->NextFile;
DF->NextFile = *Last;
map_ptrloc Next)
{
// Get a structure
- map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
+ map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description));
if (Description == 0)
return 0;
Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
Desc->NextDesc = Next;
Desc->ID = Cache.HeaderP->DescriptionCount++;
- Desc->language_code = Map.WriteString(Lang);
- Desc->md5sum = Map.WriteString(md5sum.Value());
- if (Desc->language_code == 0 || Desc->md5sum == 0)
+ map_ptrloc const idxlanguage_code = WriteStringInMap(Lang);
+ map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value());
+ if (unlikely(idxlanguage_code == 0 || idxmd5sum == 0))
return 0;
+ Desc->language_code = idxlanguage_code;
+ Desc->md5sum = idxmd5sum;
return Description;
}
// CacheGenerator::FinishCache - do various finish operations /*{{{*/
// ---------------------------------------------------------------------
/* This prepares the Cache for delivery */
-bool pkgCacheGenerator::FinishCache(OpProgress &Progress)
+bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
{
// FIXME: add progress reporting for this operation
// Do we have different architectures in your groups ?
if (archs.size() > 1)
{
// Create Conflicts in between the group
- for (pkgCache::GrpIterator G = GetCache().GrpBegin(); G.end() != true; G++)
+ pkgCache::GrpIterator G = GetCache().GrpBegin();
+ Dynamic<pkgCache::GrpIterator> DynG(G);
+ for (; G.end() != true; ++G)
{
string const PkgName = G.Name();
- for (pkgCache::PkgIterator P = G.PackageList(); P.end() != true; P = G.NextPkg(P))
+ pkgCache::PkgIterator P = G.PackageList();
+ Dynamic<pkgCache::PkgIterator> DynP(P);
+ for (; P.end() != true; P = G.NextPkg(P))
{
- if (strcmp(P.Arch(),"all") == 0)
- continue;
pkgCache::PkgIterator allPkg;
- for (pkgCache::VerIterator V = P.VersionList(); V.end() != true; V++)
+ Dynamic<pkgCache::PkgIterator> DynallPkg(allPkg);
+ pkgCache::VerIterator V = P.VersionList();
+ Dynamic<pkgCache::VerIterator> DynV(V);
+ for (; V.end() != true; ++V)
{
- string const Arch = V.Arch(true);
+ // copy P.Arch() into a string here as a cache remap
+ // in NewDepends() later may alter the pointer location
+ string Arch = P.Arch() == NULL ? "" : P.Arch();
map_ptrloc *OldDepLast = NULL;
/* MultiArch handling introduces a lot of implicit Dependencies:
- MultiArch: same → Co-Installable if they have the same version
- Architecture: all → Need to be Co-Installable for internal reasons
- All others conflict with all other group members */
- bool const coInstall = (V->MultiArch == pkgCache::Version::All ||
- V->MultiArch == pkgCache::Version::Same);
- if (V->MultiArch == pkgCache::Version::All && allPkg.end() == true)
- allPkg = G.FindPkg("all");
+ bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
for (vector<string>::const_iterator A = archs.begin(); A != archs.end(); ++A)
{
if (*A == Arch)
per group, therefore each group member conflicts
with all other group members */
pkgCache::PkgIterator D = G.FindPkg(*A);
+ Dynamic<pkgCache::PkgIterator> DynD(D);
if (D.end() == true)
continue;
if (coInstall == true)
OldDepLast);
// Breaks: ${self}:other (!= ${binary:Version})
NewDepends(D, V, V.VerStr(),
- pkgCache::Dep::Less, pkgCache::Dep::DpkgBreaks,
+ pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks,
OldDepLast);
- NewDepends(D, V, V.VerStr(),
- pkgCache::Dep::Greater, pkgCache::Dep::DpkgBreaks,
- OldDepLast);
- if (V->MultiArch == pkgCache::Version::All)
- {
- // Depend on ${self}:all which does depend on nothing
- NewDepends(allPkg, V, V.VerStr(),
- pkgCache::Dep::Equals, pkgCache::Dep::Depends,
- OldDepLast);
- }
} else {
// Conflicts: ${self}:other
NewDepends(D, V, "",
string const &Version,
unsigned int const &Op,
unsigned int const &Type,
- map_ptrloc *OldDepLast)
+ map_ptrloc* &OldDepLast)
{
+ void const * const oldMap = Map.Data();
// Get a structure
- unsigned long const Dependency = Map.Allocate(sizeof(pkgCache::Dependency));
+ map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
if (unlikely(Dependency == 0))
return false;
// Fill it in
pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
+ Dynamic<pkgCache::DepIterator> DynDep(Dep);
Dep->ParentVer = Ver.Index();
Dep->Type = Type;
Dep->CompareOp = Op;
/* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
if (I->Version != 0 && I.TargetVer() == Version)
Dep->Version = I->Version;*/
- if (Dep->Version == 0)
- if (unlikely((Dep->Version = Map.WriteString(Version)) == 0))
+ if (Dep->Version == 0) {
+ map_ptrloc const index = WriteStringInMap(Version);
+ if (unlikely(index == 0))
return false;
+ Dep->Version = index;
+ }
}
// Link it to the package
if (OldDepLast == NULL)
{
OldDepLast = &Ver->DependsList;
- for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
+ for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; ++D)
OldDepLast = &D->NextDepends;
- }
+ } else if (oldMap != Map.Data())
+ OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
Dep->NextDepends = *OldDepLast;
*OldDepLast = Dep.Index();
// ---------------------------------------------------------------------
/* This creates a Group and the Package to link this dependency to if
needed and handles also the caching of the old endpoint */
-bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
+bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver,
const string &PackageName,
const string &Arch,
const string &Version,
unsigned int Type)
{
pkgCache::GrpIterator Grp;
+ Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
return false;
// Locate the target package
pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch);
+ Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
if (Pkg.end() == true) {
if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false))
return false;
// ListParser::NewProvides - Create a Provides element /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
+bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver,
const string &PkgName,
const string &PkgArch,
const string &Version)
pkgCache &Cache = Owner->Cache;
// We do not add self referencing provides
- if (Ver.ParentPkg().Name() == PkgName && PkgArch == Ver.Arch(true))
+ if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() ||
+ (PkgArch == "all" && strcmp((Cache.StrP + Cache.HeaderP->Architecture), Ver.ParentPkg().Arch()) == 0)))
return true;
// Get a structure
- unsigned long const Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
+ map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
if (unlikely(Provides == 0))
return false;
Cache.HeaderP->ProvidesCount++;
// Fill it in
pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
+ Dynamic<pkgCache::PrvIterator> DynPrv(Prv);
Prv->Version = Ver.Index();
Prv->NextPkgProv = Ver->ProvidesList;
Ver->ProvidesList = Prv.Index();
// Locate the target package
pkgCache::PkgIterator Pkg;
+ Dynamic<pkgCache::PkgIterator> DynPkg(Pkg);
if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false))
return false;
unsigned long Flags)
{
// Get some space for the structure
- CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
- if (CurrentFile == Cache.PkgFileP)
+ map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile));
+ if (unlikely(idxFile == 0))
return false;
-
+ CurrentFile = Cache.PkgFileP + idxFile;
+
// Fill it in
- CurrentFile->FileName = Map.WriteString(File);
- CurrentFile->Site = WriteUniqString(Site);
+ map_ptrloc const idxFileName = WriteStringInMap(File);
+ map_ptrloc const idxSite = WriteUniqString(Site);
+ if (unlikely(idxFileName == 0 || idxSite == 0))
+ return false;
+ CurrentFile->FileName = idxFileName;
+ CurrentFile->Site = idxSite;
CurrentFile->NextFile = Cache.HeaderP->FileList;
CurrentFile->Flags = Flags;
CurrentFile->ID = Cache.HeaderP->PackageFileCount;
- CurrentFile->IndexType = WriteUniqString(Index.GetType()->Label);
+ map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label);
+ if (unlikely(idxIndexType == 0))
+ return false;
+ CurrentFile->IndexType = idxIndexType;
PkgFileName = File;
Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
Cache.HeaderP->PackageFileCount++;
- if (CurrentFile->FileName == 0)
- return false;
-
if (Progress != 0)
Progress->SubProgress(Index.Size());
return true;
}
// Get a structure
- unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
+ void const * const oldMap = Map.Data();
+ map_ptrloc const Item = AllocateInMap(sizeof(pkgCache::StringItem));
if (Item == 0)
return 0;
+ map_ptrloc const idxString = WriteStringInMap(S,Size);
+ if (unlikely(idxString == 0))
+ return 0;
+ if (oldMap != Map.Data()) {
+ Last += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ I += (pkgCache::StringItem*) Map.Data() - (pkgCache::StringItem*) oldMap;
+ }
+ *Last = Item;
+
// Fill in the structure
pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
ItemP->NextItem = I - Cache.StringItemP;
- *Last = Item;
- ItemP->String = Map.WriteString(S,Size);
- if (ItemP->String == 0)
- return 0;
-
+ ItemP->String = idxString;
+
Bucket = ItemP;
return ItemP->String;
}
/* This just verifies that each file in the list of index files exists,
has matching attributes with the cache and the cache does not have
any extra files. */
-static bool CheckValidity(const string &CacheFile, FileIterator Start,
- FileIterator End,MMap **OutMap = 0)
+static bool CheckValidity(const string &CacheFile,
+ pkgSourceList &List,
+ FileIterator Start,
+ FileIterator End,
+ MMap **OutMap = 0)
{
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
// No file, certainly invalid
return false;
}
+ if (List.GetLastModifiedTime() > GetModificationTime(CacheFile))
+ {
+ if (Debug == true)
+ std::clog << "sources.list is newer than the cache" << std::endl;
+ return false;
+ }
+
// Map it
FileFd CacheF(CacheFile,FileFd::ReadOnly);
SPtr<MMap> Map = new MMap(CacheF,0);
verify the IMS data and check that it is on the disk too.. */
SPtrArray<bool> Visited = new bool[Cache.HeaderP->PackageFileCount];
memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount);
- for (; Start != End; Start++)
+ for (; Start != End; ++Start)
{
if (Debug == true)
std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
static unsigned long ComputeSize(FileIterator Start,FileIterator End)
{
unsigned long TotalSize = 0;
- for (; Start != End; Start++)
+ for (; Start != End; ++Start)
{
if ((*Start)->HasPackages() == false)
continue;
// ---------------------------------------------------------------------
/* */
static bool BuildCache(pkgCacheGenerator &Gen,
- OpProgress &Progress,
+ OpProgress *Progress,
unsigned long &CurrentSize,unsigned long TotalSize,
FileIterator Start, FileIterator End)
{
FileIterator I;
- for (I = Start; I != End; I++)
+ for (I = Start; I != End; ++I)
{
if ((*I)->HasPackages() == false)
continue;
}
unsigned long Size = (*I)->Size();
- Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
+ if (Progress != NULL)
+ Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
CurrentSize += Size;
if ((*I)->Merge(Gen,Progress) == false)
if (Gen.HasFileDeps() == true)
{
- Progress.Done();
+ if (Progress != NULL)
+ Progress->Done();
TotalSize = ComputeSize(Start, End);
CurrentSize = 0;
- for (I = Start; I != End; I++)
+ for (I = Start; I != End; ++I)
{
unsigned long Size = (*I)->Size();
- Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
+ if (Progress != NULL)
+ Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
CurrentSize += Size;
if ((*I)->MergeFileProvides(Gen,Progress) == false)
return false;
return true;
}
/*}}}*/
-// MakeStatusCache - Construct the status cache /*{{{*/
+// CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
+DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) {
+ unsigned long const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024);
+ unsigned long const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024);
+ unsigned long const MapLimit = _config->FindI("APT::Cache-Limit", 0);
+ Flags |= MMap::Moveable;
+ if (_config->FindB("APT::Cache-Fallback", false) == true)
+ Flags |= MMap::Fallback;
+ if (CacheF != NULL)
+ return new DynamicMMap(*CacheF, Flags, MapStart, MapGrow, MapLimit);
+ else
+ return new DynamicMMap(Flags, MapStart, MapGrow, MapLimit);
+}
+ /*}}}*/
+// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
// ---------------------------------------------------------------------
/* This makes sure that the status cache (the cache that has all
index files from the sources list and all local ones) is ready
the cache will be stored there. This is pretty much mandetory if you
are using AllowMem. AllowMem lets the function be run as non-root
where it builds the cache 'fast' into a memory buffer. */
-bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+__deprecated bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+ MMap **OutMap, bool AllowMem)
+ { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); }
+bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
MMap **OutMap,bool AllowMem)
{
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
- unsigned long const MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
vector<pkgIndexFile *> Files;
for (vector<metaIndex *>::const_iterator i = List.begin();
i != List.end();
- i++)
+ ++i)
{
vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
for (vector<pkgIndexFile *>::const_iterator j = Indexes->begin();
j != Indexes->end();
- j++)
+ ++j)
Files.push_back (*j);
}
if (Writeable == false && AllowMem == false && CacheFile.empty() == false)
return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str());
-
- Progress.OverallProgress(0,1,1,_("Reading package lists"));
-
+
+ if (Progress != NULL)
+ Progress->OverallProgress(0,1,1,_("Reading package lists"));
+
// Cache is OK, Fin.
- if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true)
+ if (CheckValidity(CacheFile, List, Files.begin(),Files.end(),OutMap) == true)
{
- Progress.OverallProgress(1,1,1,_("Reading package lists"));
+ if (Progress != NULL)
+ Progress->OverallProgress(1,1,1,_("Reading package lists"));
if (Debug == true)
std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl;
return true;
SPtr<DynamicMMap> Map;
if (Writeable == true && CacheFile.empty() == false)
{
+ _error->PushToStack();
unlink(CacheFile.c_str());
- CacheF = new FileFd(CacheFile,FileFd::WriteEmpty);
+ CacheF = new FileFd(CacheFile,FileFd::WriteAtomic);
fchmod(CacheF->Fd(),0644);
- Map = new DynamicMMap(*CacheF,MMap::Public,MapSize);
+ Map = CreateDynamicMMap(CacheF, MMap::Public);
if (_error->PendingError() == true)
- return false;
- if (Debug == true)
+ {
+ delete CacheF.UnGuard();
+ delete Map.UnGuard();
+ if (Debug == true)
+ std::clog << "Open filebased MMap FAILED" << std::endl;
+ Writeable = false;
+ if (AllowMem == false)
+ {
+ _error->MergeWithStack();
+ return false;
+ }
+ _error->RevertToStack();
+ }
+ else if (Debug == true)
+ {
+ _error->MergeWithStack();
std::clog << "Open filebased MMap" << std::endl;
+ }
}
- else
+ if (Writeable == false || CacheFile.empty() == true)
{
// Just build it in memory..
- Map = new DynamicMMap(0,MapSize);
+ Map = CreateDynamicMMap(NULL);
if (Debug == true)
std::clog << "Open memory Map (not filebased)" << std::endl;
}
// Lets try the source cache.
unsigned long CurrentSize = 0;
unsigned long TotalSize = 0;
- if (CheckValidity(SrcCacheFile,Files.begin(),
+ if (CheckValidity(SrcCacheFile, List, Files.begin(),
Files.begin()+EndOfSource) == true)
{
if (Debug == true)
TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
// Build the status cache
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
TotalSize = ComputeSize(Files.begin(),Files.end());
// Build the source cache
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
// Write it back
if (Writeable == true && SrcCacheFile.empty() == false)
{
- FileFd SCacheF(SrcCacheFile,FileFd::WriteEmpty);
+ FileFd SCacheF(SrcCacheFile,FileFd::WriteAtomic);
if (_error->PendingError() == true)
return false;
return true;
}
/*}}}*/
-// MakeOnlyStatusCache - Build a cache with just the status files /*{{{*/
+// CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
// ---------------------------------------------------------------------
/* */
-bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+__deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+ { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
+bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
vector<pkgIndexFile *> Files;
unsigned long EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)
return false;
-
- SPtr<DynamicMMap> Map = new DynamicMMap(0,MapSize);
+
+ SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
unsigned long CurrentSize = 0;
unsigned long TotalSize = 0;
TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
// Build the status cache
- Progress.OverallProgress(0,1,1,_("Reading package lists"));
- pkgCacheGenerator Gen(Map.Get(),&Progress);
+ if (Progress != NULL)
+ Progress->OverallProgress(0,1,1,_("Reading package lists"));
+ pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
if (BuildCache(Gen,Progress,CurrentSize,TotalSize,