]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
15 #include <apt-pkg/pkgcachegen.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/version.h>
18 #include <apt-pkg/progress.h>
19 #include <apt-pkg/sourcelist.h>
20 #include <apt-pkg/configuration.h>
21 #include <apt-pkg/aptconfiguration.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/sptr.h>
24 #include <apt-pkg/pkgsystem.h>
25 #include <apt-pkg/macros.h>
26 #include <apt-pkg/tagfile.h>
27 #include <apt-pkg/metaindex.h>
28 #include <apt-pkg/fileutl.h>
38 typedef vector
<pkgIndexFile
*>::iterator FileIterator
;
39 template <typename Iter
> std::vector
<Iter
*> pkgCacheGenerator::Dynamic
<Iter
>::toReMap
;
41 bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
42 MD5SumValue
const &CurMd5
, std::string
const &CurLang
);
44 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
45 // ---------------------------------------------------------------------
46 /* We set the dirty flag and make sure that is written to the disk */
47 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
48 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
52 memset(UniqHash
,0,sizeof(UniqHash
));
54 if (_error
->PendingError() == true)
59 // Setup the map interface..
60 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
61 if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true)
64 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
67 *Cache
.HeaderP
= pkgCache::Header();
68 map_ptrloc
const idxVerSysName
= WriteStringInMap(_system
->VS
->Label
);
69 Cache
.HeaderP
->VerSysName
= idxVerSysName
;
70 map_ptrloc
const idxArchitecture
= WriteStringInMap(_config
->Find("APT::Architecture"));
71 Cache
.HeaderP
->Architecture
= idxArchitecture
;
72 if (unlikely(idxVerSysName
== 0 || idxArchitecture
== 0))
78 // Map directly from the existing file
80 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
81 if (Cache
.VS
!= _system
->VS
)
83 _error
->Error(_("Cache has an incompatible versioning system"));
88 Cache
.HeaderP
->Dirty
= true;
89 Map
.Sync(0,sizeof(pkgCache::Header
));
92 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
93 // ---------------------------------------------------------------------
94 /* We sync the data then unset the dirty flag in two steps so as to
95 advoid a problem during a crash */
96 pkgCacheGenerator::~pkgCacheGenerator()
98 if (_error
->PendingError() == true)
100 if (Map
.Sync() == false)
103 Cache
.HeaderP
->Dirty
= false;
104 Cache
.HeaderP
->CacheFileSize
= Map
.Size();
105 Map
.Sync(0,sizeof(pkgCache::Header
));
108 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
109 if (oldMap
== newMap
)
112 if (_config
->FindB("Debug::pkgCacheGen", false))
113 std::clog
<< "Remaping from " << oldMap
<< " to " << newMap
<< std::endl
;
117 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
119 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
120 if (UniqHash
[i
] != 0)
121 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
123 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
124 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
125 (*i
)->ReMap(oldMap
, newMap
);
126 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
127 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
128 (*i
)->ReMap(oldMap
, newMap
);
129 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
130 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
131 (*i
)->ReMap(oldMap
, newMap
);
132 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
133 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
134 (*i
)->ReMap(oldMap
, newMap
);
135 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
136 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
137 (*i
)->ReMap(oldMap
, newMap
);
138 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
139 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
140 (*i
)->ReMap(oldMap
, newMap
);
141 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
142 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
143 (*i
)->ReMap(oldMap
, newMap
);
145 // CacheGenerator::WriteStringInMap /*{{{*/
146 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
147 const unsigned long &Len
) {
148 void const * const oldMap
= Map
.Data();
149 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
151 ReMap(oldMap
, Map
.Data());
155 // CacheGenerator::WriteStringInMap /*{{{*/
156 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
157 void const * const oldMap
= Map
.Data();
158 map_ptrloc
const index
= Map
.WriteString(String
);
160 ReMap(oldMap
, Map
.Data());
164 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
165 void const * const oldMap
= Map
.Data();
166 map_ptrloc
const index
= Map
.Allocate(size
);
168 ReMap(oldMap
, Map
.Data());
172 // CacheGenerator::MergeList - Merge the package list /*{{{*/
173 // ---------------------------------------------------------------------
174 /* This provides the generation of the entries in the cache. Each loop
175 goes through a single package record from the underlying parse engine. */
176 bool pkgCacheGenerator::MergeList(ListParser
&List
,
177 pkgCache::VerIterator
*OutVer
)
181 unsigned int Counter
= 0;
182 while (List
.Step() == true)
184 string
const PackageName
= List
.Package();
185 if (PackageName
.empty() == true)
189 if (Counter
% 100 == 0 && Progress
!= 0)
190 Progress
->Progress(List
.Offset());
192 string Arch
= List
.Architecture();
193 string
const Version
= List
.Version();
194 if (Version
.empty() == true && Arch
.empty() == true)
196 if (MergeListGroup(List
, PackageName
) == false)
200 if (Arch
.empty() == true)
201 Arch
= _config
->Find("APT::Architecture");
203 // Get a pointer to the package structure
204 pkgCache::PkgIterator Pkg
;
205 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
206 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
207 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
210 if (Version
.empty() == true)
212 if (MergeListPackage(List
, Pkg
) == false)
217 if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false)
223 FoundFileDeps
|= List
.HasFileDeps();
228 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
229 return _error
->Error(_("Wow, you exceeded the number of package "
230 "names this APT is capable of."));
231 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
232 return _error
->Error(_("Wow, you exceeded the number of versions "
233 "this APT is capable of."));
234 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
235 return _error
->Error(_("Wow, you exceeded the number of descriptions "
236 "this APT is capable of."));
237 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
238 return _error
->Error(_("Wow, you exceeded the number of dependencies "
239 "this APT is capable of."));
241 FoundFileDeps
|= List
.HasFileDeps();
244 // CacheGenerator::MergeListGroup /*{{{*/
245 bool pkgCacheGenerator::MergeListGroup(ListParser
&List
, std::string
const &GrpName
)
247 pkgCache::GrpIterator Grp
= Cache
.FindGrp(GrpName
);
248 // a group has no data on it's own, only packages have it but these
249 // stanzas like this come from Translation- files to add descriptions,
250 // but without a version we don't need a description for it…
251 if (Grp
.end() == true)
253 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
255 pkgCache::PkgIterator Pkg
;
256 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
257 for (Pkg
= Grp
.PackageList(); Pkg
.end() == false; Pkg
= Grp
.NextPkg(Pkg
))
258 if (MergeListPackage(List
, Pkg
) == false)
264 // CacheGenerator::MergeListPackage /*{{{*/
265 bool pkgCacheGenerator::MergeListPackage(ListParser
&List
, pkgCache::PkgIterator
&Pkg
)
267 // we first process the package, then the descriptions
268 // (for deb this package processing is in fact a no-op)
269 pkgCache::VerIterator
Ver(Cache
);
270 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
271 if (List
.UsePackage(Pkg
, Ver
) == false)
272 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
275 // Find the right version to write the description
276 MD5SumValue CurMd5
= List
.Description_md5();
277 std::string CurLang
= List
.DescriptionLanguage();
279 for (Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
281 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
283 // a version can only have one md5 describing it
284 if (MD5SumValue(Desc
.md5()) != CurMd5
)
287 // don't add a new description if we have one for the given
289 if (IsDuplicateDescription(Desc
, CurMd5
, CurLang
) == true)
292 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
293 // we add at the end, so that the start is constant as we need
294 // that to be able to efficiently share these lists
295 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
296 for (;Desc
.end() == false && Desc
->NextDesc
!= 0; ++Desc
);
297 if (Desc
.end() == false)
298 LastDesc
= &Desc
->NextDesc
;
300 void const * const oldMap
= Map
.Data();
301 map_ptrloc
const descindex
= NewDescription(Desc
, CurLang
, CurMd5
, *LastDesc
);
302 if (oldMap
!= Map
.Data())
303 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
304 *LastDesc
= descindex
;
305 Desc
->ParentPkg
= Pkg
.Index();
307 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
308 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"), Pkg
.Name());
310 // we can stop here as all "same" versions will share the description
317 // CacheGenerator::MergeListVersion /*{{{*/
318 bool pkgCacheGenerator::MergeListVersion(ListParser
&List
, pkgCache::PkgIterator
&Pkg
,
319 std::string
const &Version
, pkgCache::VerIterator
* &OutVer
)
321 pkgCache::VerIterator Ver
= Pkg
.VersionList();
322 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
323 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
324 void const * oldMap
= Map
.Data();
326 unsigned long const Hash
= List
.VersionHash();
327 if (Ver
.end() == false)
329 /* We know the list is sorted so we use that fact in the search.
330 Insertion of new versions is done with correct sorting */
332 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
334 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
335 // Version is higher as current version - insert here
338 // Versionstrings are equal - is hash also equal?
339 if (Res
== 0 && Ver
->Hash
== Hash
)
341 // proceed with the next till we have either the right
342 // or we found another version (which will be lower)
345 /* We already have a version for this item, record that we saw it */
346 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
348 if (List
.UsePackage(Pkg
,Ver
) == false)
349 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
352 if (NewFileVer(Ver
,List
) == false)
353 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
356 // Read only a single record and return
368 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
369 if (verindex
== 0 && _error
->PendingError())
370 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
373 if (oldMap
!= Map
.Data())
374 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
376 Ver
->ParentPkg
= Pkg
.Index();
379 if (List
.NewVersion(Ver
) == false)
380 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
383 if (List
.UsePackage(Pkg
,Ver
) == false)
384 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
387 if (NewFileVer(Ver
,List
) == false)
388 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
391 // Read only a single record and return
398 /* Record the Description (it is not translated) */
399 MD5SumValue CurMd5
= List
.Description_md5();
400 if (CurMd5
.Value().empty() == true)
402 std::string CurLang
= List
.DescriptionLanguage();
404 /* Before we add a new description we first search in the group for
405 a version with a description of the same MD5 - if so we reuse this
406 description group instead of creating our own for this version */
407 pkgCache::GrpIterator Grp
= Pkg
.Group();
408 for (pkgCache::PkgIterator P
= Grp
.PackageList();
409 P
.end() == false; P
= Grp
.NextPkg(P
))
411 for (pkgCache::VerIterator V
= P
.VersionList();
412 V
.end() == false; ++V
)
414 if (IsDuplicateDescription(V
.DescriptionList(), CurMd5
, "") == false)
416 Ver
->DescriptionList
= V
->DescriptionList
;
421 // We haven't found reusable descriptions, so add the first description
422 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
423 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
424 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
427 map_ptrloc
const descindex
= NewDescription(Desc
, CurLang
, CurMd5
, *LastDesc
);
428 if (oldMap
!= Map
.Data())
429 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
430 *LastDesc
= descindex
;
431 Desc
->ParentPkg
= Pkg
.Index();
433 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
434 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),Pkg
.Name());
440 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
441 // ---------------------------------------------------------------------
442 /* If we found any file depends while parsing the main list we need to
443 resolve them. Since it is undesired to load the entire list of files
444 into the cache as virtual packages we do a two stage effort. MergeList
445 identifies the file depends and this creates Provdies for them by
446 re-parsing all the indexs. */
447 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
451 unsigned int Counter
= 0;
452 while (List
.Step() == true)
454 string PackageName
= List
.Package();
455 if (PackageName
.empty() == true)
457 string Version
= List
.Version();
458 if (Version
.empty() == true)
461 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
462 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
463 if (Pkg
.end() == true)
464 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
465 PackageName
.c_str());
467 if (Counter
% 100 == 0 && Progress
!= 0)
468 Progress
->Progress(List
.Offset());
470 unsigned long Hash
= List
.VersionHash();
471 pkgCache::VerIterator Ver
= Pkg
.VersionList();
472 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
473 for (; Ver
.end() == false; ++Ver
)
475 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
477 if (List
.CollectFileProvides(Cache
,Ver
) == false)
478 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
483 if (Ver
.end() == true)
484 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
490 // CacheGenerator::NewGroup - Add a new group /*{{{*/
491 // ---------------------------------------------------------------------
492 /* This creates a new group structure and adds it to the hash table */
493 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
495 Grp
= Cache
.FindGrp(Name
);
496 if (Grp
.end() == false)
500 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
501 if (unlikely(Group
== 0))
504 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
505 map_ptrloc
const idxName
= WriteStringInMap(Name
);
506 if (unlikely(idxName
== 0))
510 // Insert it into the hash table
511 unsigned long const Hash
= Cache
.Hash(Name
);
512 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
513 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
515 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
519 // CacheGenerator::NewPackage - Add a new package /*{{{*/
520 // ---------------------------------------------------------------------
521 /* This creates a new package structure and adds it to the hash table */
522 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
523 const string
&Arch
) {
524 pkgCache::GrpIterator Grp
;
525 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
526 if (unlikely(NewGroup(Grp
, Name
) == false))
529 Pkg
= Grp
.FindPkg(Arch
);
530 if (Pkg
.end() == false)
534 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
535 if (unlikely(Package
== 0))
537 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
539 // Insert the package into our package list
540 if (Grp
->FirstPackage
== 0) // the group is new
542 // Insert it into the hash table
543 unsigned long const Hash
= Cache
.Hash(Name
);
544 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
545 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
546 Grp
->FirstPackage
= Package
;
548 else // Group the Packages together
550 // this package is the new last package
551 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
552 Pkg
->NextPackage
= LastPkg
->NextPackage
;
553 LastPkg
->NextPackage
= Package
;
555 Grp
->LastPackage
= Package
;
557 // Set the name, arch and the ID
558 Pkg
->Name
= Grp
->Name
;
559 Pkg
->Group
= Grp
.Index();
560 // all is mapped to the native architecture
561 map_ptrloc
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: WriteUniqString(Arch
.c_str());
562 if (unlikely(idxArch
== 0))
565 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
570 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
571 // ---------------------------------------------------------------------
573 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
576 if (CurrentFile
== 0)
580 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
584 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
585 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
587 // Link it to the end of the list
588 map_ptrloc
*Last
= &Ver
->FileList
;
589 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; ++V
)
591 VF
->NextFile
= *Last
;
594 VF
->Offset
= List
.Offset();
595 VF
->Size
= List
.Size();
596 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
597 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
598 Cache
.HeaderP
->VerFileCount
++;
603 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
604 // ---------------------------------------------------------------------
605 /* This puts a version structure in the linked list */
606 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
607 const string
&VerStr
,
611 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
616 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
618 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
619 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
620 if (unlikely(idxVerStr
== 0))
622 Ver
->VerStr
= idxVerStr
;
627 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
628 // ---------------------------------------------------------------------
630 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
633 if (CurrentFile
== 0)
637 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
641 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
642 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
644 // Link it to the end of the list
645 map_ptrloc
*Last
= &Desc
->FileList
;
646 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; ++D
)
649 DF
->NextFile
= *Last
;
652 DF
->Offset
= List
.Offset();
653 DF
->Size
= List
.Size();
654 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
655 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
656 Cache
.HeaderP
->DescFileCount
++;
661 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
662 // ---------------------------------------------------------------------
663 /* This puts a description structure in the linked list */
664 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
666 const MD5SumValue
&md5sum
,
670 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
671 if (Description
== 0)
675 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
676 Desc
->NextDesc
= Next
;
677 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
678 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
679 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
680 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
682 Desc
->language_code
= idxlanguage_code
;
683 Desc
->md5sum
= idxmd5sum
;
688 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
689 // ---------------------------------------------------------------------
690 /* This prepares the Cache for delivery */
691 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
693 // FIXME: add progress reporting for this operation
694 // Do we have different architectures in your groups ?
695 vector
<string
> archs
= APT::Configuration::getArchitectures();
696 if (archs
.size() > 1)
698 // Create Conflicts in between the group
699 pkgCache::GrpIterator G
= GetCache().GrpBegin();
700 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
701 for (; G
.end() != true; ++G
)
703 string
const PkgName
= G
.Name();
704 pkgCache::PkgIterator P
= G
.PackageList();
705 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
706 for (; P
.end() != true; P
= G
.NextPkg(P
))
708 pkgCache::PkgIterator allPkg
;
709 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
710 pkgCache::VerIterator V
= P
.VersionList();
711 Dynamic
<pkgCache::VerIterator
> DynV(V
);
712 for (; V
.end() != true; ++V
)
714 // copy P.Arch() into a string here as a cache remap
715 // in NewDepends() later may alter the pointer location
716 string Arch
= P
.Arch() == NULL
? "" : P
.Arch();
717 map_ptrloc
*OldDepLast
= NULL
;
718 /* MultiArch handling introduces a lot of implicit Dependencies:
719 - MultiArch: same → Co-Installable if they have the same version
720 - Architecture: all → Need to be Co-Installable for internal reasons
721 - All others conflict with all other group members */
722 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
723 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
727 /* We allow only one installed arch at the time
728 per group, therefore each group member conflicts
729 with all other group members */
730 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
731 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
734 if (coInstall
== true)
736 // Replaces: ${self}:other ( << ${binary:Version})
737 NewDepends(D
, V
, V
.VerStr(),
738 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
740 // Breaks: ${self}:other (!= ${binary:Version})
741 NewDepends(D
, V
, V
.VerStr(),
742 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
745 // Conflicts: ${self}:other
747 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
758 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
759 // ---------------------------------------------------------------------
760 /* This creates a dependency element in the tree. It is linked to the
761 version and to the package that it is pointing to. */
762 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
763 pkgCache::VerIterator
&Ver
,
764 string
const &Version
,
765 unsigned int const &Op
,
766 unsigned int const &Type
,
767 map_ptrloc
* &OldDepLast
)
769 void const * const oldMap
= Map
.Data();
771 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
772 if (unlikely(Dependency
== 0))
776 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
777 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
778 Dep
->ParentVer
= Ver
.Index();
781 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
783 // Probe the reverse dependency list for a version string that matches
784 if (Version
.empty() == false)
786 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
787 if (I->Version != 0 && I.TargetVer() == Version)
788 Dep->Version = I->Version;*/
789 if (Dep
->Version
== 0) {
790 map_ptrloc
const index
= WriteStringInMap(Version
);
791 if (unlikely(index
== 0))
793 Dep
->Version
= index
;
797 // Link it to the package
798 Dep
->Package
= Pkg
.Index();
799 Dep
->NextRevDepends
= Pkg
->RevDepends
;
800 Pkg
->RevDepends
= Dep
.Index();
802 // Do we know where to link the Dependency to?
803 if (OldDepLast
== NULL
)
805 OldDepLast
= &Ver
->DependsList
;
806 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
807 OldDepLast
= &D
->NextDepends
;
808 } else if (oldMap
!= Map
.Data())
809 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
811 Dep
->NextDepends
= *OldDepLast
;
812 *OldDepLast
= Dep
.Index();
813 OldDepLast
= &Dep
->NextDepends
;
818 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
819 // ---------------------------------------------------------------------
820 /* This creates a Group and the Package to link this dependency to if
821 needed and handles also the caching of the old endpoint */
822 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
823 const string
&PackageName
,
825 const string
&Version
,
829 pkgCache::GrpIterator Grp
;
830 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
831 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
834 // Locate the target package
835 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
836 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
837 if (Pkg
.end() == true) {
838 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
842 // Is it a file dependency?
843 if (unlikely(PackageName
[0] == '/'))
844 FoundFileDeps
= true;
846 /* Caching the old end point speeds up generation substantially */
847 if (OldDepVer
!= Ver
) {
852 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
855 // ListParser::NewProvides - Create a Provides element /*{{{*/
856 // ---------------------------------------------------------------------
858 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
859 const string
&PkgName
,
860 const string
&PkgArch
,
861 const string
&Version
)
863 pkgCache
&Cache
= Owner
->Cache
;
865 // We do not add self referencing provides
866 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
867 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
871 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
872 if (unlikely(Provides
== 0))
874 Cache
.HeaderP
->ProvidesCount
++;
877 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
878 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
879 Prv
->Version
= Ver
.Index();
880 Prv
->NextPkgProv
= Ver
->ProvidesList
;
881 Ver
->ProvidesList
= Prv
.Index();
882 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
885 // Locate the target package
886 pkgCache::PkgIterator Pkg
;
887 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
888 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
891 // Link it to the package
892 Prv
->ParentPkg
= Pkg
.Index();
893 Prv
->NextProvides
= Pkg
->ProvidesList
;
894 Pkg
->ProvidesList
= Prv
.Index();
899 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
900 // ---------------------------------------------------------------------
901 /* This is used to select which file is to be associated with all newly
902 added versions. The caller is responsible for setting the IMS fields. */
903 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
904 const pkgIndexFile
&Index
,
907 // Get some space for the structure
908 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
909 if (unlikely(idxFile
== 0))
911 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
914 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
915 map_ptrloc
const idxSite
= WriteUniqString(Site
);
916 if (unlikely(idxFileName
== 0 || idxSite
== 0))
918 CurrentFile
->FileName
= idxFileName
;
919 CurrentFile
->Site
= idxSite
;
920 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
921 CurrentFile
->Flags
= Flags
;
922 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
923 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
924 if (unlikely(idxIndexType
== 0))
926 CurrentFile
->IndexType
= idxIndexType
;
928 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
929 Cache
.HeaderP
->PackageFileCount
++;
932 Progress
->SubProgress(Index
.Size());
936 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
937 // ---------------------------------------------------------------------
938 /* This is used to create handles to strings. Given the same text it
939 always returns the same number */
940 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
943 /* We use a very small transient hash table here, this speeds up generation
944 by a fair amount on slower machines */
945 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
947 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
948 return Bucket
->String
;
950 // Search for an insertion point
951 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
953 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
954 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
955 I
= Cache
.StringItemP
+ I
->NextItem
)
957 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
970 void const * const oldMap
= Map
.Data();
971 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
975 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
976 if (unlikely(idxString
== 0))
978 if (oldMap
!= Map
.Data()) {
979 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
980 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
984 // Fill in the structure
985 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
986 ItemP
->NextItem
= I
- Cache
.StringItemP
;
987 ItemP
->String
= idxString
;
990 return ItemP
->String
;
993 // CheckValidity - Check that a cache is up-to-date /*{{{*/
994 // ---------------------------------------------------------------------
995 /* This just verifies that each file in the list of index files exists,
996 has matching attributes with the cache and the cache does not have
998 static bool CheckValidity(const string
&CacheFile
,
1004 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1005 // No file, certainly invalid
1006 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
1009 std::clog
<< "CacheFile doesn't exist" << std::endl
;
1013 if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
))
1016 std::clog
<< "sources.list is newer than the cache" << std::endl
;
1021 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
1022 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
1023 pkgCache
Cache(Map
);
1024 if (_error
->PendingError() == true || Map
->Size() == 0)
1027 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
1032 /* Now we check every index file, see if it is in the cache,
1033 verify the IMS data and check that it is on the disk too.. */
1034 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
1035 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
1036 for (; Start
!= End
; ++Start
)
1039 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
1040 if ((*Start
)->HasPackages() == false)
1043 std::clog
<< "Has NO packages" << std::endl
;
1047 if ((*Start
)->Exists() == false)
1049 #if 0 // mvo: we no longer give a message here (Default Sources spec)
1050 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
1051 (*Start
)->Describe().c_str());
1054 std::clog
<< "file doesn't exist" << std::endl
;
1058 // FindInCache is also expected to do an IMS check.
1059 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
1060 if (File
.end() == true)
1063 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
1067 Visited
[File
->ID
] = true;
1069 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
1072 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
1073 if (Visited
[I
] == false)
1076 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1080 if (_error
->PendingError() == true)
1084 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1085 _error
->DumpErrors();
1092 *OutMap
= Map
.UnGuard();
1096 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1097 // ---------------------------------------------------------------------
1098 /* Size is kind of an abstract notion that is only used for the progress
1100 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1102 unsigned long TotalSize
= 0;
1103 for (; Start
!= End
; ++Start
)
1105 if ((*Start
)->HasPackages() == false)
1107 TotalSize
+= (*Start
)->Size();
1112 // BuildCache - Merge the list of index files into the cache /*{{{*/
1113 // ---------------------------------------------------------------------
1115 static bool BuildCache(pkgCacheGenerator
&Gen
,
1116 OpProgress
*Progress
,
1117 unsigned long &CurrentSize
,unsigned long TotalSize
,
1118 FileIterator Start
, FileIterator End
)
1121 for (I
= Start
; I
!= End
; ++I
)
1123 if ((*I
)->HasPackages() == false)
1126 if ((*I
)->Exists() == false)
1129 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1131 _error
->Warning("Duplicate sources.list entry %s",
1132 (*I
)->Describe().c_str());
1136 unsigned long Size
= (*I
)->Size();
1137 if (Progress
!= NULL
)
1138 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1139 CurrentSize
+= Size
;
1141 if ((*I
)->Merge(Gen
,Progress
) == false)
1145 if (Gen
.HasFileDeps() == true)
1147 if (Progress
!= NULL
)
1149 TotalSize
= ComputeSize(Start
, End
);
1151 for (I
= Start
; I
!= End
; ++I
)
1153 unsigned long Size
= (*I
)->Size();
1154 if (Progress
!= NULL
)
1155 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1156 CurrentSize
+= Size
;
1157 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1165 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1166 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1167 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1168 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1169 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1170 Flags
|= MMap::Moveable
;
1171 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1172 Flags
|= MMap::Fallback
;
1174 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1176 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1179 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1180 // ---------------------------------------------------------------------
1181 /* This makes sure that the status cache (the cache that has all
1182 index files from the sources list and all local ones) is ready
1183 to be mmaped. If OutMap is not zero then a MMap object representing
1184 the cache will be stored there. This is pretty much mandetory if you
1185 are using AllowMem. AllowMem lets the function be run as non-root
1186 where it builds the cache 'fast' into a memory buffer. */
1187 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1188 MMap
**OutMap
, bool AllowMem
)
1189 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1190 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1191 MMap
**OutMap
,bool AllowMem
)
1193 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1195 vector
<pkgIndexFile
*> Files
;
1196 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1200 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1201 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1202 j
!= Indexes
->end();
1204 Files
.push_back (*j
);
1207 unsigned long const EndOfSource
= Files
.size();
1208 if (_system
->AddStatusFiles(Files
) == false)
1211 // Decide if we can write to the files..
1212 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1213 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1215 // ensure the cache directory exists
1216 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1218 string dir
= _config
->FindDir("Dir::Cache");
1219 size_t const len
= dir
.size();
1220 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1221 dir
= dir
.substr(0, len
- 5);
1222 if (CacheFile
.empty() == false)
1223 CreateDirectory(dir
, flNotFile(CacheFile
));
1224 if (SrcCacheFile
.empty() == false)
1225 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1228 // Decide if we can write to the cache
1229 bool Writeable
= false;
1230 if (CacheFile
.empty() == false)
1231 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1233 if (SrcCacheFile
.empty() == false)
1234 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1236 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1238 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1239 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1241 if (Progress
!= NULL
)
1242 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1244 // Cache is OK, Fin.
1245 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1247 if (Progress
!= NULL
)
1248 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1250 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1253 else if (Debug
== true)
1254 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1256 /* At this point we know we need to reconstruct the package cache,
1258 SPtr
<FileFd
> CacheF
;
1259 SPtr
<DynamicMMap
> Map
;
1260 if (Writeable
== true && CacheFile
.empty() == false)
1262 _error
->PushToStack();
1263 unlink(CacheFile
.c_str());
1264 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1265 fchmod(CacheF
->Fd(),0644);
1266 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1267 if (_error
->PendingError() == true)
1269 delete CacheF
.UnGuard();
1270 delete Map
.UnGuard();
1272 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1274 if (AllowMem
== false)
1276 _error
->MergeWithStack();
1279 _error
->RevertToStack();
1281 else if (Debug
== true)
1283 _error
->MergeWithStack();
1284 std::clog
<< "Open filebased MMap" << std::endl
;
1287 if (Writeable
== false || CacheFile
.empty() == true)
1289 // Just build it in memory..
1290 Map
= CreateDynamicMMap(NULL
);
1292 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1295 // Lets try the source cache.
1296 unsigned long CurrentSize
= 0;
1297 unsigned long TotalSize
= 0;
1298 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1299 Files
.begin()+EndOfSource
) == true)
1302 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1303 // Preload the map with the source cache
1304 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1305 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1306 if ((alloc
== 0 && _error
->PendingError())
1307 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1308 SCacheF
.Size()) == false)
1311 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1313 // Build the status cache
1314 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1315 if (_error
->PendingError() == true)
1317 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1318 Files
.begin()+EndOfSource
,Files
.end()) == false)
1321 // FIXME: move me to a better place
1322 Gen
.FinishCache(Progress
);
1327 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1328 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1330 // Build the source cache
1331 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1332 if (_error
->PendingError() == true)
1334 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1335 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1339 if (Writeable
== true && SrcCacheFile
.empty() == false)
1341 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1342 if (_error
->PendingError() == true)
1345 fchmod(SCacheF
.Fd(),0644);
1347 // Write out the main data
1348 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1349 return _error
->Error(_("IO Error saving source cache"));
1352 // Write out the proper header
1353 Gen
.GetCache().HeaderP
->Dirty
= false;
1354 if (SCacheF
.Seek(0) == false ||
1355 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1356 return _error
->Error(_("IO Error saving source cache"));
1357 Gen
.GetCache().HeaderP
->Dirty
= true;
1361 // Build the status cache
1362 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1363 Files
.begin()+EndOfSource
,Files
.end()) == false)
1366 // FIXME: move me to a better place
1367 Gen
.FinishCache(Progress
);
1370 std::clog
<< "Caches are ready for shipping" << std::endl
;
1372 if (_error
->PendingError() == true)
1378 delete Map
.UnGuard();
1379 *OutMap
= new MMap(*CacheF
,0);
1383 *OutMap
= Map
.UnGuard();
1390 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1391 // ---------------------------------------------------------------------
1393 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1394 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1395 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1397 vector
<pkgIndexFile
*> Files
;
1398 unsigned long EndOfSource
= Files
.size();
1399 if (_system
->AddStatusFiles(Files
) == false)
1402 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1403 unsigned long CurrentSize
= 0;
1404 unsigned long TotalSize
= 0;
1406 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1408 // Build the status cache
1409 if (Progress
!= NULL
)
1410 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1411 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1412 if (_error
->PendingError() == true)
1414 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1415 Files
.begin()+EndOfSource
,Files
.end()) == false)
1418 // FIXME: move me to a better place
1419 Gen
.FinishCache(Progress
);
1421 if (_error
->PendingError() == true)
1423 *OutMap
= Map
.UnGuard();
1428 // IsDuplicateDescription /*{{{*/
1429 bool IsDuplicateDescription(pkgCache::DescIterator Desc
,
1430 MD5SumValue
const &CurMd5
, std::string
const &CurLang
)
1432 // Descriptions in the same link-list have all the same md5
1433 if (MD5SumValue(Desc
.md5()) != CurMd5
)
1435 for (; Desc
.end() == false; ++Desc
)
1436 if (Desc
.LanguageCode() == CurLang
)