#include <apt-pkg/progress.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/configuration.h>
-#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/macros.h>
-#include <apt-pkg/tagfile.h>
#include <apt-pkg/metaindex.h>
#include <apt-pkg/fileutl.h>
-
+#include <apt-pkg/hashsum_template.h>
+#include <apt-pkg/indexfile.h>
+#include <apt-pkg/md5.h>
+#include <apt-pkg/mmap.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cacheiterators.h>
+
+#include <stddef.h>
+#include <string.h>
+#include <iostream>
+#include <string>
#include <vector>
#include <sys/stat.h>
#include <unistd.h>
-#include <errno.h>
-#include <stdio.h>
#include <apti18n.h>
/*}}}*/
/* We set the dirty flag and make sure that is written to the disk */
pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) :
Map(*pMap), Cache(pMap,false), Progress(Prog),
- FoundFileDeps(0)
+ CurrentRlsFile(NULL), CurrentFile(NULL), FoundFileDeps(0)
{
- CurrentFile = 0;
- memset(UniqHash,0,sizeof(UniqHash));
-
if (_error->PendingError() == true)
return;
// Starting header
*Cache.HeaderP = pkgCache::Header();
- map_ptrloc const idxVerSysName = WriteStringInMap(_system->VS->Label);
+
+ // make room for the hashtables for packages and groups
+ if (Map.RawAllocate(2 * (Cache.HeaderP->GetHashTableSize() * sizeof(map_pointer_t))) == 0)
+ return;
+
+ map_stringitem_t const idxVerSysName = WriteStringInMap(_system->VS->Label);
+ if (unlikely(idxVerSysName == 0))
+ return;
Cache.HeaderP->VerSysName = idxVerSysName;
- // this pointer is set in ReMap, but we need it now for WriteUniqString
- Cache.StringItemP = (pkgCache::StringItem *)Map.Data();
- map_ptrloc const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
- Cache.HeaderP->Architecture = idxArchitecture;
- if (unlikely(idxVerSysName == 0 || idxArchitecture == 0))
+ map_stringitem_t const idxArchitecture = StoreString(MIXED, _config->Find("APT::Architecture"));
+ if (unlikely(idxArchitecture == 0))
return;
+ Cache.HeaderP->Architecture = idxArchitecture;
+
+ std::vector<std::string> archs = APT::Configuration::getArchitectures();
+ if (archs.size() > 1)
+ {
+ std::vector<std::string>::const_iterator a = archs.begin();
+ std::string list = *a;
+ for (++a; a != archs.end(); ++a)
+ list.append(",").append(*a);
+ map_stringitem_t const idxArchitectures = WriteStringInMap(list);
+ if (unlikely(idxArchitectures == 0))
+ return;
+ Cache.HeaderP->SetArchitectures(idxArchitectures);
+ }
+ else
+ Cache.HeaderP->SetArchitectures(idxArchitecture);
+
Cache.ReMap();
}
else
{
_error->Error(_("Cache has an incompatible versioning system"));
return;
- }
+ }
}
-
+
Cache.HeaderP->Dirty = true;
Map.Sync(0,sizeof(pkgCache::Header));
}
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;
+ CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap;
+ CurrentRlsFile += (pkgCache::ReleaseFile const * const) newMap - (pkgCache::ReleaseFile const * const) oldMap;
for (std::vector<pkgCache::GrpIterator*>::const_iterator i = Dynamic<pkgCache::GrpIterator>::toReMap.begin();
i != Dynamic<pkgCache::GrpIterator>::toReMap.end(); ++i)
for (std::vector<pkgCache::PkgFileIterator*>::const_iterator i = Dynamic<pkgCache::PkgFileIterator>::toReMap.begin();
i != Dynamic<pkgCache::PkgFileIterator>::toReMap.end(); ++i)
(*i)->ReMap(oldMap, newMap);
+ for (std::vector<pkgCache::RlsFileIterator*>::const_iterator i = Dynamic<pkgCache::RlsFileIterator>::toReMap.begin();
+ i != Dynamic<pkgCache::RlsFileIterator>::toReMap.end(); ++i)
+ (*i)->ReMap(oldMap, newMap);
} /*}}}*/
// CacheGenerator::WriteStringInMap /*{{{*/
-map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String,
+map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String,
const unsigned long &Len) {
void const * const oldMap = Map.Data();
- map_ptrloc const index = Map.WriteString(String, Len);
+ map_stringitem_t const index = Map.WriteString(String, Len);
if (index != 0)
ReMap(oldMap, Map.Data());
return index;
}
/*}}}*/
// CacheGenerator::WriteStringInMap /*{{{*/
-map_ptrloc pkgCacheGenerator::WriteStringInMap(const char *String) {
+map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String) {
void const * const oldMap = Map.Data();
- map_ptrloc const index = Map.WriteString(String);
+ map_stringitem_t const index = Map.WriteString(String);
if (index != 0)
ReMap(oldMap, Map.Data());
return index;
}
/*}}}*/
-map_ptrloc pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
+map_pointer_t pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
void const * const oldMap = Map.Data();
- map_ptrloc const index = Map.Allocate(size);
+ map_pointer_t const index = Map.Allocate(size);
if (index != 0)
ReMap(oldMap, Map.Data());
return index;
}
}
- if (Cache.HeaderP->PackageCount >= (1ULL<<sizeof(Cache.PkgP->ID)*8)-1)
+ if (Cache.HeaderP->PackageCount >= std::numeric_limits<map_id_t>::max())
return _error->Error(_("Wow, you exceeded the number of package "
"names this APT is capable of."));
- if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
+ if (Cache.HeaderP->VersionCount >= std::numeric_limits<map_id_t>::max())
return _error->Error(_("Wow, you exceeded the number of versions "
"this APT is capable of."));
- if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1)
+ if (Cache.HeaderP->DescriptionCount >= std::numeric_limits<map_id_t>::max())
return _error->Error(_("Wow, you exceeded the number of descriptions "
"this APT is capable of."));
- if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL)
+ if (Cache.HeaderP->DependsCount >= std::numeric_limits<map_id_t>::max())
return _error->Error(_("Wow, you exceeded the number of dependencies "
"this APT is capable of."));
// Find the right version to write the description
MD5SumValue CurMd5 = List.Description_md5();
- std::string CurLang = List.DescriptionLanguage();
-
+ if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
+ return true;
+ std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver)
{
pkgCache::DescIterator VerDesc = Ver.DescriptionList();
if (VerDesc.end() == true || MD5SumValue(VerDesc.md5()) != CurMd5)
continue;
- // don't add a new description if we have one for the given
- // md5 && language
- if (IsDuplicateDescription(VerDesc, CurMd5, CurLang) == true)
- continue;
-
- pkgCache::DescIterator Desc;
- Dynamic<pkgCache::DescIterator> DynDesc(Desc);
-
- map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, VerDesc->md5sum);
- if (unlikely(descindex == 0 && _error->PendingError()))
- return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewDescription", 1);
-
- Desc->ParentPkg = Pkg.Index();
-
- // we add at the end, so that the start is constant as we need
- // that to be able to efficiently share these lists
- VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
- for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
- map_ptrloc * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
- *LastNextDesc = descindex;
+ map_stringitem_t md5idx = VerDesc->md5sum;
+ for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+ {
+ // don't add a new description if we have one for the given
+ // md5 && language
+ if (IsDuplicateDescription(VerDesc, CurMd5, *CurLang) == true)
+ continue;
- if (NewFileDesc(Desc,List) == false)
- return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewFileDesc", 1);
+ AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx);
+ }
// we can stop here as all "same" versions will share the description
break;
{
pkgCache::VerIterator Ver = Pkg.VersionList();
Dynamic<pkgCache::VerIterator> DynVer(Ver);
- map_ptrloc *LastVer = &Pkg->VersionList;
+ map_pointer_t *LastVer = &Pkg->VersionList;
void const * oldMap = Map.Data();
- unsigned long const Hash = List.VersionHash();
+ unsigned short const Hash = List.VersionHash();
if (Ver.end() == false)
{
/* We know the list is sorted so we use that fact in the search.
Insertion of new versions is done with correct sorting */
int Res = 1;
- for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, ++Ver)
{
Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
// Version is higher as current version - insert here
if (Res > 0)
break;
// Versionstrings are equal - is hash also equal?
- if (Res == 0 && Ver->Hash == Hash)
+ if (Res == 0 && List.SameVersion(Hash, Ver) == true)
break;
// proceed with the next till we have either the right
// or we found another version (which will be lower)
}
// Add a new version
- map_ptrloc const verindex = NewVersion(Ver,Version,*LastVer);
+ map_pointer_t const verindex = NewVersion(Ver, Version, Pkg.Index(), Hash, *LastVer);
if (verindex == 0 && _error->PendingError())
return _error->Error(_("Error occurred while processing %s (%s%d)"),
Pkg.Name(), "NewVersion", 1);
if (oldMap != Map.Data())
- LastVer += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ LastVer += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
*LastVer = verindex;
- Ver->ParentPkg = Pkg.Index();
- Ver->Hash = Hash;
if (unlikely(List.NewVersion(Ver) == false))
return _error->Error(_("Error occurred while processing %s (%s%d)"),
D.ParentPkg().Group() == Grp)
continue;
- map_ptrloc *OldDepLast = NULL;
+ map_pointer_t *OldDepLast = NULL;
pkgCache::VerIterator ConVersion = D.ParentVer();
Dynamic<pkgCache::VerIterator> DynV(ConVersion);
// duplicate the Conflicts/Breaks/Replaces for :none arch
return true;
}
- /* Record the Description (it is not translated) */
+ /* Record the Description(s) based on their master md5sum */
MD5SumValue CurMd5 = List.Description_md5();
- if (CurMd5.Value().empty() == true)
+ if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
return true;
- std::string CurLang = List.DescriptionLanguage();
/* Before we add a new description we first search in the group for
a version with a description of the same MD5 - if so we reuse this
for (pkgCache::VerIterator V = P.VersionList();
V.end() == false; ++V)
{
- if (IsDuplicateDescription(V.DescriptionList(), CurMd5, "") == false)
+ if (V->DescriptionList == 0 || MD5SumValue(V.DescriptionList().md5()) != CurMd5)
continue;
Ver->DescriptionList = V->DescriptionList;
- return true;
}
}
- // We haven't found reusable descriptions, so add the first description
- pkgCache::DescIterator Desc = Ver.DescriptionList();
+ // We haven't found reusable descriptions, so add the first description(s)
+ map_stringitem_t md5idx = Ver->DescriptionList == 0 ? 0 : Ver.DescriptionList()->md5sum;
+ std::vector<std::string> availDesc = List.AvailableDescriptionLanguages();
+ for (std::vector<std::string>::const_iterator CurLang = availDesc.begin(); CurLang != availDesc.end(); ++CurLang)
+ if (AddNewDescription(List, Ver, *CurLang, CurMd5, md5idx) == false)
+ return false;
+ return true;
+}
+ /*}}}*/
+bool pkgCacheGenerator::AddNewDescription(ListParser &List, pkgCache::VerIterator &Ver, std::string const &lang, MD5SumValue const &CurMd5, map_stringitem_t &md5idx) /*{{{*/
+{
+ pkgCache::DescIterator Desc;
Dynamic<pkgCache::DescIterator> DynDesc(Desc);
- map_ptrloc const descindex = NewDescription(Desc, CurLang, CurMd5, 0);
+ map_pointer_t const descindex = NewDescription(Desc, lang, CurMd5, md5idx);
if (unlikely(descindex == 0 && _error->PendingError()))
return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewDescription", 2);
+ Ver.ParentPkg().Name(), "NewDescription", 1);
+
+ md5idx = Desc->md5sum;
+ Desc->ParentPkg = Ver.ParentPkg().Index();
- Desc->ParentPkg = Pkg.Index();
- Ver->DescriptionList = descindex;
+ // we add at the end, so that the start is constant as we need
+ // that to be able to efficiently share these lists
+ pkgCache::DescIterator VerDesc = Ver.DescriptionList(); // old value might be invalid after ReMap
+ for (;VerDesc.end() == false && VerDesc->NextDesc != 0; ++VerDesc);
+ map_pointer_t * const LastNextDesc = (VerDesc.end() == true) ? &Ver->DescriptionList : &VerDesc->NextDesc;
+ *LastNextDesc = descindex;
if (NewFileDesc(Desc,List) == false)
return _error->Error(_("Error occurred while processing %s (%s%d)"),
- Pkg.Name(), "NewFileDesc", 2);
+ Ver.ParentPkg().Name(), "NewFileDesc", 1);
return true;
}
if (Counter % 100 == 0 && Progress != 0)
Progress->Progress(List.Offset());
- unsigned long Hash = List.VersionHash();
+ unsigned short Hash = List.VersionHash();
pkgCache::VerIterator Ver = Pkg.VersionList();
Dynamic<pkgCache::VerIterator> DynVer(Ver);
for (; Ver.end() == false; ++Ver)
{
- if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr())
+ if (List.SameVersion(Hash, Ver) == true && Version == Ver.VerStr())
{
if (List.CollectFileProvides(Cache,Ver) == false)
return _error->Error(_("Error occurred while processing %s (%s%d)"),
return true;
// Get a structure
- map_ptrloc const Group = AllocateInMap(sizeof(pkgCache::Group));
+ map_pointer_t const Group = AllocateInMap(sizeof(pkgCache::Group));
if (unlikely(Group == 0))
return false;
Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
- map_ptrloc const idxName = WriteStringInMap(Name);
+ map_stringitem_t const idxName = StoreString(PKGNAME, Name);
if (unlikely(idxName == 0))
return false;
Grp->Name = idxName;
// Insert it into the hash table
unsigned long const Hash = Cache.Hash(Name);
- map_ptrloc *insertAt = &Cache.HeaderP->GrpHashTable[Hash];
+ map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTableP()[Hash];
while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
insertAt = &(Cache.GrpP + *insertAt)->Next;
Grp->Next = *insertAt;
return true;
// Get a structure
- map_ptrloc const Package = AllocateInMap(sizeof(pkgCache::Package));
+ map_pointer_t const Package = AllocateInMap(sizeof(pkgCache::Package));
if (unlikely(Package == 0))
return false;
Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
{
Grp->FirstPackage = Package;
// Insert it into the hash table
- unsigned long const Hash = Cache.Hash(Name);
- map_ptrloc *insertAt = &Cache.HeaderP->PkgHashTable[Hash];
- while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0)
+ map_id_t const Hash = Cache.Hash(Name);
+ map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTableP()[Hash];
+ while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
Pkg->NextPackage = *insertAt;
*insertAt = Package;
Grp->LastPackage = Package;
// Set the name, arch and the ID
- Pkg->Name = Grp->Name;
+ APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;)
Pkg->Group = Grp.Index();
// all is mapped to the native architecture
- map_ptrloc const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : WriteUniqString(Arch.c_str());
+ map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch);
if (unlikely(idxArch == 0))
return false;
Pkg->Arch = idxArch;
// 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;
+ map_pointer_t *OldDepLast = NULL;
/* MultiArch handling introduces a lot of implicit Dependencies:
- MultiArch: same → Co-Installable if they have the same version
- All others conflict with all other group members */
bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
pkgCache::PkgIterator D = G.PackageList();
Dynamic<pkgCache::PkgIterator> DynD(D);
- map_ptrloc const VerStrIdx = V->VerStr;
+ map_stringitem_t const VerStrIdx = V->VerStr;
for (; D.end() != true; D = G.NextPkg(D))
{
if (Arch == D.Arch() || D->VersionList == 0)
/* MultiArch handling introduces a lot of implicit Dependencies:
- MultiArch: same → Co-Installable if they have the same version
- All others conflict with all other group members */
- map_ptrloc *OldDepLast = NULL;
+ map_pointer_t *OldDepLast = NULL;
bool const coInstall = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
if (coInstall == true)
{
- map_ptrloc const VerStrIdx = V->VerStr;
+ map_stringitem_t const VerStrIdx = V->VerStr;
// Replaces: ${self}:other ( << ${binary:Version})
NewDepends(D, V, VerStrIdx,
pkgCache::Dep::Less, pkgCache::Dep::Replaces,
return true;
// Get a structure
- map_ptrloc const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
+ map_pointer_t const VerFile = AllocateInMap(sizeof(pkgCache::VerFile));
if (VerFile == 0)
- return 0;
+ return false;
pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
VF->File = CurrentFile - Cache.PkgFileP;
// Link it to the end of the list
- map_ptrloc *Last = &Ver->FileList;
+ map_pointer_t *Last = &Ver->FileList;
for (pkgCache::VerFileIterator V = Ver.FileList(); V.end() == false; ++V)
Last = &V->NextFile;
VF->NextFile = *Last;
// CacheGenerator::NewVersion - Create a new Version /*{{{*/
// ---------------------------------------------------------------------
/* This puts a version structure in the linked list */
-unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
+map_pointer_t pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
const string &VerStr,
- unsigned long Next)
+ map_pointer_t const ParentPkg,
+ unsigned short const Hash,
+ map_pointer_t const Next)
{
// Get a structure
- map_ptrloc const Version = AllocateInMap(sizeof(pkgCache::Version));
+ map_pointer_t const Version = AllocateInMap(sizeof(pkgCache::Version));
if (Version == 0)
return 0;
Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
//Dynamic<pkgCache::VerIterator> DynV(Ver); // caller MergeListVersion already takes care of it
Ver->NextVer = Next;
+ Ver->ParentPkg = ParentPkg;
+ Ver->Hash = Hash;
Ver->ID = Cache.HeaderP->VersionCount++;
- map_ptrloc const idxVerStr = WriteStringInMap(VerStr);
+
+ // try to find the version string in the group for reuse
+ pkgCache::PkgIterator Pkg = Ver.ParentPkg();
+ pkgCache::GrpIterator Grp = Pkg.Group();
+ if (Pkg.end() == false && Grp.end() == false)
+ {
+ for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+ {
+ if (Pkg == P)
+ continue;
+ for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; ++V)
+ {
+ int const cmp = strcmp(V.VerStr(), VerStr.c_str());
+ if (cmp == 0)
+ {
+ Ver->VerStr = V->VerStr;
+ return Version;
+ }
+ else if (cmp < 0)
+ break;
+ }
+ }
+ }
+ // haven't found the version string, so create
+ map_stringitem_t const idxVerStr = StoreString(VERSIONNUMBER, VerStr);
if (unlikely(idxVerStr == 0))
return 0;
Ver->VerStr = idxVerStr;
-
return Version;
}
/*}}}*/
return true;
// Get a structure
- map_ptrloc const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
+ map_pointer_t const DescFile = AllocateInMap(sizeof(pkgCache::DescFile));
if (DescFile == 0)
return false;
DF->File = CurrentFile - Cache.PkgFileP;
// Link it to the end of the list
- map_ptrloc *Last = &Desc->FileList;
+ map_pointer_t *Last = &Desc->FileList;
for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; ++D)
Last = &D->NextFile;
// CacheGenerator::NewDescription - Create a new Description /*{{{*/
// ---------------------------------------------------------------------
/* This puts a description structure in the linked list */
-map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
+map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
const string &Lang,
const MD5SumValue &md5sum,
- map_ptrloc idxmd5str)
+ map_stringitem_t const idxmd5str)
{
// Get a structure
- map_ptrloc const Description = AllocateInMap(sizeof(pkgCache::Description));
+ map_pointer_t const Description = AllocateInMap(sizeof(pkgCache::Description));
if (Description == 0)
return 0;
// Fill it in
Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
Desc->ID = Cache.HeaderP->DescriptionCount++;
- map_ptrloc const idxlanguage_code = WriteUniqString(Lang);
+ map_stringitem_t const idxlanguage_code = StoreString(MIXED, Lang);
if (unlikely(idxlanguage_code == 0))
return 0;
Desc->language_code = idxlanguage_code;
Desc->md5sum = idxmd5str;
else
{
- map_ptrloc const idxmd5sum = WriteStringInMap(md5sum.Value());
+ map_stringitem_t const idxmd5sum = WriteStringInMap(md5sum.Value());
if (unlikely(idxmd5sum == 0))
return 0;
Desc->md5sum = idxmd5sum;
string const &Version,
unsigned int const &Op,
unsigned int const &Type,
- map_ptrloc* &OldDepLast)
+ map_stringitem_t* &OldDepLast)
{
- map_ptrloc index = 0;
+ map_stringitem_t index = 0;
if (Version.empty() == false)
{
int const CmpOp = Op & 0x0F;
if (index == 0)
{
void const * const oldMap = Map.Data();
- index = WriteStringInMap(Version);
+ index = StoreString(VERSIONNUMBER, Version);
if (unlikely(index == 0))
return false;
- if (oldMap != Map.Data())
- OldDepLast += (map_ptrloc*) Map.Data() - (map_ptrloc*) oldMap;
+ if (OldDepLast != 0 && oldMap != Map.Data())
+ OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
}
}
return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast);
}
bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
pkgCache::VerIterator &Ver,
- map_ptrloc const Version,
+ map_pointer_t const Version,
unsigned int const &Op,
unsigned int const &Type,
- map_ptrloc* &OldDepLast)
+ map_pointer_t* &OldDepLast)
{
void const * const oldMap = Map.Data();
// Get a structure
- map_ptrloc const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
+ map_pointer_t const Dependency = AllocateInMap(sizeof(pkgCache::Dependency));
if (unlikely(Dependency == 0))
return false;
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;
+ OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
Dep->NextDepends = *OldDepLast;
*OldDepLast = Dep.Index();
return true;
// Get a structure
- map_ptrloc const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
+ map_pointer_t const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides));
if (unlikely(Provides == 0))
return false;
Cache.HeaderP->ProvidesCount++;
Prv->NextPkgProv = Ver->ProvidesList;
Ver->ProvidesList = Prv.Index();
if (Version.empty() == false) {
- map_ptrloc const idxProvideVersion = WriteString(Version);
+ map_stringitem_t const idxProvideVersion = WriteString(Version);
Prv->ProvideVersion = idxProvideVersion;
if (unlikely(idxProvideVersion == 0))
return false;
Prv->NextProvides = Pkg->ProvidesList;
Pkg->ProvidesList = Prv.Index();
+ return true;
+}
+ /*}}}*/
+bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{*/
+ pkgCache::VerIterator const &Ver)
+{
+ return Hash == Ver->Hash;
+}
+ /*}}}*/
+// CacheGenerator::SelectReleaseFile - Select the current release file the indexes belong to /*{{{*/
+bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site,
+ unsigned long Flags)
+{
+ if (File.empty() && Site.empty())
+ {
+ CurrentRlsFile = NULL;
+ return true;
+ }
+
+ // Get some space for the structure
+ map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentRlsFile));
+ if (unlikely(idxFile == 0))
+ return false;
+ CurrentRlsFile = Cache.RlsFileP + idxFile;
+
+ // Fill it in
+ map_stringitem_t const idxFileName = WriteStringInMap(File);
+ map_stringitem_t const idxSite = StoreString(MIXED, Site);
+ if (unlikely(idxFileName == 0 || idxSite == 0))
+ return false;
+ CurrentRlsFile->FileName = idxFileName;
+ CurrentRlsFile->Site = idxSite;
+ CurrentRlsFile->NextFile = Cache.HeaderP->RlsFileList;
+ CurrentRlsFile->Flags = Flags;
+ CurrentRlsFile->ID = Cache.HeaderP->ReleaseFileCount;
+ RlsFileName = File;
+ Cache.HeaderP->RlsFileList = CurrentRlsFile - Cache.RlsFileP;
+ Cache.HeaderP->ReleaseFileCount++;
+
return true;
}
/*}}}*/
// ---------------------------------------------------------------------
/* This is used to select which file is to be associated with all newly
added versions. The caller is responsible for setting the IMS fields. */
-bool pkgCacheGenerator::SelectFile(const string &File,const string &Site,
- const pkgIndexFile &Index,
- unsigned long Flags)
+bool pkgCacheGenerator::SelectFile(std::string const &File,
+ pkgIndexFile const &Index,
+ std::string const &Component,
+ unsigned long const Flags)
{
// Get some space for the structure
- map_ptrloc const idxFile = AllocateInMap(sizeof(*CurrentFile));
+ map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile));
if (unlikely(idxFile == 0))
return false;
CurrentFile = Cache.PkgFileP + idxFile;
// Fill it in
- map_ptrloc const idxFileName = WriteStringInMap(File);
- map_ptrloc const idxSite = WriteUniqString(Site);
- if (unlikely(idxFileName == 0 || idxSite == 0))
+ map_stringitem_t const idxFileName = WriteStringInMap(File);
+ if (unlikely(idxFileName == 0))
return false;
CurrentFile->FileName = idxFileName;
- CurrentFile->Site = idxSite;
CurrentFile->NextFile = Cache.HeaderP->FileList;
- CurrentFile->Flags = Flags;
CurrentFile->ID = Cache.HeaderP->PackageFileCount;
- map_ptrloc const idxIndexType = WriteUniqString(Index.GetType()->Label);
+ map_stringitem_t const idxIndexType = StoreString(MIXED, Index.GetType()->Label);
if (unlikely(idxIndexType == 0))
return false;
CurrentFile->IndexType = idxIndexType;
+ map_stringitem_t const component = StoreString(pkgCacheGenerator::MIXED, Component);
+ if (unlikely(component == 0))
+ return false;
+ CurrentFile->Component = component;
+ CurrentFile->Flags = Flags;
+ if (CurrentRlsFile != NULL)
+ CurrentFile->Release = CurrentRlsFile - Cache.RlsFileP;
+ else
+ CurrentFile->Release = 0;
PkgFileName = File;
Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
Cache.HeaderP->PackageFileCount++;
// ---------------------------------------------------------------------
/* This is used to create handles to strings. Given the same text it
always returns the same number */
-unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
+map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, const char *S,
unsigned int Size)
{
- /* We use a very small transient hash table here, this speeds up generation
- by a fair amount on slower machines */
- pkgCache::StringItem *&Bucket = UniqHash[(S[0]*5 + S[1]) % _count(UniqHash)];
- if (Bucket != 0 &&
- stringcmp(S,S+Size,Cache.StrP + Bucket->String) == 0)
- return Bucket->String;
-
- // Search for an insertion point
- pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
- int Res = 1;
- map_ptrloc *Last = &Cache.HeaderP->StringList;
- for (; I != Cache.StringItemP; Last = &I->NextItem,
- I = Cache.StringItemP + I->NextItem)
- {
- Res = stringcmp(S,S+Size,Cache.StrP + I->String);
- if (Res >= 0)
- break;
- }
-
- // Match
- if (Res == 0)
- {
- Bucket = I;
- return I->String;
- }
-
- // Get a structure
- 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;
+ std::string const key(S, Size);
+
+ std::map<std::string,map_stringitem_t> * strings;
+ switch(type) {
+ case MIXED: strings = &strMixed; break;
+ case PKGNAME: strings = &strPkgNames; break;
+ case VERSIONNUMBER: strings = &strVersions; break;
+ case SECTION: strings = &strSections; break;
+ default: _error->Fatal("Unknown enum type used for string storage of '%s'", key.c_str()); return 0;
}
- *Last = Item;
- // Fill in the structure
- pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
- ItemP->NextItem = I - Cache.StringItemP;
- ItemP->String = idxString;
+ std::map<std::string,map_stringitem_t>::const_iterator const item = strings->find(key);
+ if (item != strings->end())
+ return item->second;
- Bucket = ItemP;
- return ItemP->String;
+ map_stringitem_t const idxString = WriteStringInMap(S,Size);
+ strings->insert(std::make_pair(key, idxString));
+ return idxString;
}
/*}}}*/
// CheckValidity - Check that a cache is up-to-date /*{{{*/
_error->Discard();
return false;
}
-
+
+ SPtrArray<bool> RlsVisited = new bool[Cache.HeaderP->ReleaseFileCount];
+ memset(RlsVisited,0,sizeof(*RlsVisited)*Cache.HeaderP->ReleaseFileCount);
+ std::vector<pkgIndexFile *> Files;
+ for (pkgSourceList::const_iterator i = List.begin(); i != List.end(); ++i)
+ {
+ if (Debug == true)
+ std::clog << "Checking RlsFile " << (*i)->Describe() << ": ";
+ pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache, true);
+ if (RlsFile.end() == true)
+ {
+ if (Debug == true)
+ std::clog << "FindInCache returned end-Pointer" << std::endl;
+ return false;
+ }
+
+ RlsVisited[RlsFile->ID] = true;
+ if (Debug == true)
+ std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl;
+
+ std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+ for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j)
+ if ((*j)->HasPackages())
+ Files.push_back (*j);
+ }
+ for (unsigned I = 0; I != Cache.HeaderP->ReleaseFileCount; ++I)
+ if (RlsVisited[I] == false)
+ {
+ if (Debug == true)
+ std::clog << "RlsFile with ID" << I << " wasn't visited" << std::endl;
+ return false;
+ }
+
+ for (; Start != End; ++Start)
+ Files.push_back(*Start);
+
/* Now we check every index file, see if it is in the cache,
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 (std::vector<pkgIndexFile *>::const_reverse_iterator PkgFile = Files.rbegin(); PkgFile != Files.rend(); ++PkgFile)
{
if (Debug == true)
- std::clog << "Checking PkgFile " << (*Start)->Describe() << ": ";
- if ((*Start)->HasPackages() == false)
+ std::clog << "Checking PkgFile " << (*PkgFile)->Describe() << ": ";
+ if ((*PkgFile)->Exists() == false)
{
- if (Debug == true)
- std::clog << "Has NO packages" << std::endl;
- continue;
- }
-
- if ((*Start)->Exists() == false)
- {
-#if 0 // mvo: we no longer give a message here (Default Sources spec)
- _error->WarningE("stat",_("Couldn't stat source package list %s"),
- (*Start)->Describe().c_str());
-#endif
if (Debug == true)
std::clog << "file doesn't exist" << std::endl;
continue;
}
// FindInCache is also expected to do an IMS check.
- pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
+ pkgCache::PkgFileIterator File = (*PkgFile)->FindInCache(Cache);
if (File.end() == true)
{
if (Debug == true)
if (Debug == true)
std::clog << "with ID " << File->ID << " is valid" << std::endl;
}
-
+
for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++)
if (Visited[I] == false)
{
if (Debug == true)
- std::clog << "File with ID" << I << " wasn't visited" << std::endl;
+ std::clog << "PkgFile with ID" << I << " wasn't visited" << std::endl;
return false;
}
-
+
if (_error->PendingError() == true)
{
if (Debug == true)
// ---------------------------------------------------------------------
/* Size is kind of an abstract notion that is only used for the progress
meter */
-static unsigned long ComputeSize(FileIterator Start,FileIterator End)
+static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator Start,FileIterator End)
{
- unsigned long TotalSize = 0;
- for (; Start != End; ++Start)
+ map_filesize_t TotalSize = 0;
+ if (List != NULL)
+ {
+ for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i)
+ {
+ std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+ for (std::vector<pkgIndexFile *>::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j)
+ if ((*j)->HasPackages() == true)
+ TotalSize += (*j)->Size();
+ }
+ }
+
+ for (; Start < End; ++Start)
{
if ((*Start)->HasPackages() == false)
- continue;
+ continue;
TotalSize += (*Start)->Size();
}
return TotalSize;
/* */
static bool BuildCache(pkgCacheGenerator &Gen,
OpProgress *Progress,
- unsigned long &CurrentSize,unsigned long TotalSize,
+ map_filesize_t &CurrentSize,map_filesize_t TotalSize,
+ pkgSourceList const * const List,
FileIterator Start, FileIterator End)
{
+ std::vector<pkgIndexFile *> Files;
+ bool const HasFileDeps = Gen.HasFileDeps();
+
+ if (List != NULL)
+ {
+ for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i)
+ {
+ if ((*i)->FindInCache(Gen.GetCache(), false).end() == false)
+ {
+ _error->Warning("Duplicate sources.list entry %s",
+ (*i)->Describe().c_str());
+ continue;
+ }
+
+ if ((*i)->Merge(Gen, Progress) == false)
+ return false;
+
+ std::vector <pkgIndexFile *> *Indexes = (*i)->GetIndexFiles();
+ for (std::vector<pkgIndexFile *>::const_iterator I = Indexes->begin(); I != Indexes->end(); ++I)
+ {
+ if (HasFileDeps)
+ Files.push_back(*I);
+
+ if ((*I)->HasPackages() == false)
+ continue;
+
+ if ((*I)->Exists() == false)
+ continue;
+
+ if ((*I)->FindInCache(Gen.GetCache()).end() == false)
+ {
+ _error->Warning("Duplicate sources.list entry %s",
+ (*I)->Describe().c_str());
+ continue;
+ }
+
+ map_filesize_t Size = (*I)->Size();
+ if (Progress != NULL)
+ Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
+ CurrentSize += Size;
+
+ if ((*I)->Merge(Gen,Progress) == false)
+ return false;
+ }
+ }
+ }
+
+ Gen.SelectReleaseFile("", "");
FileIterator I;
for (I = Start; I != End; ++I)
{
+ if (HasFileDeps)
+ Files.push_back(*I);
+
if ((*I)->HasPackages() == false)
continue;
continue;
}
- unsigned long Size = (*I)->Size();
+ map_filesize_t Size = (*I)->Size();
if (Progress != NULL)
Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists"));
CurrentSize += Size;
return false;
}
- if (Gen.HasFileDeps() == true)
+ if (HasFileDeps == true)
{
if (Progress != NULL)
Progress->Done();
- TotalSize = ComputeSize(Start, End);
+ TotalSize = ComputeSize(List, Start, End);
CurrentSize = 0;
- for (I = Start; I != End; ++I)
+ for (std::vector<pkgIndexFile *>::const_iterator I = Files.begin(); I != Files.end(); ++I)
{
- unsigned long Size = (*I)->Size();
+ map_filesize_t Size = (*I)->Size();
if (Progress != NULL)
Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides"));
CurrentSize += Size;
/*}}}*/
// 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);
+ map_filesize_t const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024);
+ map_filesize_t const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024);
+ map_filesize_t const MapLimit = _config->FindI("APT::Cache-Limit", 0);
Flags |= MMap::Moveable;
if (_config->FindB("APT::Cache-Fallback", false) == true)
Flags |= MMap::Fallback;
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. */
-__deprecated bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
+APT_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,
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
std::vector<pkgIndexFile *> Files;
+ /*
for (std::vector<metaIndex *>::const_iterator i = List.begin();
i != List.end();
++i)
++j)
Files.push_back (*j);
}
-
- unsigned long const EndOfSource = Files.size();
+*/
if (_system->AddStatusFiles(Files) == false)
return false;
}
// Lets try the source cache.
- unsigned long CurrentSize = 0;
- unsigned long TotalSize = 0;
- if (CheckValidity(SrcCacheFile, List, Files.begin(),
- Files.begin()+EndOfSource) == true)
+ map_filesize_t CurrentSize = 0;
+ map_filesize_t TotalSize = 0;
+ if (CheckValidity(SrcCacheFile, List, Files.end(),
+ Files.end()) == true)
{
if (Debug == true)
std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
// Preload the map with the source cache
FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly);
- unsigned long const alloc = Map->RawAllocate(SCacheF.Size());
+ map_pointer_t const alloc = Map->RawAllocate(SCacheF.Size());
if ((alloc == 0 && _error->PendingError())
|| SCacheF.Read((unsigned char *)Map->Data() + alloc,
SCacheF.Size()) == false)
return false;
- TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
+ TotalSize = ComputeSize(NULL, Files.begin(), Files.end());
// Build the status cache
pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
- if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
- Files.begin()+EndOfSource,Files.end()) == false)
+ if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL,
+ Files.begin(),Files.end()) == false)
return false;
}
else
{
if (Debug == true)
std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl;
- TotalSize = ComputeSize(Files.begin(),Files.end());
+ TotalSize = ComputeSize(&List, Files.begin(),Files.end());
// Build the source cache
pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
- if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
- Files.begin(),Files.begin()+EndOfSource) == false)
+ if (BuildCache(Gen, Progress, CurrentSize, TotalSize, &List,
+ Files.end(),Files.end()) == false)
return false;
// Write it back
}
// Build the status cache
- if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
- Files.begin()+EndOfSource,Files.end()) == false)
+ if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL,
+ Files.begin(), Files.end()) == false)
return false;
}
if (Debug == true)
// CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
// ---------------------------------------------------------------------
/* */
-__deprecated bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
+APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
{ return pkgCacheGenerator::MakeOnlyStatusCache(&Progress, OutMap); }
bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
{
std::vector<pkgIndexFile *> Files;
- unsigned long EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)
return false;
SPtr<DynamicMMap> Map = CreateDynamicMMap(NULL);
- unsigned long CurrentSize = 0;
- unsigned long TotalSize = 0;
+ map_filesize_t CurrentSize = 0;
+ map_filesize_t TotalSize = 0;
- TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end());
+ TotalSize = ComputeSize(NULL, Files.begin(), Files.end());
// Build the status cache
if (Progress != NULL)
pkgCacheGenerator Gen(Map.Get(),Progress);
if (_error->PendingError() == true)
return false;
- if (BuildCache(Gen,Progress,CurrentSize,TotalSize,
- Files.begin()+EndOfSource,Files.end()) == false)
+ if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL,
+ Files.begin(), Files.end()) == false)
return false;
if (_error->PendingError() == true)
}
/*}}}*/
// CacheGenerator::FinishCache /*{{{*/
-bool pkgCacheGenerator::FinishCache(OpProgress *Progress)
+bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/)
{
return true;
}