/* 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;
*Cache.HeaderP = pkgCache::Header();
// make room for the hashtables for packages and groups
- if (Map.RawAllocate(2 * (Cache.HeaderP->HashTableSize * sizeof(map_pointer_t))) == 0)
+ 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_stringitem_t const idxArchitecture = WriteUniqString(_config->Find("APT::Architecture"));
+ map_stringitem_t const idxArchitecture = StoreString(MIXED, _config->Find("APT::Architecture"));
if (unlikely(idxArchitecture == 0))
return;
Cache.HeaderP->Architecture = idxArchitecture;
map_stringitem_t const idxArchitectures = WriteStringInMap(list);
if (unlikely(idxArchitectures == 0))
return;
- Cache.HeaderP->Architectures = idxArchitectures;
+ Cache.HeaderP->SetArchitectures(idxArchitectures);
}
else
- Cache.HeaderP->Architectures = idxArchitecture;
+ Cache.HeaderP->SetArchitectures(idxArchitecture);
Cache.ReMap();
}
Cache.ReMap(false);
CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap;
-
- for (size_t i = 0; i < _count(UniqHash); ++i)
- if (UniqHash[i] != 0)
- UniqHash[i] += (pkgCache::StringItem const * const) newMap - (pkgCache::StringItem 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_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String,
/* 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
return false;
Grp = pkgCache::GrpIterator(Cache, Cache.GrpP + Group);
- map_pointer_t 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_pointer_t *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;
Grp->FirstPackage = Package;
// Insert it into the hash table
map_id_t const Hash = Cache.Hash(Name);
- map_pointer_t *insertAt = &Cache.HeaderP->PkgHashTable()[Hash];
- while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0)
- insertAt = &(Cache.PkgP + *insertAt)->Next;
- Pkg->Next = *insertAt;
+ 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;
}
else // Group the Packages together
{
// this package is the new last package
pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage);
- Pkg->Next = LastPkg->Next;
- LastPkg->Next = Package;
+ Pkg->NextPackage = LastPkg->NextPackage;
+ LastPkg->NextPackage = 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_stringitem_t 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;
}
}
// haven't found the version string, so create
- map_stringitem_t const idxVerStr = WriteStringInMap(VerStr);
+ map_stringitem_t const idxVerStr = StoreString(VERSIONNUMBER, VerStr);
if (unlikely(idxVerStr == 0))
return 0;
Ver->VerStr = idxVerStr;
// Fill it in
Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description);
Desc->ID = Cache.HeaderP->DescriptionCount++;
- map_stringitem_t 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;
if (index == 0)
{
void const * const oldMap = Map.Data();
- index = WriteStringInMap(Version);
+ index = StoreString(VERSIONNUMBER, Version);
if (unlikely(index == 0))
return false;
if (OldDepLast != 0 && oldMap != Map.Data())
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;
+}
+ /*}}}*/
// CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
// ---------------------------------------------------------------------
/* 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 &Architecture,
+ std::string const &Component,
+ unsigned long const Flags)
{
// Get some space for the structure
map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile));
// Fill it in
map_stringitem_t const idxFileName = WriteStringInMap(File);
- map_stringitem_t const idxSite = WriteUniqString(Site);
- if (unlikely(idxFileName == 0 || idxSite == 0))
+ 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_stringitem_t 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;
+ if (Architecture.empty())
+ CurrentFile->Architecture = 0;
+ else
+ {
+ map_stringitem_t const arch = StoreString(pkgCacheGenerator::MIXED, Architecture);
+ if (unlikely(arch == 0))
+ return false;
+ CurrentFile->Architecture = arch;
+ }
+ 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 */
-map_stringitem_t 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_stringitem_t *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_pointer_t const Item = AllocateInMap(sizeof(pkgCache::StringItem));
- if (Item == 0)
- return 0;
-
- map_stringitem_t const idxString = WriteStringInMap(S,Size);
- if (unlikely(idxString == 0))
- return 0;
- if (oldMap != Map.Data()) {
- Last += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap;
- I += (pkgCache::StringItem const * const) Map.Data() - (pkgCache::StringItem const * const) 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 map_filesize_t ComputeSize(FileIterator Start,FileIterator End)
+static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator Start,FileIterator End)
{
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)
static bool BuildCache(pkgCacheGenerator &Gen,
OpProgress *Progress,
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;
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)
{
map_filesize_t Size = (*I)->Size();
if (Progress != NULL)
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);
}
-
- map_filesize_t const EndOfSource = Files.size();
+*/
if (_system->AddStatusFiles(Files) == false)
return false;
// Lets try the source cache.
map_filesize_t CurrentSize = 0;
map_filesize_t TotalSize = 0;
- if (CheckValidity(SrcCacheFile, List, Files.begin(),
- Files.begin()+EndOfSource) == true)
+ if (CheckValidity(SrcCacheFile, List, Files.end(),
+ Files.end()) == true)
{
if (Debug == true)
std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl;
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)
bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap)
{
std::vector<pkgIndexFile *> Files;
- map_filesize_t EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)
return false;
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)