MD5SumValue const &CurMd5, std::string const &CurLang);
using std::string;
+using APT::StringView;
// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
// ---------------------------------------------------------------------
else
Cache.HeaderP->SetArchitectures(idxArchitecture);
+ // Calculate the hash for the empty map, so ReMap does not fail
+ Cache.HeaderP->CacheFileSize = Cache.CacheHash();
Cache.ReMap();
}
else
return;
Cache.HeaderP->Dirty = false;
- Cache.HeaderP->CacheFileSize = Map.Size();
+ Cache.HeaderP->CacheFileSize = Cache.CacheHash();
+
+ if (_config->FindB("Debug::pkgCacheGen", false))
+ std::clog << "Produced cache with hash " << Cache.HeaderP->CacheFileSize << std::endl;
Map.Sync(0,sizeof(pkgCache::Header));
}
/*}}}*/
-void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap) {/*{{{*/
+void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newMap, size_t oldSize) {/*{{{*/
if (oldMap == newMap)
return;
for (std::vector<pkgCache::RlsFileIterator*>::const_iterator i = Dynamic<pkgCache::RlsFileIterator>::toReMap.begin();
i != Dynamic<pkgCache::RlsFileIterator>::toReMap.end(); ++i)
(*i)->ReMap(oldMap, newMap);
+ for (APT::StringView* ViewP : Dynamic<APT::StringView>::toReMap) {
+ // Ignore views outside of the cache.
+ if (ViewP->data() < static_cast<const char*>(oldMap)
+ || ViewP->data() > static_cast<const char*>(oldMap) + oldSize)
+ continue;
+ const char *data = ViewP->data() + (static_cast<const char*>(newMap) - static_cast<const char*>(oldMap));
+ *ViewP = StringView(data , ViewP->size());
+ }
} /*}}}*/
// CacheGenerator::WriteStringInMap /*{{{*/
map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String,
const unsigned long &Len) {
+ size_t oldSize = Map.Size();
void const * const oldMap = Map.Data();
map_stringitem_t const index = Map.WriteString(String, Len);
if (index != 0)
- ReMap(oldMap, Map.Data());
+ ReMap(oldMap, Map.Data(), oldSize);
return index;
}
/*}}}*/
// CacheGenerator::WriteStringInMap /*{{{*/
map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String) {
+ size_t oldSize = Map.Size();
void const * const oldMap = Map.Data();
map_stringitem_t const index = Map.WriteString(String);
if (index != 0)
- ReMap(oldMap, Map.Data());
+ ReMap(oldMap, Map.Data(), oldSize);
return index;
}
/*}}}*/
map_pointer_t pkgCacheGenerator::AllocateInMap(const unsigned long &size) {/*{{{*/
+ size_t oldSize = Map.Size();
void const * const oldMap = Map.Data();
map_pointer_t const index = Map.Allocate(size);
if (index != 0)
- ReMap(oldMap, Map.Data());
+ ReMap(oldMap, Map.Data(), oldSize);
return index;
}
/*}}}*/
// Find the right version to write the description
MD5SumValue CurMd5 = List.Description_md5();
- 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)
{
/* Record the Description(s) based on their master md5sum */
MD5SumValue CurMd5 = List.Description_md5();
- if (CurMd5.Value().empty() == true && List.Description("").empty() == true)
- return true;
/* 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
// CacheGenerator::NewGroup - Add a new group /*{{{*/
// ---------------------------------------------------------------------
/* This creates a new group structure and adds it to the hash table */
-bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, const string &Name)
+bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator &Grp, StringView Name)
{
+ Dynamic<StringView> DName(Name);
Grp = Cache.FindGrp(Name);
if (Grp.end() == false)
return true;
// Insert it into the hash table
unsigned long const Hash = Cache.Hash(Name);
map_pointer_t *insertAt = &Cache.HeaderP->GrpHashTableP()[Hash];
- while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.GrpP + *insertAt)->Name) > 0)
+
+ while (*insertAt != 0 && Name.compare(Cache.ViewString((Cache.GrpP + *insertAt)->Name)) > 0)
insertAt = &(Cache.GrpP + *insertAt)->Next;
Grp->Next = *insertAt;
*insertAt = Group;
// CacheGenerator::NewPackage - Add a new package /*{{{*/
// ---------------------------------------------------------------------
/* This creates a new package structure and adds it to the hash table */
-bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name,
- const string &Arch) {
+bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg, StringView Name,
+ StringView Arch) {
pkgCache::GrpIterator Grp;
+ Dynamic<StringView> DName(Name);
+ Dynamic<StringView> DArch(Arch);
Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
if (unlikely(NewGroup(Grp, Name) == false))
return false;
// Insert it into the hash table
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)
+ while (*insertAt != 0 && Name.compare(Cache.StrP + (Cache.GrpP + (Cache.PkgP + *insertAt)->Group)->Name) > 0)
insertAt = &(Cache.PkgP + *insertAt)->NextPackage;
Pkg->NextPackage = *insertAt;
*insertAt = Package;
}
else // Group the Packages together
{
- // but first get implicit provides done
- if (APT::Configuration::checkArchitecture(Pkg.Arch()) == true)
+ // if sibling is provided by another package, this one is too
{
pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); // native or any foreign pkg will do
if (M.end() == false) {
if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed ||
((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign &&
(Prv->Flags & pkgCache::Flag::MultiArchImplicit) == 0))
+ {
+ if (APT::Configuration::checkArchitecture(Ver.ParentPkg().Arch()) == false)
+ continue;
if (NewProvides(Ver, Pkg, Prv->ProvideVersion, Prv->Flags) == false)
return false;
+ }
}
}
-
-
+ }
+ // let M-A:foreign package siblings provide this package
+ {
pkgCache::PkgIterator P;
pkgCache::VerIterator Ver;
Dynamic<pkgCache::PkgIterator> DynP(P);
Dynamic<pkgCache::VerIterator> DynVer(Ver);
for (P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P))
+ {
+ if (APT::Configuration::checkArchitecture(P.Arch()) == false)
+ continue;
for (Ver = P.VersionList(); Ver.end() == false; ++Ver)
if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false)
return false;
+ }
}
// and negative dependencies, don't forget negative dependencies
{
if (Arch == "any")
{
size_t const found = Name.find(':');
- std::string const NameA = Name.substr(0, found);
- std::string const ArchA = Name.substr(found + 1);
- pkgCache::PkgIterator PkgA = Cache.FindPkg(NameA, ArchA);
- if (PkgA.end() == false)
+ StringView ArchA = Name.substr(found + 1);
+ if (ArchA != "any")
{
+ // ArchA is used inside the loop which might remap (NameA is not used)
+ Dynamic<StringView> DynArchA(ArchA);
+ StringView NameA = Name.substr(0, found);
+ pkgCache::PkgIterator PkgA = Cache.FindPkg(NameA, ArchA);
Dynamic<pkgCache::PkgIterator> DynPkgA(PkgA);
- pkgCache::PrvIterator Prv = PkgA.ProvidesList();
- for (; Prv.end() == false; ++Prv)
+ if (PkgA.end())
{
- if (Prv.IsMultiArchImplicit())
- continue;
- pkgCache::VerIterator V = Prv.OwnerVer();
- if (ArchA != V.ParentPkg().Arch())
- continue;
- if (NewProvides(V, Pkg, V->VerStr, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ Dynamic<StringView> DynNameA(NameA);
+ if (NewPackage(PkgA, NameA, ArchA) == false)
return false;
}
- pkgCache::VerIterator V = PkgA.VersionList();
- Dynamic<pkgCache::VerIterator> DynV(V);
- for (; V.end() == false; ++V)
+ if (unlikely(PkgA.end()))
+ return _error->Fatal("NewPackage was successful for %s:%s,"
+ "but the package doesn't exist anyhow!",
+ NameA.to_string().c_str(), ArchA.to_string().c_str());
+ else
{
- if (NewProvides(V, Pkg, V->VerStr, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
- return false;
+ pkgCache::PrvIterator Prv = PkgA.ProvidesList();
+ for (; Prv.end() == false; ++Prv)
+ {
+ if (Prv.IsMultiArchImplicit())
+ continue;
+ pkgCache::VerIterator V = Prv.OwnerVer();
+ if (ArchA != V.ParentPkg().Arch())
+ continue;
+ if (NewProvides(V, Pkg, V->VerStr, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ return false;
+ }
+ pkgCache::VerIterator V = PkgA.VersionList();
+ Dynamic<pkgCache::VerIterator> DynV(V);
+ for (; V.end() == false; ++V)
+ {
+ if (NewProvides(V, Pkg, V->VerStr, pkgCache::Flag::MultiArchImplicit | pkgCache::Flag::ArchSpecific) == false)
+ return false;
+ }
}
}
}
/* This creates a Group and the Package to link this dependency to if
needed and handles also the caching of the old endpoint */
bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver,
- const string &PackageName,
- const string &Arch,
- const string &Version,
+ StringView PackageName,
+ StringView Arch,
+ StringView Version,
uint8_t const Op,
uint8_t const Type)
{
pkgCache::GrpIterator Grp;
Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
+ Dynamic<StringView> DynPackageName(PackageName);
+ Dynamic<StringView> DynArch(Arch);
+ Dynamic<StringView> DynVersion(Version);
if (unlikely(Owner->NewGroup(Grp, PackageName) == false))
return false;
{
int const CmpOp = Op & 0x0F;
// =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages)
- if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0)
+ if (CmpOp == pkgCache::Dep::Equals && Version == Ver.VerStr())
idxVersion = Ver->VerStr;
if (idxVersion == 0)
/*}}}*/
// ListParser::NewProvides - Create a Provides element /*{{{*/
bool pkgCacheListParser::NewProvides(pkgCache::VerIterator &Ver,
- const string &PkgName,
- const string &PkgArch,
- const string &Version,
+ StringView PkgName,
+ StringView PkgArch,
+ StringView Version,
uint8_t const Flags)
{
pkgCache const &Cache = Owner->Cache;
+ Dynamic<StringView> DynPkgName(PkgName);
+ Dynamic<StringView> DynArch(PkgArch);
+ Dynamic<StringView> DynVersion(Version);
// We do not add self referencing provides
if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() ||
}
/*}}}*/
// ListParser::NewProvidesAllArch - add provides for all architectures /*{{{*/
-bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package,
- string const &Version, uint8_t const Flags) {
+bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, StringView Package,
+ StringView Version, uint8_t const Flags) {
pkgCache &Cache = Owner->Cache;
pkgCache::GrpIterator Grp = Cache.FindGrp(Package);
Dynamic<pkgCache::GrpIterator> DynGrp(Grp);
+ Dynamic<StringView> DynPackage(Package);
+ Dynamic<StringView> DynVersion(Version);
if (Grp.end() == true)
return NewProvides(Ver, Package, Cache.NativeArch(), Version, Flags);
map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, const char *S,
unsigned int Size)
{
- std::string const key(S, Size);
-
- std::map<std::string,map_stringitem_t> * strings;
+ auto strings = &strMixed;
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;
+ default: _error->Fatal("Unknown enum type used for string storage of '%.*s'", Size, S); return 0;
}
- std::map<std::string,map_stringitem_t>::const_iterator const item = strings->find(key);
+ auto const item = strings->find({S, Size, nullptr, 0});
if (item != strings->end())
- return item->second;
+ return item->item;
map_stringitem_t const idxString = WriteStringInMap(S,Size);
- strings->insert(std::make_pair(key, idxString));
+ strings->insert({nullptr, Size, this, idxString});
return idxString;
}
/*}}}*/
pkgSourceList &List,
FileIterator const Start,
FileIterator const End,
- MMap **OutMap = 0)
+ MMap **OutMap = 0,
+ pkgCache **OutCache = 0)
{
ScopedErrorRevert ser;
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
std::unique_ptr<MMap> Map(new MMap(CacheF,0));
if (unlikely(Map->validData()) == false)
return false;
- pkgCache Cache(Map.get());
+ std::unique_ptr<pkgCache> CacheP(new pkgCache(Map.get()));
+ pkgCache &Cache = *CacheP.get();
if (_error->PendingError() || Map->Size() == 0)
{
if (Debug == true)
if (OutMap != 0)
*OutMap = Map.release();
+ if (OutCache != 0)
+ *OutCache = CacheP.release();
return true;
}
/*}}}*/
// Write out the main data
if (SCacheF.Write(Map->Data(),Map->Size()) == false)
return _error->Error(_("IO Error saving source cache"));
- SCacheF.Sync();
// Write out the proper header
Gen->GetCache().HeaderP->Dirty = false;
+ Gen->GetCache().HeaderP->CacheFileSize = Gen->GetCache().CacheHash();
if (SCacheF.Seek(0) == false ||
SCacheF.Write(Map->Data(),sizeof(*Gen->GetCache().HeaderP)) == false)
return _error->Error(_("IO Error saving source cache"));
Gen->GetCache().HeaderP->Dirty = true;
- SCacheF.Sync();
return true;
}
static bool loadBackMMapFromFile(std::unique_ptr<pkgCacheGenerator> &Gen,
{ return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); }
bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
MMap **OutMap,bool)
+{
+ return pkgCacheGenerator::MakeStatusCache(List, Progress, OutMap, nullptr, true);
+}
+bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress,
+ MMap **OutMap,pkgCache **OutCache, bool)
{
// FIXME: deprecate the ignored AllowMem parameter
bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
bool srcpkgcache_fine = false;
bool volatile_fine = List.GetVolatileFiles().empty();
- if (CheckValidity(CacheFile, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL) == true)
+ if (CheckValidity(CacheFile, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL,
+ volatile_fine ? OutCache : NULL) == true)
{
if (Debug == true)
std::clog << "pkgcache.bin is valid - no need to build any cache" << std::endl;