##################################################################### */
/*}}}*/
// Include Files /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-pkg/pkgcachegen.h"
-#endif
-
#define APT_COMPATIBILITY 986
#include <apt-pkg/pkgcachegen.h>
#include <apt-pkg/sptr.h>
#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/tagfile.h>
+
#include <apti18n.h>
#include <vector>
#include <system.h>
/*}}}*/
typedef vector<pkgIndexFile *>::iterator FileIterator;
+uint32_t hashlittle( const void *key, size_t length, uint32_t initval);
// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
// ---------------------------------------------------------------------
string Version = List.Version();
if (Version.empty() == true)
{
+ // 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)
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;
+
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
+ {
+ pkgCache::DescIterator Desc = Ver.DescriptionList();
+ 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++)
+ if (MD5SumValue(Desc.md5()) == CurMd5 &&
+ Desc.LanguageCode() == List.DescriptionLanguage())
+ duplicate=true;
+ if(duplicate)
+ continue;
+
+ for (Desc = Ver.DescriptionList();
+ Desc.end() == false;
+ LastDesc = &Desc->NextDesc, Desc++)
+ {
+ if (MD5SumValue(Desc.md5()) == CurMd5)
+ {
+ // Add new description
+ *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc);
+ Desc->ParentPkg = Pkg.Index();
+
+ if (NewFileDesc(Desc,List) == false)
+ return _error->Error(_("Error occurred while processing %s (NewFileDesc1)"),PackageName.c_str());
+ break;
+ }
+ }
+ }
+
continue;
}
pkgCache::VerIterator Ver = Pkg.VersionList();
- map_ptrloc *Last = &Pkg->VersionList;
+ map_ptrloc *LastVer = &Pkg->VersionList;
int Res = 1;
- for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
{
Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
if (Res >= 0)
// Skip to the end of the same version set.
if (Res == 0)
{
- for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
+ for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++)
{
Res = Cache.VS->CmpVersion(Version,Ver.VerStr());
if (Res != 0)
}
// Add a new version
- *Last = NewVersion(Ver,Version,*Last);
+ *LastVer = NewVersion(Ver,Version,*LastVer);
Ver->ParentPkg = Pkg.Index();
Ver->Hash = Hash;
+
if (List.NewVersion(Ver) == false)
return _error->Error(_("Error occurred while processing %s (NewVersion1)"),
PackageName.c_str());
FoundFileDeps |= List.HasFileDeps();
return true;
}
+
+ /* Record the Description data. Description data always exist in
+ Packages and Translation-* files. */
+ pkgCache::DescIterator Desc = Ver.DescriptionList();
+ 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);
+ Desc->ParentPkg = Pkg.Index();
+
+ if (NewFileDesc(Desc,List) == false)
+ return _error->Error(_("Error occurred while processing %s (NewFileDesc2)"),PackageName.c_str());
}
FoundFileDeps |= List.HasFileDeps();
if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1)
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)
+ 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)
return _error->Error(_("Wow, you exceeded the number of dependencies "
"this APT is capable of."));
Pkg = Cache.FindPkg(Name);
if (Pkg.end() == false)
return true;
-
+
// Get a structure
unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
if (Package == 0)
return Version;
}
/*}}}*/
+// CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc,
+ ListParser &List)
+{
+ if (CurrentFile == 0)
+ return true;
+
+ // Get a structure
+ unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile));
+ if (DescFile == 0)
+ return 0;
+
+ pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile);
+ DF->File = CurrentFile - Cache.PkgFileP;
+
+ // Link it to the end of the list
+ map_ptrloc *Last = &Desc->FileList;
+ for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++)
+ Last = &D->NextFile;
+
+ DF->NextFile = *Last;
+ *Last = DF.Index();
+
+ DF->Offset = List.Offset();
+ DF->Size = List.Size();
+ if (Cache.HeaderP->MaxDescFileSize < DF->Size)
+ Cache.HeaderP->MaxDescFileSize = DF->Size;
+ Cache.HeaderP->DescFileCount++;
+
+ return true;
+}
+ /*}}}*/
+// CacheGenerator::NewDescription - Create a new Description /*{{{*/
+// ---------------------------------------------------------------------
+/* This puts a description structure in the linked list */
+map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc,
+ const string &Lang,
+ const MD5SumValue &md5sum,
+ map_ptrloc Next)
+{
+ // Get a structure
+ map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description));
+ if (Description == 0)
+ return 0;
+
+ // Fill it in
+ 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());
+
+ return Description;
+}
+ /*}}}*/
// ListParser::NewDepends - Create a dependency element /*{{{*/
// ---------------------------------------------------------------------
/* This creates a dependency element in the tree. It is linked to the
Prv->NextProvides = Pkg->ProvidesList;
Pkg->ProvidesList = Prv.Index();
+ return true;
+}
+ /*}}}*/
+// ListParser::NewTag - Create a Tag element /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool pkgCacheGenerator::ListParser::NewTag(pkgCache::PkgIterator Pkg,
+ const char *NameStart,
+ unsigned int NameSize)
+{
+ pkgCache &Cache = Owner->Cache;
+
+ // Get a structure
+ unsigned long Tagg = Owner->Map.Allocate(sizeof(pkgCache::Tag));
+ if (Tagg == 0)
+ return false;
+ Cache.HeaderP->TagCount++;
+
+ // Fill it in
+ pkgCache::TagIterator Tg(Cache,Cache.TagP + Tagg);
+ Tg->Name = WriteString(NameStart,NameSize);
+ if (Tg->Name == 0)
+ return false;
+ Tg->NextTag = Pkg->TagList;
+ Pkg->TagList = Tg.Index();
+
return true;
}
/*}}}*/
unsigned long pkgCacheGenerator::WriteUniqString(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;
+ uint32_t hash = hashlittle(S, Size, 0xdeadbeef);
+
+ /* We use a VERY LARGE INTRANSIENT hash table here, this speeds up generation
+ by AN INSANE amount on ALL machines */
+ pkgCache::StringItem **Bucket2;
+ while (true) {
+ Bucket2 = &UniqHash[hash % _count(UniqHash)];
+ if (*Bucket2 == NULL)
+ break;
+ if (stringcmp(S,S+Size,Cache.StrP + (*Bucket2)->String) == 0)
+ return (*Bucket2)->String;
+ hash += 7;
}
- // Match
- if (Res == 0)
- {
- Bucket = I;
- return I->String;
- }
+ pkgCache::StringItem *&Bucket = *Bucket2;
+ pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
+ map_ptrloc *Last = &Cache.HeaderP->StringList;
// Get a structure
unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
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
continue;
}
pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache);
if (File.end() == true)
return false;
-
+
Visited[File->ID] = true;
}
bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress,
MMap **OutMap,bool AllowMem)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024);
+ unsigned long MapSize = _config->FindI("APT::Cache-Limit",24*1024*1024);
vector<pkgIndexFile *> Files;
for (vector<metaIndex *>::const_iterator i = List.begin();
/* */
bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap)
{
- unsigned long MapSize = _config->FindI("APT::Cache-Limit",8*1024*1024);
+ unsigned long MapSize = _config->FindI("APT::Cache-Limit",20*1024*1024);
vector<pkgIndexFile *> Files;
unsigned long EndOfSource = Files.size();
if (_system->AddStatusFiles(Files) == false)