1 : // -*- mode: c++; mode: fold -*-
2 : // Description /*{{{*/
3 : // $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $
4 : /* ######################################################################
5 :
6 : DepCache - Dependency Extension data for the cache
7 :
8 : This class stores the cache data and a set of extension structures for
9 : monitoring the current state of all the packages. It also generates and
10 : caches the 'install' state of many things. This refers to the state of the
11 : package after an install has been run.
12 :
13 : The StateCache::State field can be -1,0,1,2 which is <,=,>,no current.
14 : StateCache::Mode is which of the 3 fields is active.
15 :
16 : This structure is important to support the readonly status of the cache
17 : file. When the data is saved the cache will be refereshed from our
18 : internal rep and written to disk. Then the actual persistant data
19 : files will be put on the disk.
20 :
21 : Each dependency is compared against 3 target versions to produce to
22 : 3 dependency results.
23 : Now - Compared using the Currently install version
24 : Install - Compared using the install version (final state)
25 : CVer - (Candidate Verion) Compared using the Candidate Version
26 : The candidate and now results are used to decide wheather a package
27 : should be automatically installed or if it should be left alone.
28 :
29 : Remember, the Candidate Version is selected based on the distribution
30 : settings for the Package. The Install Version is selected based on the
31 : state (Delete, Keep, Install) field and can be either the Current Version
32 : or the Candidate version.
33 :
34 : The Candidate version is what is shown the 'Install Version' field.
35 :
36 : ##################################################################### */
37 : /*}}}*/
38 : #ifndef PKGLIB_DEPCACHE_H
39 : #define PKGLIB_DEPCACHE_H
40 :
41 :
42 : #include <apt-pkg/pkgcache.h>
43 : #include <apt-pkg/progress.h>
44 :
45 : #include <regex.h>
46 :
47 : #include <vector>
48 : #include <memory>
49 :
50 : class pkgDepCache : protected pkgCache::Namespace
51 : {
52 : public:
53 :
54 : /** \brief An arbitrary predicate on packages. */
55 : class InRootSetFunc
56 : {
57 : public:
58 : virtual bool InRootSet(const pkgCache::PkgIterator &pkg) {return false;};
59 : virtual ~InRootSetFunc() {};
60 : };
61 :
62 : private:
63 : /** \brief Mark a single package and all its unmarked important
64 : * dependencies during mark-and-sweep.
65 : *
66 : * Recursively invokes itself to mark all dependencies of the
67 : * package.
68 : *
69 : * \param pkg The package to mark.
70 : *
71 : * \param ver The version of the package that is to be marked.
72 : *
73 : * \param follow_recommends If \b true, recommendations of the
74 : * package will be recursively marked.
75 : *
76 : * \param follow_suggests If \b true, suggestions of the package
77 : * will be recursively marked.
78 : */
79 : void MarkPackage(const pkgCache::PkgIterator &pkg,
80 : const pkgCache::VerIterator &ver,
81 : bool follow_recommends,
82 : bool follow_suggests);
83 :
84 : /** \brief Update the Marked field of all packages.
85 : *
86 : * Each package's StateCache::Marked field will be set to \b true
87 : * if and only if it can be reached from the root set. By
88 : * default, the root set consists of the set of manually installed
89 : * or essential packages, but it can be extended using the
90 : * parameter #rootFunc.
91 : *
92 : * \param rootFunc A callback that can be used to add extra
93 : * packages to the root set.
94 : *
95 : * \return \b false if an error occurred.
96 : */
97 : bool MarkRequired(InRootSetFunc &rootFunc);
98 :
99 : /** \brief Set the StateCache::Garbage flag on all packages that
100 : * should be removed.
101 : *
102 : * Packages that were not marked by the last call to #MarkRequired
103 : * are tested to see whether they are actually garbage. If so,
104 : * they are marked as such.
105 : *
106 : * \return \b false if an error occurred.
107 : */
108 : bool Sweep();
109 :
110 : public:
111 :
112 : // These flags are used in DepState
113 : enum DepFlags {DepNow = (1 << 0),DepInstall = (1 << 1),DepCVer = (1 << 2),
114 : DepGNow = (1 << 3),DepGInstall = (1 << 4),DepGCVer = (1 << 5)};
115 :
116 : // These flags are used in StateCache::DepState
117 : enum DepStateFlags {DepNowPolicy = (1 << 0), DepNowMin = (1 << 1),
118 : DepInstPolicy = (1 << 2), DepInstMin = (1 << 3),
119 : DepCandPolicy = (1 << 4), DepCandMin = (1 << 5)};
120 :
121 : // These flags are used in StateCache::iFlags
122 : enum InternalFlags {AutoKept = (1 << 0), Purge = (1 << 1), ReInstall = (1 << 2)};
123 :
124 : enum VersionTypes {NowVersion, InstallVersion, CandidateVersion};
125 : enum ModeList {ModeDelete = 0, ModeKeep = 1, ModeInstall = 2};
126 :
127 : /** \brief Represents an active action group.
128 : *
129 : * An action group is a group of actions that are currently being
130 : * performed. While an active group is active, certain routine
131 : * clean-up actions that would normally be performed after every
132 : * cache operation are delayed until the action group is
133 : * completed. This is necessary primarily to avoid inefficiencies
134 : * when modifying a large number of packages at once.
135 : *
136 : * This class represents an active action group. Creating an
137 : * instance will create an action group; destroying one will
138 : * destroy the corresponding action group.
139 : *
140 : * The following operations are suppressed by this class:
141 : *
142 : * - Keeping the Marked and Garbage flags up to date.
143 : *
144 : * \note This can be used in the future to easily accumulate
145 : * atomic actions for undo or to display "what apt did anyway";
146 : * e.g., change the counter of how many action groups are active
147 : * to a std::set of pointers to them and use those to store
148 : * information about what happened in a group in the group.
149 : */
150 : class ActionGroup
151 : {
152 : pkgDepCache &cache;
153 :
154 : bool released;
155 :
156 : /** Action groups are noncopyable. */
157 : ActionGroup(const ActionGroup &other);
158 : public:
159 : /** \brief Create a new ActionGroup.
160 : *
161 : * \param cache The cache that this ActionGroup should
162 : * manipulate.
163 : *
164 : * As long as this object exists, no automatic cleanup
165 : * operations will be undertaken.
166 : */
167 : ActionGroup(pkgDepCache &cache);
168 :
169 : /** \brief Clean up the action group before it is destroyed.
170 : *
171 : * If it is destroyed later, no second cleanup wil be run.
172 : */
173 : void release();
174 :
175 : /** \brief Destroy the action group.
176 : *
177 : * If this is the last action group, the automatic cache
178 : * cleanup operations will be undertaken.
179 : */
180 : ~ActionGroup();
181 : };
182 :
183 : /** \brief Returns \b true for packages matching a regular
184 : * expression in APT::NeverAutoRemove.
185 : */
186 : class DefaultRootSetFunc : public InRootSetFunc
187 : {
188 : std::vector<regex_t *> rootSetRegexp;
189 : bool constructedSuccessfully;
190 :
191 : public:
192 : DefaultRootSetFunc();
193 : ~DefaultRootSetFunc();
194 :
195 : /** \return \b true if the class initialized successfully, \b
196 : * false otherwise. Used to avoid throwing an exception, since
197 : * APT classes generally don't.
198 : */
199 : bool wasConstructedSuccessfully() const { return constructedSuccessfully; }
200 :
201 : bool InRootSet(const pkgCache::PkgIterator &pkg);
202 : };
203 :
204 : struct StateCache
205 : {
206 : // Epoch stripped text versions of the two version fields
207 : const char *CandVersion;
208 : const char *CurVersion;
209 :
210 : // Pointer to the candidate install version.
211 : Version *CandidateVer;
212 :
213 : // Pointer to the install version.
214 : Version *InstallVer;
215 :
216 : // Copy of Package::Flags
217 : unsigned short Flags;
218 : unsigned short iFlags; // Internal flags
219 :
220 : /** \brief \b true if this package can be reached from the root set. */
221 : bool Marked;
222 :
223 : /** \brief \b true if this package is unused and should be removed.
224 : *
225 : * This differs from !#Marked, because it is possible that some
226 : * unreachable packages will be protected from becoming
227 : * garbage.
228 : */
229 : bool Garbage;
230 :
231 : // Various tree indicators
232 : signed char Status; // -1,0,1,2
233 : unsigned char Mode; // ModeList
234 : unsigned char DepState; // DepState Flags
235 :
236 : // Update of candidate version
237 : const char *StripEpoch(const char *Ver);
238 : void Update(PkgIterator Pkg,pkgCache &Cache);
239 :
240 : // Various test members for the current status of the package
241 : inline bool NewInstall() const {return Status == 2 && Mode == ModeInstall;};
242 3785 : inline bool Delete() const {return Mode == ModeDelete;};
243 3785 : inline bool Keep() const {return Mode == ModeKeep;};
244 : inline bool Upgrade() const {return Status > 0 && Mode == ModeInstall;};
245 : inline bool Upgradable() const {return Status >= 1;};
246 : inline bool Downgrade() const {return Status < 0 && Mode == ModeInstall;};
247 : inline bool Held() const {return Status != 0 && Keep();};
248 3785 : inline bool NowBroken() const {return (DepState & DepNowMin) != DepNowMin;};
249 : inline bool NowPolicyBroken() const {return (DepState & DepNowPolicy) != DepNowPolicy;};
250 3785 : inline bool InstBroken() const {return (DepState & DepInstMin) != DepInstMin;};
251 : inline bool InstPolicyBroken() const {return (DepState & DepInstPolicy) != DepInstPolicy;};
252 3785 : inline bool Install() const {return Mode == ModeInstall;};
253 : inline VerIterator InstVerIter(pkgCache &Cache)
254 : {return VerIterator(Cache,InstallVer);};
255 : inline VerIterator CandidateVerIter(pkgCache &Cache)
256 : {return VerIterator(Cache,CandidateVer);};
257 : };
258 :
259 : // Helper functions
260 : void BuildGroupOrs(VerIterator const &V);
261 : void UpdateVerState(PkgIterator Pkg);
262 :
263 : // User Policy control
264 : class Policy
265 : {
266 : public:
267 :
268 : virtual VerIterator GetCandidateVer(PkgIterator Pkg);
269 : virtual bool IsImportantDep(DepIterator Dep);
270 :
271 : virtual ~Policy() {};
272 : };
273 :
274 : private:
275 : /** The number of open "action groups"; certain post-action
276 : * operations are suppressed if this number is > 0.
277 : */
278 : int group_level;
279 :
280 : friend class ActionGroup;
281 :
282 : protected:
283 :
284 : // State information
285 : pkgCache *Cache;
286 : StateCache *PkgState;
287 : unsigned char *DepState;
288 :
289 : double iUsrSize;
290 : double iDownloadSize;
291 : unsigned long iInstCount;
292 : unsigned long iDelCount;
293 : unsigned long iKeepCount;
294 : unsigned long iBrokenCount;
295 : unsigned long iPolicyBrokenCount;
296 : unsigned long iBadCount;
297 :
298 : Policy *delLocalPolicy; // For memory clean up..
299 : Policy *LocalPolicy;
300 :
301 : // Check for a matching provides
302 : bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res);
303 : inline bool CheckDep(DepIterator Dep,int Type)
304 : {
305 : PkgIterator Res(*this,0);
306 : return CheckDep(Dep,Type,Res);
307 : }
308 :
309 : // Computes state information for deps and versions (w/o storing)
310 : unsigned char DependencyState(DepIterator &D);
311 : unsigned char VersionState(DepIterator D,unsigned char Check,
312 : unsigned char SetMin,
313 : unsigned char SetPolicy);
314 :
315 : // Recalculates various portions of the cache, call after changing something
316 : void Update(DepIterator Dep); // Mostly internal
317 : void Update(PkgIterator const &P);
318 :
319 : // Count manipulators
320 : void AddSizes(const PkgIterator &Pkg,signed long Mult = 1);
321 : inline void RemoveSizes(const PkgIterator &Pkg) {AddSizes(Pkg,-1);};
322 : void AddStates(const PkgIterator &Pkg,int Add = 1);
323 : inline void RemoveStates(const PkgIterator &Pkg) {AddStates(Pkg,-1);};
324 :
325 : public:
326 :
327 : // Legacy.. We look like a pkgCache
328 : inline operator pkgCache &() {return *Cache;};
329 : inline Header &Head() {return *Cache->HeaderP;};
330 : inline PkgIterator PkgBegin() {return Cache->PkgBegin();};
331 : inline PkgIterator FindPkg(string const &Name) {return Cache->FindPkg(Name);};
332 :
333 : inline pkgCache &GetCache() {return *Cache;};
334 : inline pkgVersioningSystem &VS() {return *Cache->VS;};
335 :
336 : // Policy implementation
337 : inline VerIterator GetCandidateVer(PkgIterator Pkg) {return LocalPolicy->GetCandidateVer(Pkg);};
338 : inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);};
339 : inline Policy &GetPolicy() {return *LocalPolicy;};
340 :
341 : // Accessors
342 3787 : inline StateCache &operator [](PkgIterator const &I) {return PkgState[I->ID];};
343 : inline unsigned char &operator [](DepIterator const &I) {return DepState[I->ID];};
344 :
345 : /** \return A function identifying packages in the root set other
346 : * than manually installed packages and essential packages, or \b
347 : * NULL if an error occurs.
348 : *
349 : * \todo Is this the best place for this function? Perhaps the
350 : * settings for mark-and-sweep should be stored in a single
351 : * external class?
352 : */
353 : virtual InRootSetFunc *GetRootSetFunc();
354 :
355 : /** \return \b true if the garbage collector should follow recommendations.
356 : */
357 : virtual bool MarkFollowsRecommends();
358 :
359 : /** \return \b true if the garbage collector should follow suggestions.
360 : */
361 : virtual bool MarkFollowsSuggests();
362 :
363 : /** \brief Update the Marked and Garbage fields of all packages.
364 : *
365 : * This routine is implicitly invoked after all state manipulators
366 : * and when an ActionGroup is destroyed. It invokes #MarkRequired
367 : * and #Sweep to do its dirty work.
368 : *
369 : * \param rootFunc A predicate that returns \b true for packages
370 : * that should be added to the root set.
371 : */
372 : bool MarkAndSweep(InRootSetFunc &rootFunc)
373 : {
374 : return MarkRequired(rootFunc) && Sweep();
375 : }
376 :
377 : bool MarkAndSweep()
378 : {
379 : std::auto_ptr<InRootSetFunc> f(GetRootSetFunc());
380 : if(f.get() != NULL)
381 : return MarkAndSweep(*f.get());
382 : else
383 : return false;
384 : }
385 :
386 : /** \name State Manipulators
387 : */
388 : // @{
389 : void MarkKeep(PkgIterator const &Pkg, bool Soft = false,
390 : bool FromUser = true);
391 : void MarkDelete(PkgIterator const &Pkg,bool Purge = false);
392 : void MarkInstall(PkgIterator const &Pkg,bool AutoInst = true,
393 : unsigned long Depth = 0, bool FromUser = true,
394 : bool ForceImportantDeps = false);
395 : void SetReInstall(PkgIterator const &Pkg,bool To);
396 : void SetCandidateVersion(VerIterator TargetVer);
397 :
398 : /** Set the "is automatically installed" flag of Pkg. */
399 : void MarkAuto(const PkgIterator &Pkg, bool Auto);
400 : // @}
401 :
402 : // This is for debuging
403 : void Update(OpProgress *Prog = 0);
404 :
405 : // read persistent states
406 : bool readStateFile(OpProgress *prog);
407 : bool writeStateFile(OpProgress *prog, bool InstalledOnly=false);
408 :
409 : // Size queries
410 : inline double UsrSize() {return iUsrSize;};
411 : inline double DebSize() {return iDownloadSize;};
412 : inline unsigned long DelCount() {return iDelCount;};
413 : inline unsigned long KeepCount() {return iKeepCount;};
414 : inline unsigned long InstCount() {return iInstCount;};
415 : inline unsigned long BrokenCount() {return iBrokenCount;};
416 : inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;};
417 : inline unsigned long BadCount() {return iBadCount;};
418 :
419 : bool Init(OpProgress *Prog);
420 :
421 : pkgDepCache(pkgCache *Cache,Policy *Plcy = 0);
422 : virtual ~pkgDepCache();
423 : };
424 :
425 : #endif
|