]>
git.saurik.com Git - apt.git/blob - apt-pkg/algorithms.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: algorithms.cc,v 1.3 1998/07/12 23:58:20 jgg Exp $
4 /* ######################################################################
6 Algorithms - A set of misc algorithms
8 ##################################################################### */
10 // Include Files /*{{{*/
12 #pragma implementation "apt-pkg/algorithms.h"
14 #include <apt-pkg/algorithms.h>
15 #include <apt-pkg/error.h>
19 pkgProblemResolver
*pkgProblemResolver::This
= 0;
21 // Simulate::Simulate - Constructor /*{{{*/
22 // ---------------------------------------------------------------------
24 pkgSimulate::pkgSimulate(pkgDepCache
&Cache
) : pkgPackageManager(Cache
),
27 Flags
= new unsigned char[Cache
.HeaderP
->PackageCount
];
28 memset(Flags
,0,sizeof(*Flags
)*Cache
.HeaderP
->PackageCount
);
31 // Simulate::Install - Simulate unpacking of a package /*{{{*/
32 // ---------------------------------------------------------------------
34 bool pkgSimulate::Install(PkgIterator iPkg
,string
/*File*/)
37 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
40 cout
<< "Inst " << Pkg
.Name();
41 Sim
.MarkInstall(Pkg
,false);
43 // Look for broken conflicts+predepends.
44 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
46 if (Sim
[I
].InstallVer
== 0)
49 for (DepIterator D
= Sim
[I
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
50 if (D
->Type
== pkgCache::Dep::Conflicts
|| D
->Type
== pkgCache::Dep::PreDepends
)
52 if ((Sim
[D
] & pkgDepCache::DepInstall
) == 0)
54 cout
<< " [" << I
.Name() << " on " << D
.TargetPkg().Name() << ']';
55 if (D
->Type
== pkgCache::Dep::Conflicts
)
56 _error
->Error("Fatal, conflicts violated %s",I
.Name());
61 if (Sim
.BrokenCount() != 0)
68 // Simulate::Configure - Simulate configuration of a Package /*{{{*/
69 // ---------------------------------------------------------------------
70 /* This is not an acurate simulation of relatity, we should really not
71 install the package.. For some investigations it may be necessary
73 bool pkgSimulate::Configure(PkgIterator iPkg
)
76 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
79 // Sim.MarkInstall(Pkg,false);
80 if (Sim
[Pkg
].InstBroken() == true)
82 cout
<< "Conf " << Pkg
.Name() << " broken" << endl
;
86 // Print out each package and the failed dependencies
87 for (pkgCache::DepIterator D
= Sim
[Pkg
].InstVerIter(Sim
).DependsList(); D
.end() == false; D
++)
89 if (Sim
.IsImportantDep(D
) == false ||
90 (Sim
[D
] & pkgDepCache::DepInstall
) != 0)
93 if (D
->Type
== pkgCache::Dep::Conflicts
)
94 cout
<< " Conflicts:" << D
.TargetPkg().Name();
96 cout
<< " Depends:" << D
.TargetPkg().Name();
100 _error
->Error("Conf Broken %s",Pkg
.Name());
103 cout
<< "Conf " << Pkg
.Name();
105 if (Sim
.BrokenCount() != 0)
113 // Simulate::Remove - Simulate the removal of a package /*{{{*/
114 // ---------------------------------------------------------------------
116 bool pkgSimulate::Remove(PkgIterator iPkg
)
118 // Adapt the iterator
119 PkgIterator Pkg
= Sim
.FindPkg(iPkg
.Name());
123 cout
<< "Remv " << Pkg
.Name();
125 if (Sim
.BrokenCount() != 0)
133 // Simulate::ShortBreaks - Print out a short line describing all breaks /*{{{*/
134 // ---------------------------------------------------------------------
136 void pkgSimulate::ShortBreaks()
139 for (PkgIterator I
= Sim
.PkgBegin(); I
.end() == false; I
++)
141 if (Sim
[I
].InstBroken() == true)
143 if (Flags
[I
->ID
] == 0)
144 cout
<< I
.Name() << ' ';
146 cout << I.Name() << "! ";*/
152 // ApplyStatus - Adjust for non-ok packages /*{{{*/
153 // ---------------------------------------------------------------------
154 /* We attempt to change the state of the all packages that have failed
155 installation toward their real state. The ordering code will perform
156 the necessary calculations to deal with the problems. */
157 bool pkgApplyStatus(pkgDepCache
&Cache
)
159 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
161 switch (I
->CurrentState
)
163 // This means installation failed somehow
164 case pkgCache::State::UnPacked
:
165 case pkgCache::State::HalfConfigured
:
169 // This means removal failed
170 case pkgCache::State::HalfInstalled
:
175 if (I
->InstState
!= pkgCache::State::Ok
)
176 return _error
->Error("The package %s is not ok and I "
177 "don't know how to fix it!",I
.Name());
183 // FixBroken - Fix broken packages /*{{{*/
184 // ---------------------------------------------------------------------
185 /* This autoinstalls every broken package and then runs ScoredFix on the
187 bool pkgFixBroken(pkgDepCache
&Cache
)
189 // Auto upgrade all broken packages
190 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
191 if (Cache
[I
].NowBroken() == true)
192 Cache
.MarkInstall(I
,true);
194 /* Fix packages that are in a NeedArchive state but don't have a
195 downloadable install version */
196 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
198 if (I
.State() != pkgCache::PkgIterator::NeedsUnpack
||
199 Cache
[I
].Delete() == true)
202 if (Cache
[I
].InstVerIter(Cache
).Downloadable() == false)
205 Cache
.MarkInstall(I
,true);
208 pkgProblemResolver
Fix(Cache
);
209 return Fix
.Resolve(true);
212 // DistUpgrade - Distribution upgrade /*{{{*/
213 // ---------------------------------------------------------------------
214 /* This autoinstalls every package and then force installs every
215 pre-existing package. This creates the initial set of conditions which
216 most likely contain problems because too many things were installed.
218 ScoredFix is used to resolve the problems.
220 bool pkgDistUpgrade(pkgDepCache
&Cache
)
222 /* Auto upgrade all installed packages, this provides the basis
223 for the installation */
224 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
225 if (I
->CurrentVer
!= 0)
226 Cache
.MarkInstall(I
,true);
228 /* Now, auto upgrade all essential packages - this ensures that
229 the essential packages are present and working */
230 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
231 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
232 Cache
.MarkInstall(I
,true);
234 /* We do it again over all previously installed packages to force
235 conflict resolution on them all. */
236 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
237 if (I
->CurrentVer
!= 0)
238 Cache
.MarkInstall(I
,false);
240 pkgProblemResolver
Fix(Cache
);
242 // Hold back held packages.
243 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
245 if (I
->SelectedState
== pkgCache::State::Hold
)
252 return Fix
.Resolve();
256 // ProblemResolver::pkgProblemResolver - Constructor /*{{{*/
257 // ---------------------------------------------------------------------
259 pkgProblemResolver::pkgProblemResolver(pkgDepCache
&Cache
) : Cache(Cache
)
262 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
263 Scores
= new signed short[Size
];
264 Flags
= new unsigned char[Size
];
265 memset(Flags
,0,sizeof(*Flags
)*Size
);
267 // Set debug to true to see its decision logic
271 // ProblemResolver::ScoreSort - Sort the list by score /*{{{*/
272 // ---------------------------------------------------------------------
274 int pkgProblemResolver::ScoreSort(const void *a
,const void *b
)
276 Package
const **A
= (Package
const **)a
;
277 Package
const **B
= (Package
const **)b
;
278 if (This
->Scores
[(*A
)->ID
] > This
->Scores
[(*B
)->ID
])
280 if (This
->Scores
[(*A
)->ID
] < This
->Scores
[(*B
)->ID
])
285 // ProblemResolver::MakeScores - Make the score table /*{{{*/
286 // ---------------------------------------------------------------------
288 void pkgProblemResolver::MakeScores()
290 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
291 memset(Scores
,0,sizeof(*Scores
)*Size
);
293 // Generate the base scores for a package based on its properties
294 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
296 if (Cache
[I
].InstallVer
== 0)
299 signed short &Score
= Scores
[I
->ID
];
301 /* This is arbitary, it should be high enough to elevate an
302 essantial package above most other packages but low enough
303 to allow an obsolete essential packages to be removed by
304 a conflicts on a powerfull normal package (ie libc6) */
305 if ((I
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
308 // We transform the priority
309 // Important Required Standard Optional Extra
310 signed short PrioMap
[] = {0,3,2,1,-1,-2};
311 if (Cache
[I
].InstVerIter(Cache
)->Priority
<= 5)
312 Score
+= PrioMap
[Cache
[I
].InstVerIter(Cache
)->Priority
];
314 /* This helps to fix oddball problems with conflicting packages
315 on the same level. We enhance the score of installed packages */
316 if (I
->CurrentVer
!= 0)
320 // Now that we have the base scores we go and propogate dependencies
321 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
323 if (Cache
[I
].InstallVer
== 0)
326 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false; D
++)
328 if (D
->Type
== pkgCache::Dep::Depends
|| D
->Type
== pkgCache::Dep::PreDepends
)
329 Scores
[D
.TargetPkg()->ID
]++;
333 // Copy the scores to advoid additive looping
334 signed short *OldScores
= new signed short[Size
];
335 memcpy(OldScores
,Scores
,sizeof(*Scores
)*Size
);
337 /* Now we cause 1 level of dependency inheritance, that is we add the
338 score of the packages that depend on the target Package. This
339 fortifies high scoring packages */
340 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
342 if (Cache
[I
].InstallVer
== 0)
345 for (pkgCache::DepIterator D
= I
.RevDependsList(); D
.end() == false; D
++)
347 // Only do it for the install version
348 if ((pkgCache::Version
*)D
.ParentVer() != Cache
[D
.ParentPkg()].InstallVer
||
349 (D
->Type
!= pkgCache::Dep::Depends
&& D
->Type
!= pkgCache::Dep::PreDepends
))
352 Scores
[I
->ID
] += abs(OldScores
[D
.ParentPkg()->ID
]);
356 /* Now we propogate along provides. This makes the packages that
357 provide important packages extremely important */
358 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
360 for (pkgCache::PrvIterator P
= I
.ProvidesList(); P
.end() == false; P
++)
362 // Only do it once per package
363 if ((pkgCache::Version
*)P
.OwnerVer() != Cache
[P
.OwnerPkg()].InstallVer
)
365 Scores
[P
.OwnerPkg()->ID
] += abs(Scores
[I
->ID
] - OldScores
[I
->ID
]);
369 /* Protected things are pushed really high up. This number should put them
370 ahead of everything */
371 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
372 if ((Flags
[I
->ID
] & Protected
) != 0)
373 Scores
[I
->ID
] += 10000;
378 // ProblemResolver::DoUpgrade - Attempt to upgrade this package /*{{{*/
379 // ---------------------------------------------------------------------
380 /* This goes through and tries to reinstall packages to make this package
382 bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg
)
384 if ((Flags
[Pkg
->ID
] & Upgradable
) == 0 || Cache
[Pkg
].Upgradable() == false)
386 Flags
[Pkg
->ID
] &= ~Upgradable
;
388 bool WasKept
= Cache
[Pkg
].Keep();
389 Cache
.MarkInstall(Pkg
,false);
391 // Isolate the problem dependency
393 for (pkgCache::DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
395 // Compute a single dependency element (glob or)
396 pkgCache::DepIterator Start
= D
;
397 pkgCache::DepIterator End
= D
;
398 unsigned char State
= 0;
399 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
402 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
407 // We only worry about critical deps.
408 if (End
.IsCritical() != true)
412 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
415 // Hm, the group is broken.. I have no idea how to handle this
418 cout
<< "Note, a broken or group was found in " << Pkg
.Name() << "." << endl
;
423 // Upgrade the package if the candidate version will fix the problem.
424 if ((Cache
[Start
] & pkgDepCache::DepCVer
) == pkgDepCache::DepCVer
)
426 PkgIterator P
= Start
.SmartTargetPkg();
427 if (DoUpgrade(P
) == false)
430 cout
<< " Reinst Failed because of " << P
.Name() << endl
;
437 /* We let the algorithm deal with conflicts on its next iteration,
438 it is much smarter than us */
439 if (End
->Type
== pkgCache::Dep::Conflicts
)
443 cout
<< " Reinst Failed early because of " << Start
.TargetPkg().Name() << endl
;
449 // Undo our operations - it might be smart to undo everything this did..
455 Cache
.MarkDelete(Pkg
);
460 cout
<< " Re-Instated " << Pkg
.Name() << endl
;
464 // ProblemResolver::Resolve - Run the resolution pass /*{{{*/
465 // ---------------------------------------------------------------------
466 /* This routines works by calculating a score for each package. The score
467 is derived by considering the package's priority and all reverse
468 dependents giving an integer that reflects the amount of breakage that
469 adjusting the package will inflict.
471 It goes from highest score to lowest and corrects all of the breaks by
472 keeping or removing the dependant packages. If that fails then it removes
473 the package itself and goes on. The routine should be able to intelligently
474 go from any broken state to a fixed state.
476 The BrokenFix flag enables a mode where the algorithm tries to
477 upgrade packages to advoid problems. */
478 bool pkgProblemResolver::Resolve(bool BrokenFix
)
480 unsigned long Size
= Cache
.HeaderP
->PackageCount
;
482 // Record which packages are marked for install
487 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
489 if (Cache
[I
].Install() == true)
490 Flags
[I
->ID
] |= PreInstalled
;
493 if (Cache
[I
].InstBroken() == true && BrokenFix
== true)
495 Cache
.MarkInstall(I
,false);
496 if (Cache
[I
].Install() == true)
500 Flags
[I
->ID
] &= ~PreInstalled
;
502 Flags
[I
->ID
] |= Upgradable
;
505 while (Again
== true);
508 cout
<< "Starting" << endl
;
512 /* We have to order the packages so that the broken fixing pass
513 operates from highest score to lowest. This prevents problems when
514 high score packages cause the removal of lower score packages that
515 would cause the removal of even lower score packages. */
516 pkgCache::Package
**PList
= new pkgCache::Package
*[Size
];
517 pkgCache::Package
**PEnd
= PList
;
518 for (pkgCache::PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
521 qsort(PList
,PEnd
- PList
,sizeof(*PList
),&ScoreSort
);
523 /* for (pkgCache::Package **K = PList; K != PEnd; K++)
524 if (Scores[(*K)->ID] != 0)
526 pkgCache::PkgIterator Pkg(Cache,*K);
527 cout << Scores[(*K)->ID] << ' ' << Pkg.Name() <<
528 ' ' << (pkgCache::Version *)Pkg.CurrentVer() << ' ' <<
529 Cache[Pkg].InstallVer << ' ' << Cache[Pkg].CandidateVer << endl;
533 cout
<< "Starting 2" << endl
;
535 /* Now consider all broken packages. For each broken package we either
536 remove the package or fix it's problem. We do this once, it should
537 not be possible for a loop to form (that is a < b < c and fixing b by
538 changing a breaks c) */
540 for (int Counter
= 0; Counter
!= 10 && Change
== true; Counter
++)
543 for (pkgCache::Package
**K
= PList
; K
!= PEnd
; K
++)
545 pkgCache::PkgIterator
I(Cache
,*K
);
547 /* We attempt to install this and see if any breaks result,
548 this takes care of some strange cases */
549 if (Cache
[I
].CandidateVer
!= Cache
[I
].InstallVer
&&
550 I
->CurrentVer
!= 0 && Cache
[I
].InstallVer
!= 0 &&
551 (Flags
[I
->ID
] & PreInstalled
) != 0 &&
552 (Flags
[I
->ID
] & Protected
) == 0)
555 cout
<< " Try to Re-Instate " << I
.Name() << endl
;
556 int OldBreaks
= Cache
.BrokenCount();
557 pkgCache::Version
*OldVer
= Cache
[I
].InstallVer
;
559 Cache
.MarkInstall(I
,false);
560 if (Cache
[I
].InstBroken() == true ||
561 OldBreaks
< Cache
.BrokenCount())
570 cout
<< "Re-Instated " << I
.Name() << endl
;
573 if (Cache
[I
].InstallVer
== 0 || Cache
[I
].InstBroken() == false)
576 // Isolate the problem dependency
577 PackageKill KillList
[100];
578 PackageKill
*LEnd
= KillList
;
579 for (pkgCache::DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
581 // Compute a single dependency element (glob or)
582 pkgCache::DepIterator Start
= D
;
583 pkgCache::DepIterator End
= D
;
584 unsigned char State
= 0;
585 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
588 LastOR
= (D
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
;
593 // We only worry about critical deps.
594 if (End
.IsCritical() != true)
598 if ((Cache
[End
] & pkgDepCache::DepGInstall
) == pkgDepCache::DepGInstall
)
601 // Hm, the group is broken.. I have no idea how to handle this
604 cout
<< "Note, a broken or group was found in " << I
.Name() << "." << endl
;
610 cout
<< "Package " << I
.Name() << " has broken dep on " << End
.TargetPkg().Name() << endl
;
612 /* Conflicts is simple, decide if we should remove this package
613 or the conflicted one */
614 pkgCache::Version
**VList
= End
.AllTargets();
616 for (pkgCache::Version
**V
= VList
; *V
!= 0; V
++)
618 pkgCache::VerIterator
Ver(Cache
,*V
);
619 pkgCache::PkgIterator Pkg
= Ver
.ParentPkg();
622 cout
<< " Considering " << Pkg
.Name() << ' ' << (int)Scores
[Pkg
->ID
] <<
623 " as a solution to " << I
.Name() << ' ' << (int)Scores
[I
->ID
] << endl
;
624 if (Scores
[I
->ID
] <= Scores
[Pkg
->ID
] ||
625 ((Cache
[End
] & pkgDepCache::DepGNow
) == 0 &&
626 End
->Type
!= pkgCache::Dep::Conflicts
))
628 if ((Flags
[I
->ID
] & Protected
) != 0)
631 // See if a keep will do
633 if (Cache
[I
].InstBroken() == false)
636 cout
<< " Holding Back " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
640 if (BrokenFix
== false || DoUpgrade(I
) == false)
643 cout
<< " Removing " << I
.Name() << " rather than change " << End
.TargetPkg().Name() << endl
;
646 Scores
[I
->ID
] = Scores
[Pkg
->ID
];
656 // Skip this if it is protected
657 if ((Flags
[Pkg
->ID
] & Protected
) != 0)
663 if (End
->Type
!= pkgCache::Dep::Conflicts
)
668 // Hm, nothing can possibly satisify this dep. Nuke it.
669 if (VList
[0] == 0 && End
->Type
!= pkgCache::Dep::Conflicts
)
672 if (Cache
[I
].InstBroken() == false)
675 cout
<< " Holding Back " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
680 cout
<< " Removing " << I
.Name() << " because I can't find " << End
.TargetPkg().Name() << endl
;
693 // Apply the kill list now
694 if (Cache
[I
].InstallVer
!= 0)
695 for (PackageKill
*J
= KillList
; J
!= LEnd
; J
++)
698 if ((Cache
[J
->Dep
] & pkgDepCache::DepGNow
) == 0)
700 if (J
->Dep
->Type
== pkgCache::Dep::Conflicts
)
703 cout
<< " Fixing " << I
.Name() << " via remove of " << J
->Pkg
.Name() << endl
;
704 Cache
.MarkDelete(J
->Pkg
);
710 cout
<< " Fixing " << I
.Name() << " via keep of " << J
->Pkg
.Name() << endl
;
711 Cache
.MarkKeep(J
->Pkg
);
715 Scores
[J
->Pkg
->ID
] = Scores
[I
->ID
];
721 cout
<< "Done" << endl
;
726 if (Cache
.BrokenCount() != 0)
727 return _error
->Error("Internal error, ScoredFix generated breaks.");