]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
5147d7547e16d5690de12e9eeabac0af40a57e42
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 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
42 // ---------------------------------------------------------------------
43 /* We set the dirty flag and make sure that is written to the disk */
44 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
45 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
49 memset(UniqHash
,0,sizeof(UniqHash
));
51 if (_error
->PendingError() == true)
56 // Setup the map interface..
57 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
58 if (Map
.RawAllocate(sizeof(pkgCache::Header
)) == 0 && _error
->PendingError() == true)
61 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
64 *Cache
.HeaderP
= pkgCache::Header();
65 map_ptrloc
const idxVerSysName
= WriteStringInMap(_system
->VS
->Label
);
66 Cache
.HeaderP
->VerSysName
= idxVerSysName
;
67 map_ptrloc
const idxArchitecture
= WriteStringInMap(_config
->Find("APT::Architecture"));
68 Cache
.HeaderP
->Architecture
= idxArchitecture
;
69 if (unlikely(idxVerSysName
== 0 || idxArchitecture
== 0))
75 // Map directly from the existing file
77 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
78 if (Cache
.VS
!= _system
->VS
)
80 _error
->Error(_("Cache has an incompatible versioning system"));
85 Cache
.HeaderP
->Dirty
= true;
86 Map
.Sync(0,sizeof(pkgCache::Header
));
89 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
90 // ---------------------------------------------------------------------
91 /* We sync the data then unset the dirty flag in two steps so as to
92 advoid a problem during a crash */
93 pkgCacheGenerator::~pkgCacheGenerator()
95 if (_error
->PendingError() == true)
97 if (Map
.Sync() == false)
100 Cache
.HeaderP
->Dirty
= false;
101 Cache
.HeaderP
->CacheFileSize
= Map
.Size();
102 Map
.Sync(0,sizeof(pkgCache::Header
));
105 void pkgCacheGenerator::ReMap(void const * const oldMap
, void const * const newMap
) {/*{{{*/
106 if (oldMap
== newMap
)
109 if (_config
->FindB("Debug::pkgCacheGen", false))
110 std::clog
<< "Remaping from " << oldMap
<< " to " << newMap
<< std::endl
;
114 CurrentFile
+= (pkgCache::PackageFile
*) newMap
- (pkgCache::PackageFile
*) oldMap
;
116 for (size_t i
= 0; i
< _count(UniqHash
); ++i
)
117 if (UniqHash
[i
] != 0)
118 UniqHash
[i
] += (pkgCache::StringItem
*) newMap
- (pkgCache::StringItem
*) oldMap
;
120 for (std::vector
<pkgCache::GrpIterator
*>::const_iterator i
= Dynamic
<pkgCache::GrpIterator
>::toReMap
.begin();
121 i
!= Dynamic
<pkgCache::GrpIterator
>::toReMap
.end(); ++i
)
122 (*i
)->ReMap(oldMap
, newMap
);
123 for (std::vector
<pkgCache::PkgIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgIterator
>::toReMap
.begin();
124 i
!= Dynamic
<pkgCache::PkgIterator
>::toReMap
.end(); ++i
)
125 (*i
)->ReMap(oldMap
, newMap
);
126 for (std::vector
<pkgCache::VerIterator
*>::const_iterator i
= Dynamic
<pkgCache::VerIterator
>::toReMap
.begin();
127 i
!= Dynamic
<pkgCache::VerIterator
>::toReMap
.end(); ++i
)
128 (*i
)->ReMap(oldMap
, newMap
);
129 for (std::vector
<pkgCache::DepIterator
*>::const_iterator i
= Dynamic
<pkgCache::DepIterator
>::toReMap
.begin();
130 i
!= Dynamic
<pkgCache::DepIterator
>::toReMap
.end(); ++i
)
131 (*i
)->ReMap(oldMap
, newMap
);
132 for (std::vector
<pkgCache::DescIterator
*>::const_iterator i
= Dynamic
<pkgCache::DescIterator
>::toReMap
.begin();
133 i
!= Dynamic
<pkgCache::DescIterator
>::toReMap
.end(); ++i
)
134 (*i
)->ReMap(oldMap
, newMap
);
135 for (std::vector
<pkgCache::PrvIterator
*>::const_iterator i
= Dynamic
<pkgCache::PrvIterator
>::toReMap
.begin();
136 i
!= Dynamic
<pkgCache::PrvIterator
>::toReMap
.end(); ++i
)
137 (*i
)->ReMap(oldMap
, newMap
);
138 for (std::vector
<pkgCache::PkgFileIterator
*>::const_iterator i
= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.begin();
139 i
!= Dynamic
<pkgCache::PkgFileIterator
>::toReMap
.end(); ++i
)
140 (*i
)->ReMap(oldMap
, newMap
);
142 // CacheGenerator::WriteStringInMap /*{{{*/
143 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
,
144 const unsigned long &Len
) {
145 void const * const oldMap
= Map
.Data();
146 map_ptrloc
const index
= Map
.WriteString(String
, Len
);
148 ReMap(oldMap
, Map
.Data());
152 // CacheGenerator::WriteStringInMap /*{{{*/
153 map_ptrloc
pkgCacheGenerator::WriteStringInMap(const char *String
) {
154 void const * const oldMap
= Map
.Data();
155 map_ptrloc
const index
= Map
.WriteString(String
);
157 ReMap(oldMap
, Map
.Data());
161 map_ptrloc
pkgCacheGenerator::AllocateInMap(const unsigned long &size
) {/*{{{*/
162 void const * const oldMap
= Map
.Data();
163 map_ptrloc
const index
= Map
.Allocate(size
);
165 ReMap(oldMap
, Map
.Data());
169 // CacheGenerator::MergeList - Merge the package list /*{{{*/
170 // ---------------------------------------------------------------------
171 /* This provides the generation of the entries in the cache. Each loop
172 goes through a single package record from the underlying parse engine. */
173 bool pkgCacheGenerator::MergeList(ListParser
&List
,
174 pkgCache::VerIterator
*OutVer
)
178 unsigned int Counter
= 0;
179 while (List
.Step() == true)
181 string
const PackageName
= List
.Package();
182 if (PackageName
.empty() == true)
186 if (Counter
% 100 == 0 && Progress
!= 0)
187 Progress
->Progress(List
.Offset());
189 string Arch
= List
.Architecture();
190 string
const Version
= List
.Version();
191 if (Version
.empty() == true && Arch
.empty() == true)
193 if (MergeListGroup(List
, PackageName
) == false)
197 if (Arch
.empty() == true)
198 Arch
= _config
->Find("APT::Architecture");
200 // Get a pointer to the package structure
201 pkgCache::PkgIterator Pkg
;
202 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
203 if (NewPackage(Pkg
, PackageName
, Arch
) == false)
204 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
207 if (Version
.empty() == true)
209 if (MergeListPackage(List
, Pkg
) == false)
214 if (MergeListVersion(List
, Pkg
, Version
, OutVer
) == false)
220 FoundFileDeps
|= List
.HasFileDeps();
225 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
226 return _error
->Error(_("Wow, you exceeded the number of package "
227 "names this APT is capable of."));
228 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
229 return _error
->Error(_("Wow, you exceeded the number of versions "
230 "this APT is capable of."));
231 if (Cache
.HeaderP
->DescriptionCount
>= (1ULL<<(sizeof(Cache
.DescP
->ID
)*8))-1)
232 return _error
->Error(_("Wow, you exceeded the number of descriptions "
233 "this APT is capable of."));
234 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
235 return _error
->Error(_("Wow, you exceeded the number of dependencies "
236 "this APT is capable of."));
238 FoundFileDeps
|= List
.HasFileDeps();
241 // CacheGenerator::MergeListGroup /*{{{*/
242 bool pkgCacheGenerator::MergeListGroup(ListParser
&List
, std::string
const &GrpName
)
244 pkgCache::GrpIterator Grp
= Cache
.FindGrp(GrpName
);
245 if (Grp
.end() == true)
246 return _error
->Error("Information merge for non-existent group %s requested", GrpName
.c_str());
247 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
249 pkgCache::PkgIterator Pkg
;
250 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
251 for (Pkg
= Grp
.PackageList(); Pkg
.end() == false; Pkg
= Grp
.NextPkg(Pkg
))
252 if (MergeListPackage(List
, Pkg
) == false)
258 // CacheGenerator::MergeListPackage /*{{{*/
259 bool pkgCacheGenerator::MergeListPackage(ListParser
&List
, pkgCache::PkgIterator
&Pkg
)
261 // we first process the package, then the descriptions
262 // (for deb this package processing is in fact a no-op)
263 pkgCache::VerIterator
Ver(Cache
);
264 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
265 if (List
.UsePackage(Pkg
, Ver
) == false)
266 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
269 // Find the right version to write the description
270 MD5SumValue CurMd5
= List
.Description_md5();
272 for (Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
274 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
275 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
276 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
279 // don't add a new description if we have one for the given
281 bool duplicate
= false;
282 for ( ; Desc
.end() == false; ++Desc
)
283 if (MD5SumValue(Desc
.md5()) == CurMd5
&&
284 Desc
.LanguageCode() == List
.DescriptionLanguage())
286 if (duplicate
== true)
289 for (Desc
= Ver
.DescriptionList();
291 LastDesc
= &Desc
->NextDesc
, ++Desc
)
293 if (MD5SumValue(Desc
.md5()) != CurMd5
)
296 // Add new description
297 void const * const oldMap
= Map
.Data();
298 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), CurMd5
, *LastDesc
);
299 if (oldMap
!= Map
.Data())
300 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
301 *LastDesc
= descindex
;
302 Desc
->ParentPkg
= Pkg
.Index();
304 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
305 return _error
->Error(_("Error occurred while processing %s (NewFileDesc1)"), Pkg
.Name());
313 // CacheGenerator::MergeListVersion /*{{{*/
314 bool pkgCacheGenerator::MergeListVersion(ListParser
&List
, pkgCache::PkgIterator
&Pkg
,
315 std::string
const &Version
, pkgCache::VerIterator
* &OutVer
)
317 pkgCache::VerIterator Ver
= Pkg
.VersionList();
318 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
319 map_ptrloc
*LastVer
= &Pkg
->VersionList
;
320 void const * oldMap
= Map
.Data();
322 unsigned long const Hash
= List
.VersionHash();
323 if (Ver
.end() == false)
325 /* We know the list is sorted so we use that fact in the search.
326 Insertion of new versions is done with correct sorting */
328 for (; Ver
.end() == false; LastVer
= &Ver
->NextVer
, Ver
++)
330 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
331 // Version is higher as current version - insert here
334 // Versionstrings are equal - is hash also equal?
335 if (Res
== 0 && Ver
->Hash
== Hash
)
337 // proceed with the next till we have either the right
338 // or we found another version (which will be lower)
341 /* We already have a version for this item, record that we saw it */
342 if (Res
== 0 && Ver
.end() == false && Ver
->Hash
== Hash
)
344 if (List
.UsePackage(Pkg
,Ver
) == false)
345 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
348 if (NewFileVer(Ver
,List
) == false)
349 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
352 // Read only a single record and return
364 map_ptrloc
const verindex
= NewVersion(Ver
,Version
,*LastVer
);
365 if (verindex
== 0 && _error
->PendingError())
366 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
369 if (oldMap
!= Map
.Data())
370 LastVer
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
372 Ver
->ParentPkg
= Pkg
.Index();
375 if (List
.NewVersion(Ver
) == false)
376 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
379 if (List
.UsePackage(Pkg
,Ver
) == false)
380 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
383 if (NewFileVer(Ver
,List
) == false)
384 return _error
->Error(_("Error occurred while processing %s (NewVersion%d)"),
387 // Read only a single record and return
394 /* Record the Description data. Description data always exist in
395 Packages and Translation-* files. */
396 pkgCache::DescIterator Desc
= Ver
.DescriptionList();
397 Dynamic
<pkgCache::DescIterator
> DynDesc(Desc
);
398 map_ptrloc
*LastDesc
= &Ver
->DescriptionList
;
400 // Skip to the end of description set
401 for (; Desc
.end() == false; LastDesc
= &Desc
->NextDesc
, ++Desc
);
403 // Add new description
405 map_ptrloc
const descindex
= NewDescription(Desc
, List
.DescriptionLanguage(), List
.Description_md5(), *LastDesc
);
406 if (oldMap
!= Map
.Data())
407 LastDesc
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
408 *LastDesc
= descindex
;
409 Desc
->ParentPkg
= Pkg
.Index();
411 if ((*LastDesc
== 0 && _error
->PendingError()) || NewFileDesc(Desc
,List
) == false)
412 return _error
->Error(_("Error occurred while processing %s (NewFileDesc2)"),Pkg
.Name());
418 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
419 // ---------------------------------------------------------------------
420 /* If we found any file depends while parsing the main list we need to
421 resolve them. Since it is undesired to load the entire list of files
422 into the cache as virtual packages we do a two stage effort. MergeList
423 identifies the file depends and this creates Provdies for them by
424 re-parsing all the indexs. */
425 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
429 unsigned int Counter
= 0;
430 while (List
.Step() == true)
432 string PackageName
= List
.Package();
433 if (PackageName
.empty() == true)
435 string Version
= List
.Version();
436 if (Version
.empty() == true)
439 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
440 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
441 if (Pkg
.end() == true)
442 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
443 PackageName
.c_str());
445 if (Counter
% 100 == 0 && Progress
!= 0)
446 Progress
->Progress(List
.Offset());
448 unsigned long Hash
= List
.VersionHash();
449 pkgCache::VerIterator Ver
= Pkg
.VersionList();
450 Dynamic
<pkgCache::VerIterator
> DynVer(Ver
);
451 for (; Ver
.end() == false; ++Ver
)
453 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
455 if (List
.CollectFileProvides(Cache
,Ver
) == false)
456 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
461 if (Ver
.end() == true)
462 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
468 // CacheGenerator::NewGroup - Add a new group /*{{{*/
469 // ---------------------------------------------------------------------
470 /* This creates a new group structure and adds it to the hash table */
471 bool pkgCacheGenerator::NewGroup(pkgCache::GrpIterator
&Grp
, const string
&Name
)
473 Grp
= Cache
.FindGrp(Name
);
474 if (Grp
.end() == false)
478 map_ptrloc
const Group
= AllocateInMap(sizeof(pkgCache::Group
));
479 if (unlikely(Group
== 0))
482 Grp
= pkgCache::GrpIterator(Cache
, Cache
.GrpP
+ Group
);
483 map_ptrloc
const idxName
= WriteStringInMap(Name
);
484 if (unlikely(idxName
== 0))
488 // Insert it into the hash table
489 unsigned long const Hash
= Cache
.Hash(Name
);
490 Grp
->Next
= Cache
.HeaderP
->GrpHashTable
[Hash
];
491 Cache
.HeaderP
->GrpHashTable
[Hash
] = Group
;
493 Grp
->ID
= Cache
.HeaderP
->GroupCount
++;
497 // CacheGenerator::NewPackage - Add a new package /*{{{*/
498 // ---------------------------------------------------------------------
499 /* This creates a new package structure and adds it to the hash table */
500 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
,
501 const string
&Arch
) {
502 pkgCache::GrpIterator Grp
;
503 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
504 if (unlikely(NewGroup(Grp
, Name
) == false))
507 Pkg
= Grp
.FindPkg(Arch
);
508 if (Pkg
.end() == false)
512 map_ptrloc
const Package
= AllocateInMap(sizeof(pkgCache::Package
));
513 if (unlikely(Package
== 0))
515 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
517 // Insert the package into our package list
518 if (Grp
->FirstPackage
== 0) // the group is new
520 // Insert it into the hash table
521 unsigned long const Hash
= Cache
.Hash(Name
);
522 Pkg
->NextPackage
= Cache
.HeaderP
->PkgHashTable
[Hash
];
523 Cache
.HeaderP
->PkgHashTable
[Hash
] = Package
;
524 Grp
->FirstPackage
= Package
;
526 else // Group the Packages together
528 // this package is the new last package
529 pkgCache::PkgIterator
LastPkg(Cache
, Cache
.PkgP
+ Grp
->LastPackage
);
530 Pkg
->NextPackage
= LastPkg
->NextPackage
;
531 LastPkg
->NextPackage
= Package
;
533 Grp
->LastPackage
= Package
;
535 // Set the name, arch and the ID
536 Pkg
->Name
= Grp
->Name
;
537 Pkg
->Group
= Grp
.Index();
538 // all is mapped to the native architecture
539 map_ptrloc
const idxArch
= (Arch
== "all") ? Cache
.HeaderP
->Architecture
: WriteUniqString(Arch
.c_str());
540 if (unlikely(idxArch
== 0))
543 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
548 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
549 // ---------------------------------------------------------------------
551 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
554 if (CurrentFile
== 0)
558 map_ptrloc
const VerFile
= AllocateInMap(sizeof(pkgCache::VerFile
));
562 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
563 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
565 // Link it to the end of the list
566 map_ptrloc
*Last
= &Ver
->FileList
;
567 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; ++V
)
569 VF
->NextFile
= *Last
;
572 VF
->Offset
= List
.Offset();
573 VF
->Size
= List
.Size();
574 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
575 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
576 Cache
.HeaderP
->VerFileCount
++;
581 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
582 // ---------------------------------------------------------------------
583 /* This puts a version structure in the linked list */
584 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
585 const string
&VerStr
,
589 map_ptrloc
const Version
= AllocateInMap(sizeof(pkgCache::Version
));
594 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
596 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
597 map_ptrloc
const idxVerStr
= WriteStringInMap(VerStr
);
598 if (unlikely(idxVerStr
== 0))
600 Ver
->VerStr
= idxVerStr
;
605 // CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/
606 // ---------------------------------------------------------------------
608 bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator
&Desc
,
611 if (CurrentFile
== 0)
615 map_ptrloc
const DescFile
= AllocateInMap(sizeof(pkgCache::DescFile
));
619 pkgCache::DescFileIterator
DF(Cache
,Cache
.DescFileP
+ DescFile
);
620 DF
->File
= CurrentFile
- Cache
.PkgFileP
;
622 // Link it to the end of the list
623 map_ptrloc
*Last
= &Desc
->FileList
;
624 for (pkgCache::DescFileIterator D
= Desc
.FileList(); D
.end() == false; ++D
)
627 DF
->NextFile
= *Last
;
630 DF
->Offset
= List
.Offset();
631 DF
->Size
= List
.Size();
632 if (Cache
.HeaderP
->MaxDescFileSize
< DF
->Size
)
633 Cache
.HeaderP
->MaxDescFileSize
= DF
->Size
;
634 Cache
.HeaderP
->DescFileCount
++;
639 // CacheGenerator::NewDescription - Create a new Description /*{{{*/
640 // ---------------------------------------------------------------------
641 /* This puts a description structure in the linked list */
642 map_ptrloc
pkgCacheGenerator::NewDescription(pkgCache::DescIterator
&Desc
,
644 const MD5SumValue
&md5sum
,
648 map_ptrloc
const Description
= AllocateInMap(sizeof(pkgCache::Description
));
649 if (Description
== 0)
653 Desc
= pkgCache::DescIterator(Cache
,Cache
.DescP
+ Description
);
654 Desc
->NextDesc
= Next
;
655 Desc
->ID
= Cache
.HeaderP
->DescriptionCount
++;
656 map_ptrloc
const idxlanguage_code
= WriteStringInMap(Lang
);
657 map_ptrloc
const idxmd5sum
= WriteStringInMap(md5sum
.Value());
658 if (unlikely(idxlanguage_code
== 0 || idxmd5sum
== 0))
660 Desc
->language_code
= idxlanguage_code
;
661 Desc
->md5sum
= idxmd5sum
;
666 // CacheGenerator::FinishCache - do various finish operations /*{{{*/
667 // ---------------------------------------------------------------------
668 /* This prepares the Cache for delivery */
669 bool pkgCacheGenerator::FinishCache(OpProgress
*Progress
)
671 // FIXME: add progress reporting for this operation
672 // Do we have different architectures in your groups ?
673 vector
<string
> archs
= APT::Configuration::getArchitectures();
674 if (archs
.size() > 1)
676 // Create Conflicts in between the group
677 pkgCache::GrpIterator G
= GetCache().GrpBegin();
678 Dynamic
<pkgCache::GrpIterator
> DynG(G
);
679 for (; G
.end() != true; ++G
)
681 string
const PkgName
= G
.Name();
682 pkgCache::PkgIterator P
= G
.PackageList();
683 Dynamic
<pkgCache::PkgIterator
> DynP(P
);
684 for (; P
.end() != true; P
= G
.NextPkg(P
))
686 pkgCache::PkgIterator allPkg
;
687 Dynamic
<pkgCache::PkgIterator
> DynallPkg(allPkg
);
688 pkgCache::VerIterator V
= P
.VersionList();
689 Dynamic
<pkgCache::VerIterator
> DynV(V
);
690 for (; V
.end() != true; ++V
)
692 // copy P.Arch() into a string here as a cache remap
693 // in NewDepends() later may alter the pointer location
694 string Arch
= P
.Arch() == NULL
? "" : P
.Arch();
695 map_ptrloc
*OldDepLast
= NULL
;
696 /* MultiArch handling introduces a lot of implicit Dependencies:
697 - MultiArch: same → Co-Installable if they have the same version
698 - Architecture: all → Need to be Co-Installable for internal reasons
699 - All others conflict with all other group members */
700 bool const coInstall
= ((V
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
);
701 for (vector
<string
>::const_iterator A
= archs
.begin(); A
!= archs
.end(); ++A
)
705 /* We allow only one installed arch at the time
706 per group, therefore each group member conflicts
707 with all other group members */
708 pkgCache::PkgIterator D
= G
.FindPkg(*A
);
709 Dynamic
<pkgCache::PkgIterator
> DynD(D
);
712 if (coInstall
== true)
714 // Replaces: ${self}:other ( << ${binary:Version})
715 NewDepends(D
, V
, V
.VerStr(),
716 pkgCache::Dep::Less
, pkgCache::Dep::Replaces
,
718 // Breaks: ${self}:other (!= ${binary:Version})
719 NewDepends(D
, V
, V
.VerStr(),
720 pkgCache::Dep::NotEquals
, pkgCache::Dep::DpkgBreaks
,
723 // Conflicts: ${self}:other
725 pkgCache::Dep::NoOp
, pkgCache::Dep::Conflicts
,
736 // CacheGenerator::NewDepends - Create a dependency element /*{{{*/
737 // ---------------------------------------------------------------------
738 /* This creates a dependency element in the tree. It is linked to the
739 version and to the package that it is pointing to. */
740 bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator
&Pkg
,
741 pkgCache::VerIterator
&Ver
,
742 string
const &Version
,
743 unsigned int const &Op
,
744 unsigned int const &Type
,
745 map_ptrloc
* &OldDepLast
)
747 void const * const oldMap
= Map
.Data();
749 map_ptrloc
const Dependency
= AllocateInMap(sizeof(pkgCache::Dependency
));
750 if (unlikely(Dependency
== 0))
754 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
755 Dynamic
<pkgCache::DepIterator
> DynDep(Dep
);
756 Dep
->ParentVer
= Ver
.Index();
759 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
761 // Probe the reverse dependency list for a version string that matches
762 if (Version
.empty() == false)
764 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
765 if (I->Version != 0 && I.TargetVer() == Version)
766 Dep->Version = I->Version;*/
767 if (Dep
->Version
== 0) {
768 map_ptrloc
const index
= WriteStringInMap(Version
);
769 if (unlikely(index
== 0))
771 Dep
->Version
= index
;
775 // Link it to the package
776 Dep
->Package
= Pkg
.Index();
777 Dep
->NextRevDepends
= Pkg
->RevDepends
;
778 Pkg
->RevDepends
= Dep
.Index();
780 // Do we know where to link the Dependency to?
781 if (OldDepLast
== NULL
)
783 OldDepLast
= &Ver
->DependsList
;
784 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; ++D
)
785 OldDepLast
= &D
->NextDepends
;
786 } else if (oldMap
!= Map
.Data())
787 OldDepLast
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
789 Dep
->NextDepends
= *OldDepLast
;
790 *OldDepLast
= Dep
.Index();
791 OldDepLast
= &Dep
->NextDepends
;
796 // ListParser::NewDepends - Create the environment for a new dependency /*{{{*/
797 // ---------------------------------------------------------------------
798 /* This creates a Group and the Package to link this dependency to if
799 needed and handles also the caching of the old endpoint */
800 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator
&Ver
,
801 const string
&PackageName
,
803 const string
&Version
,
807 pkgCache::GrpIterator Grp
;
808 Dynamic
<pkgCache::GrpIterator
> DynGrp(Grp
);
809 if (unlikely(Owner
->NewGroup(Grp
, PackageName
) == false))
812 // Locate the target package
813 pkgCache::PkgIterator Pkg
= Grp
.FindPkg(Arch
);
814 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
815 if (Pkg
.end() == true) {
816 if (unlikely(Owner
->NewPackage(Pkg
, PackageName
, Arch
) == false))
820 // Is it a file dependency?
821 if (unlikely(PackageName
[0] == '/'))
822 FoundFileDeps
= true;
824 /* Caching the old end point speeds up generation substantially */
825 if (OldDepVer
!= Ver
) {
830 return Owner
->NewDepends(Pkg
, Ver
, Version
, Op
, Type
, OldDepLast
);
833 // ListParser::NewProvides - Create a Provides element /*{{{*/
834 // ---------------------------------------------------------------------
836 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator
&Ver
,
837 const string
&PkgName
,
838 const string
&PkgArch
,
839 const string
&Version
)
841 pkgCache
&Cache
= Owner
->Cache
;
843 // We do not add self referencing provides
844 if (Ver
.ParentPkg().Name() == PkgName
&& (PkgArch
== Ver
.ParentPkg().Arch() ||
845 (PkgArch
== "all" && strcmp((Cache
.StrP
+ Cache
.HeaderP
->Architecture
), Ver
.ParentPkg().Arch()) == 0)))
849 map_ptrloc
const Provides
= Owner
->AllocateInMap(sizeof(pkgCache::Provides
));
850 if (unlikely(Provides
== 0))
852 Cache
.HeaderP
->ProvidesCount
++;
855 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
856 Dynamic
<pkgCache::PrvIterator
> DynPrv(Prv
);
857 Prv
->Version
= Ver
.Index();
858 Prv
->NextPkgProv
= Ver
->ProvidesList
;
859 Ver
->ProvidesList
= Prv
.Index();
860 if (Version
.empty() == false && unlikely((Prv
->ProvideVersion
= WriteString(Version
)) == 0))
863 // Locate the target package
864 pkgCache::PkgIterator Pkg
;
865 Dynamic
<pkgCache::PkgIterator
> DynPkg(Pkg
);
866 if (unlikely(Owner
->NewPackage(Pkg
,PkgName
, PkgArch
) == false))
869 // Link it to the package
870 Prv
->ParentPkg
= Pkg
.Index();
871 Prv
->NextProvides
= Pkg
->ProvidesList
;
872 Pkg
->ProvidesList
= Prv
.Index();
877 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
878 // ---------------------------------------------------------------------
879 /* This is used to select which file is to be associated with all newly
880 added versions. The caller is responsible for setting the IMS fields. */
881 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
882 const pkgIndexFile
&Index
,
885 // Get some space for the structure
886 map_ptrloc
const idxFile
= AllocateInMap(sizeof(*CurrentFile
));
887 if (unlikely(idxFile
== 0))
889 CurrentFile
= Cache
.PkgFileP
+ idxFile
;
892 map_ptrloc
const idxFileName
= WriteStringInMap(File
);
893 map_ptrloc
const idxSite
= WriteUniqString(Site
);
894 if (unlikely(idxFileName
== 0 || idxSite
== 0))
896 CurrentFile
->FileName
= idxFileName
;
897 CurrentFile
->Site
= idxSite
;
898 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
899 CurrentFile
->Flags
= Flags
;
900 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
901 map_ptrloc
const idxIndexType
= WriteUniqString(Index
.GetType()->Label
);
902 if (unlikely(idxIndexType
== 0))
904 CurrentFile
->IndexType
= idxIndexType
;
906 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
907 Cache
.HeaderP
->PackageFileCount
++;
910 Progress
->SubProgress(Index
.Size());
914 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
915 // ---------------------------------------------------------------------
916 /* This is used to create handles to strings. Given the same text it
917 always returns the same number */
918 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
921 /* We use a very small transient hash table here, this speeds up generation
922 by a fair amount on slower machines */
923 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
925 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
926 return Bucket
->String
;
928 // Search for an insertion point
929 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
931 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
932 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
933 I
= Cache
.StringItemP
+ I
->NextItem
)
935 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
948 void const * const oldMap
= Map
.Data();
949 map_ptrloc
const Item
= AllocateInMap(sizeof(pkgCache::StringItem
));
953 map_ptrloc
const idxString
= WriteStringInMap(S
,Size
);
954 if (unlikely(idxString
== 0))
956 if (oldMap
!= Map
.Data()) {
957 Last
+= (map_ptrloc
*) Map
.Data() - (map_ptrloc
*) oldMap
;
958 I
+= (pkgCache::StringItem
*) Map
.Data() - (pkgCache::StringItem
*) oldMap
;
962 // Fill in the structure
963 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
964 ItemP
->NextItem
= I
- Cache
.StringItemP
;
965 ItemP
->String
= idxString
;
968 return ItemP
->String
;
971 // CheckValidity - Check that a cache is up-to-date /*{{{*/
972 // ---------------------------------------------------------------------
973 /* This just verifies that each file in the list of index files exists,
974 has matching attributes with the cache and the cache does not have
976 static bool CheckValidity(const string
&CacheFile
,
982 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
983 // No file, certainly invalid
984 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
987 std::clog
<< "CacheFile doesn't exist" << std::endl
;
991 if (List
.GetLastModifiedTime() > GetModificationTime(CacheFile
))
994 std::clog
<< "sources.list is newer than the cache" << std::endl
;
999 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
1000 SPtr
<MMap
> Map
= new MMap(CacheF
,0);
1001 pkgCache
Cache(Map
);
1002 if (_error
->PendingError() == true || Map
->Size() == 0)
1005 std::clog
<< "Errors are pending or Map is empty()" << std::endl
;
1010 /* Now we check every index file, see if it is in the cache,
1011 verify the IMS data and check that it is on the disk too.. */
1012 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
1013 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
1014 for (; Start
!= End
; ++Start
)
1017 std::clog
<< "Checking PkgFile " << (*Start
)->Describe() << ": ";
1018 if ((*Start
)->HasPackages() == false)
1021 std::clog
<< "Has NO packages" << std::endl
;
1025 if ((*Start
)->Exists() == false)
1027 #if 0 // mvo: we no longer give a message here (Default Sources spec)
1028 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
1029 (*Start
)->Describe().c_str());
1032 std::clog
<< "file doesn't exist" << std::endl
;
1036 // FindInCache is also expected to do an IMS check.
1037 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
1038 if (File
.end() == true)
1041 std::clog
<< "FindInCache returned end-Pointer" << std::endl
;
1045 Visited
[File
->ID
] = true;
1047 std::clog
<< "with ID " << File
->ID
<< " is valid" << std::endl
;
1050 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
1051 if (Visited
[I
] == false)
1054 std::clog
<< "File with ID" << I
<< " wasn't visited" << std::endl
;
1058 if (_error
->PendingError() == true)
1062 std::clog
<< "Validity failed because of pending errors:" << std::endl
;
1063 _error
->DumpErrors();
1070 *OutMap
= Map
.UnGuard();
1074 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
1075 // ---------------------------------------------------------------------
1076 /* Size is kind of an abstract notion that is only used for the progress
1078 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
1080 unsigned long TotalSize
= 0;
1081 for (; Start
!= End
; ++Start
)
1083 if ((*Start
)->HasPackages() == false)
1085 TotalSize
+= (*Start
)->Size();
1090 // BuildCache - Merge the list of index files into the cache /*{{{*/
1091 // ---------------------------------------------------------------------
1093 static bool BuildCache(pkgCacheGenerator
&Gen
,
1094 OpProgress
*Progress
,
1095 unsigned long &CurrentSize
,unsigned long TotalSize
,
1096 FileIterator Start
, FileIterator End
)
1099 for (I
= Start
; I
!= End
; ++I
)
1101 if ((*I
)->HasPackages() == false)
1104 if ((*I
)->Exists() == false)
1107 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
1109 _error
->Warning("Duplicate sources.list entry %s",
1110 (*I
)->Describe().c_str());
1114 unsigned long Size
= (*I
)->Size();
1115 if (Progress
!= NULL
)
1116 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
1117 CurrentSize
+= Size
;
1119 if ((*I
)->Merge(Gen
,Progress
) == false)
1123 if (Gen
.HasFileDeps() == true)
1125 if (Progress
!= NULL
)
1127 TotalSize
= ComputeSize(Start
, End
);
1129 for (I
= Start
; I
!= End
; ++I
)
1131 unsigned long Size
= (*I
)->Size();
1132 if (Progress
!= NULL
)
1133 Progress
->OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
1134 CurrentSize
+= Size
;
1135 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
1143 // CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/
1144 DynamicMMap
* pkgCacheGenerator::CreateDynamicMMap(FileFd
*CacheF
, unsigned long Flags
) {
1145 unsigned long const MapStart
= _config
->FindI("APT::Cache-Start", 24*1024*1024);
1146 unsigned long const MapGrow
= _config
->FindI("APT::Cache-Grow", 1*1024*1024);
1147 unsigned long const MapLimit
= _config
->FindI("APT::Cache-Limit", 0);
1148 Flags
|= MMap::Moveable
;
1149 if (_config
->FindB("APT::Cache-Fallback", false) == true)
1150 Flags
|= MMap::Fallback
;
1152 return new DynamicMMap(*CacheF
, Flags
, MapStart
, MapGrow
, MapLimit
);
1154 return new DynamicMMap(Flags
, MapStart
, MapGrow
, MapLimit
);
1157 // CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/
1158 // ---------------------------------------------------------------------
1159 /* This makes sure that the status cache (the cache that has all
1160 index files from the sources list and all local ones) is ready
1161 to be mmaped. If OutMap is not zero then a MMap object representing
1162 the cache will be stored there. This is pretty much mandetory if you
1163 are using AllowMem. AllowMem lets the function be run as non-root
1164 where it builds the cache 'fast' into a memory buffer. */
1165 __deprecated
bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
1166 MMap
**OutMap
, bool AllowMem
)
1167 { return pkgCacheGenerator::MakeStatusCache(List
, &Progress
, OutMap
, AllowMem
); }
1168 bool pkgCacheGenerator::MakeStatusCache(pkgSourceList
&List
,OpProgress
*Progress
,
1169 MMap
**OutMap
,bool AllowMem
)
1171 bool const Debug
= _config
->FindB("Debug::pkgCacheGen", false);
1173 vector
<pkgIndexFile
*> Files
;
1174 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
1178 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
1179 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
1180 j
!= Indexes
->end();
1182 Files
.push_back (*j
);
1185 unsigned long const EndOfSource
= Files
.size();
1186 if (_system
->AddStatusFiles(Files
) == false)
1189 // Decide if we can write to the files..
1190 string
const CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
1191 string
const SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
1193 // ensure the cache directory exists
1194 if (CacheFile
.empty() == false || SrcCacheFile
.empty() == false)
1196 string dir
= _config
->FindDir("Dir::Cache");
1197 size_t const len
= dir
.size();
1198 if (len
> 5 && dir
.find("/apt/", len
- 6, 5) == len
- 5)
1199 dir
= dir
.substr(0, len
- 5);
1200 if (CacheFile
.empty() == false)
1201 CreateDirectory(dir
, flNotFile(CacheFile
));
1202 if (SrcCacheFile
.empty() == false)
1203 CreateDirectory(dir
, flNotFile(SrcCacheFile
));
1206 // Decide if we can write to the cache
1207 bool Writeable
= false;
1208 if (CacheFile
.empty() == false)
1209 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
1211 if (SrcCacheFile
.empty() == false)
1212 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
1214 std::clog
<< "Do we have write-access to the cache files? " << (Writeable
? "YES" : "NO") << std::endl
;
1216 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
1217 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
1219 if (Progress
!= NULL
)
1220 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1222 // Cache is OK, Fin.
1223 if (CheckValidity(CacheFile
, List
, Files
.begin(),Files
.end(),OutMap
) == true)
1225 if (Progress
!= NULL
)
1226 Progress
->OverallProgress(1,1,1,_("Reading package lists"));
1228 std::clog
<< "pkgcache.bin is valid - no need to build anything" << std::endl
;
1231 else if (Debug
== true)
1232 std::clog
<< "pkgcache.bin is NOT valid" << std::endl
;
1234 /* At this point we know we need to reconstruct the package cache,
1236 SPtr
<FileFd
> CacheF
;
1237 SPtr
<DynamicMMap
> Map
;
1238 if (Writeable
== true && CacheFile
.empty() == false)
1240 _error
->PushToStack();
1241 unlink(CacheFile
.c_str());
1242 CacheF
= new FileFd(CacheFile
,FileFd::WriteAtomic
);
1243 fchmod(CacheF
->Fd(),0644);
1244 Map
= CreateDynamicMMap(CacheF
, MMap::Public
);
1245 if (_error
->PendingError() == true)
1247 delete CacheF
.UnGuard();
1248 delete Map
.UnGuard();
1250 std::clog
<< "Open filebased MMap FAILED" << std::endl
;
1252 if (AllowMem
== false)
1254 _error
->MergeWithStack();
1257 _error
->RevertToStack();
1259 else if (Debug
== true)
1261 _error
->MergeWithStack();
1262 std::clog
<< "Open filebased MMap" << std::endl
;
1265 if (Writeable
== false || CacheFile
.empty() == true)
1267 // Just build it in memory..
1268 Map
= CreateDynamicMMap(NULL
);
1270 std::clog
<< "Open memory Map (not filebased)" << std::endl
;
1273 // Lets try the source cache.
1274 unsigned long CurrentSize
= 0;
1275 unsigned long TotalSize
= 0;
1276 if (CheckValidity(SrcCacheFile
, List
, Files
.begin(),
1277 Files
.begin()+EndOfSource
) == true)
1280 std::clog
<< "srcpkgcache.bin is valid - populate MMap with it." << std::endl
;
1281 // Preload the map with the source cache
1282 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
1283 unsigned long const alloc
= Map
->RawAllocate(SCacheF
.Size());
1284 if ((alloc
== 0 && _error
->PendingError())
1285 || SCacheF
.Read((unsigned char *)Map
->Data() + alloc
,
1286 SCacheF
.Size()) == false)
1289 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1291 // Build the status cache
1292 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1293 if (_error
->PendingError() == true)
1295 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1296 Files
.begin()+EndOfSource
,Files
.end()) == false)
1299 // FIXME: move me to a better place
1300 Gen
.FinishCache(Progress
);
1305 std::clog
<< "srcpkgcache.bin is NOT valid - rebuild" << std::endl
;
1306 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
1308 // Build the source cache
1309 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1310 if (_error
->PendingError() == true)
1312 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1313 Files
.begin(),Files
.begin()+EndOfSource
) == false)
1317 if (Writeable
== true && SrcCacheFile
.empty() == false)
1319 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteAtomic
);
1320 if (_error
->PendingError() == true)
1323 fchmod(SCacheF
.Fd(),0644);
1325 // Write out the main data
1326 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
1327 return _error
->Error(_("IO Error saving source cache"));
1330 // Write out the proper header
1331 Gen
.GetCache().HeaderP
->Dirty
= false;
1332 if (SCacheF
.Seek(0) == false ||
1333 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
1334 return _error
->Error(_("IO Error saving source cache"));
1335 Gen
.GetCache().HeaderP
->Dirty
= true;
1339 // Build the status cache
1340 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1341 Files
.begin()+EndOfSource
,Files
.end()) == false)
1344 // FIXME: move me to a better place
1345 Gen
.FinishCache(Progress
);
1348 std::clog
<< "Caches are ready for shipping" << std::endl
;
1350 if (_error
->PendingError() == true)
1356 delete Map
.UnGuard();
1357 *OutMap
= new MMap(*CacheF
,0);
1361 *OutMap
= Map
.UnGuard();
1368 // CacheGenerator::MakeOnlyStatusCache - Build only a status files cache/*{{{*/
1369 // ---------------------------------------------------------------------
1371 __deprecated
bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
1372 { return pkgCacheGenerator::MakeOnlyStatusCache(&Progress
, OutMap
); }
1373 bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress
*Progress
,DynamicMMap
**OutMap
)
1375 vector
<pkgIndexFile
*> Files
;
1376 unsigned long EndOfSource
= Files
.size();
1377 if (_system
->AddStatusFiles(Files
) == false)
1380 SPtr
<DynamicMMap
> Map
= CreateDynamicMMap(NULL
);
1381 unsigned long CurrentSize
= 0;
1382 unsigned long TotalSize
= 0;
1384 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
1386 // Build the status cache
1387 if (Progress
!= NULL
)
1388 Progress
->OverallProgress(0,1,1,_("Reading package lists"));
1389 pkgCacheGenerator
Gen(Map
.Get(),Progress
);
1390 if (_error
->PendingError() == true)
1392 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
1393 Files
.begin()+EndOfSource
,Files
.end()) == false)
1396 // FIXME: move me to a better place
1397 Gen
.FinishCache(Progress
);
1399 if (_error
->PendingError() == true)
1401 *OutMap
= Map
.UnGuard();