2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * SAT based dependency solver
29 #define RULES_BLOCK 63
30 #define REGARD_RECOMMENDS_OF_INSTALLED_ITEMS 0
34 solver_splitprovides(Solver *solv, Id dep)
36 Pool *pool = solv->pool;
41 if (!solv->dosplitprovides || !solv->installed)
45 rd = GETRELDEP(pool, dep);
46 if (rd->flags != REL_WITH)
48 FOR_PROVIDES(p, pp, dep)
50 s = pool->solvables + p;
51 if (s->repo == solv->installed && s->name == rd->name)
58 solver_dep_installed(Solver *solv, Id dep)
61 Pool *pool = solv->pool;
66 Reldep *rd = GETRELDEP(pool, dep);
67 if (rd->flags == REL_AND)
69 if (!solver_dep_installed(solv, rd->name))
71 return solver_dep_installed(solv, rd->evr);
73 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
74 return solver_dep_installed(solv, rd->evr);
76 FOR_PROVIDES(p, pp, dep)
78 if (p == SYSTEMSOLVABLE || (solv->installed && pool->solvables[p].repo == solv->installed))
86 /* this mirrors solver_dep_fulfilled but uses map m instead of the decisionmap */
88 dep_possible(Solver *solv, Id dep, Map *m)
90 Pool *pool = solv->pool;
95 Reldep *rd = GETRELDEP(pool, dep);
96 if (rd->flags == REL_AND)
98 if (!dep_possible(solv, rd->name, m))
100 return dep_possible(solv, rd->evr, m);
102 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_SPLITPROVIDES)
103 return solver_splitprovides(solv, rd->evr);
104 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
105 return solver_dep_installed(solv, rd->evr);
107 FOR_PROVIDES(p, pp, dep)
115 /*-----------------------------------------------------------------*/
122 printruleelement(Solver *solv, int type, Rule *r, Id v)
124 Pool *pool = solv->pool;
128 s = pool->solvables + -v;
129 POOL_DEBUG(type, " !%s [%d]", solvable2str(pool, s), -v);
133 s = pool->solvables + v;
134 POOL_DEBUG(type, " %s [%d]", solvable2str(pool, s), v);
139 POOL_DEBUG(type, " (w1)");
141 POOL_DEBUG(type, " (w2)");
143 if (solv->decisionmap[s - pool->solvables] > 0)
144 POOL_DEBUG(type, " Install.level%d", solv->decisionmap[s - pool->solvables]);
145 if (solv->decisionmap[s - pool->solvables] < 0)
146 POOL_DEBUG(type, " Conflict.level%d", -solv->decisionmap[s - pool->solvables]);
147 POOL_DEBUG(type, "\n");
156 printrule(Solver *solv, int type, Rule *r)
158 Pool *pool = solv->pool;
162 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
163 POOL_DEBUG(type, "Rule #%d:", (int)(r - solv->rules));
165 POOL_DEBUG(type, "Rule:"); /* r is any rule */
167 POOL_DEBUG(type, " (disabled)");
168 POOL_DEBUG(type, "\n");
172 /* print direct literal */
174 else if (r->d == ID_NULL)
178 /* binary rule --> print w2 as second literal */
182 /* every other which is in d */
183 v = solv->pool->whatprovidesdata[r->d + i - 1];
186 printruleelement(solv, type, r, v);
188 POOL_DEBUG(type, " next rules: %d %d\n", r->n1, r->n2);
192 printruleclass(Solver *solv, int type, Rule *r)
194 Pool *pool = solv->pool;
195 if (r - solv->rules >= solv->learntrules)
196 POOL_DEBUG(type, "LEARNT ");
197 else if (r - solv->rules >= solv->weakrules)
198 POOL_DEBUG(type, "WEAK ");
199 else if (r - solv->rules >= solv->systemrules)
200 POOL_DEBUG(type, "SYSTEM ");
201 else if (r - solv->rules >= solv->jobrules)
202 POOL_DEBUG(type, "JOB ");
203 printrule(solv, type, r);
207 /*-----------------------------------------------------------------*/
213 static Pool *unifyrules_sortcmp_data;
216 * compare rules for unification sort
220 unifyrules_sortcmp(const void *ap, const void *bp)
222 Pool *pool = unifyrules_sortcmp_data;
223 Rule *a = (Rule *)ap;
224 Rule *b = (Rule *)bp;
230 return x; /* p differs */
233 if (a->d == 0 && b->d == 0)
234 return a->w2 - b->w2; /* assertion: return w2 diff */
236 if (a->d == 0) /* a is assertion, b not */
238 x = a->w2 - pool->whatprovidesdata[b->d];
242 if (b->d == 0) /* b is assertion, a not */
244 x = pool->whatprovidesdata[a->d] - b->w2;
248 /* compare whatprovidesdata */
249 ad = pool->whatprovidesdata + a->d;
250 bd = pool->whatprovidesdata + b->d;
252 if ((x = *ad++ - *bd++) != 0)
263 unifyrules(Solver *solv)
265 Pool *pool = solv->pool;
269 if (solv->nrules <= 1) /* nothing to unify */
272 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- unifyrules -----\n");
274 /* sort rules first */
275 unifyrules_sortcmp_data = solv->pool;
276 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
283 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
285 if (jr && !unifyrules_sortcmp(ir, jr))
286 continue; /* prune! */
287 jr = solv->rules + j++; /* keep! */
292 /* reduced count from nrules to j rules */
293 POOL_DEBUG(SAT_DEBUG_STATS, "pruned rules from %d to %d\n", solv->nrules, j);
295 /* adapt rule buffer */
297 solv->rules = sat_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
298 IF_POOLDEBUG (SAT_DEBUG_STATS)
305 for (i = 1; i < solv->nrules; i++)
312 dp = solv->pool->whatprovidesdata + r->d;
317 POOL_DEBUG(SAT_DEBUG_STATS, " binary: %d\n", binr);
318 POOL_DEBUG(SAT_DEBUG_STATS, " normal: %d, %d literals\n", solv->nrules - 1 - binr, lits);
320 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- unifyrules end -----\n");
330 hashrule(Solver *solv, Id p, Id d, int n)
332 unsigned int x = (unsigned int)p;
336 return (x * 37) ^ (unsigned int)d;
337 dp = solv->pool->whatprovidesdata + d;
339 x = (x * 37) ^ (unsigned int)*dp++;
347 * p = direct literal; always < 0 for installed rpm rules
348 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
351 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
353 * p < 0 : pkg id of A
354 * d > 0 : Offset in whatprovidesdata (list of providers of b)
356 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
357 * p < 0 : pkg id of A
358 * d < 0 : Id of solvable (e.g. B1)
360 * d == 0: unary rule, assertion => (A) or (-A)
362 * Install: p > 0, d = 0 (A) user requested install
363 * Remove: p < 0, d = 0 (-A) user requested remove
364 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
365 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
366 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider) (binary rule)
367 * ? p > 0, d < 0 (A|-B)
368 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
372 * Direct assertion (no watch needed)( if d <0 ) --> d = 0, w1 = p, w2 = 0
373 * Binary rule: p = first literal, d = 0, w2 = second literal, w1 = p
374 * every other : w1 = p, w2 = whatprovidesdata[d];
375 * Disabled rule: w1 = 0
377 * always returns a rule for non-rpm rules
381 addrule(Solver *solv, Id p, Id d)
383 Pool *pool = solv->pool;
387 int n = 0; /* number of literals in rule - 1
388 0 = direct assertion (single literal)
392 /* it often happenes that requires lead to adding the same rpm rule
393 * multiple times, so we prune those duplicates right away to make
394 * the work for unifyrules a bit easier */
396 if (solv->nrules && !solv->jobrules)
398 r = solv->rules + solv->nrules - 1; /* get the last added rule */
399 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
405 /* always a binary rule */
407 return 0; /* ignore self conflict */
412 for (dp = pool->whatprovidesdata + d; *dp; dp++, n++)
414 return 0; /* rule is self-fulfilling */
416 d = dp[-1]; /* take single literal */
419 if (n == 0 && !solv->jobrules)
421 /* this is a rpm rule assertion, we do not have to allocate it */
422 /* it can be identified by a level of 1 and a zero reason */
423 /* we must not drop those rules from the decisionq when rewinding! */
425 assert(solv->decisionmap[-p] == 0 || solv->decisionmap[-p] == -1);
426 if (solv->decisionmap[-p])
427 return 0; /* already got that one */
428 queue_push(&solv->decisionq, p);
429 queue_push(&solv->decisionq_why, 0);
430 solv->decisionmap[-p] = -1;
435 /* smallest literal first so we can find dups */
439 n = 1; /* re-set n, was used as temp var */
442 /* check if the last added rule is exactly the same as what we're looking for. */
443 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
444 return r; /* binary rule */
446 if (r && n > 1 && r->d && r->p == p)
448 /* Rule where d is an offset in whatprovidesdata */
452 dp2 = pool->whatprovidesdata + r->d;
453 for (dp = pool->whatprovidesdata + d; *dp; dp++, dp2++)
464 /* extend rule buffer */
465 solv->rules = sat_extend(solv->rules, solv->nrules, 1, sizeof(Rule), RULES_BLOCK);
466 r = solv->rules + solv->nrules++; /* point to rule space */
471 /* direct assertion, no watch needed */
487 r->w2 = pool->whatprovidesdata[d];
492 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
494 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, " Add rule: ");
495 printrule(solv, SAT_DEBUG_RULE_CREATION, r);
502 disablerule(Solver *solv, Rule *r)
508 enablerule(Solver *solv, Rule *r)
510 if (r->d == 0 || r->w2 != r->p)
513 r->w1 = solv->pool->whatprovidesdata[r->d];
517 /**********************************************************************************/
519 /* a problem is an item on the solver's problem list. It can either be >0, in that
520 * case it is a system (upgrade) rule, or it can be <0, which makes it refer to a job
521 * consisting of multiple job rules.
525 disableproblem(Solver *solv, Id v)
533 disablerule(solv, solv->rules + v);
537 jp = solv->ruletojob.elements;
538 for (i = solv->jobrules, r = solv->rules + i; i < solv->systemrules; i++, r++, jp++)
540 disablerule(solv, r);
544 enableproblem(Solver *solv, Id v)
552 enablerule(solv, solv->rules + v);
556 jp = solv->ruletojob.elements;
557 for (i = solv->jobrules, r = solv->rules + i; i < solv->systemrules; i++, r++, jp++)
563 printproblem(Solver *solv, Id v)
565 Pool *pool = solv->pool;
571 printrule(solv, SAT_DEBUG_SOLUTIONS, solv->rules + v);
575 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "JOB %d\n", v);
576 jp = solv->ruletojob.elements;
577 for (i = solv->jobrules, r = solv->rules + i; i < solv->systemrules; i++, r++, jp++)
580 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "- ");
581 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
583 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "ENDJOB\n");
589 /************************************************************************/
591 /* go through system and job rules and add direct assertions
592 * to the decisionqueue. If we find a conflict, disable rules and
593 * add them to problem queue.
596 makeruledecisions(Solver *solv)
598 Pool *pool = solv->pool;
604 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- makeruledecisions ; size decisionq: %d -----\n",solv->decisionq.count);
606 decisionstart = solv->decisionq.count;
608 /* FIXME: For the time being we first need to assert what we can get
609 from learned rules. Currently it can happen that we learn a unit
610 rule (i.e. assertion) in direct conflict with e.g. a job unit rule. The
611 input problem was unsolvable, but we can't deal with this situation
612 of two conflicting assertions (see also FIXME at refine_suggestion).
614 What normally would happen (without this loop), we would first see the
615 job rule (and let's say decide to install A), and later see the learned
616 rule (which says don't install A), have a conflict, and assert, because
617 we don't ever expect to see conflicts with learned rules.
619 So we gather assertions from learned rules first. This then leads
620 to a conflict with a job rule, which is dealt with (mostly). We note
621 that job rule as a problem (and don't remember the learned rule as a
622 problem like we would normally do, as even other code doesn't expect to
623 see learned rules in problem descriptions.
625 We need to deal with this situation in a better way, preferably by
626 never learning unit rules in conflicts with any other unit rule. */
628 for (ri = solv->learntrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
630 if (!r->w1 || r->w2) /* disabled or no assertion */
634 if (solv->decisionmap[vv] == 0)
636 queue_push(&solv->decisionq, v);
637 queue_push(&solv->decisionq_why, r - solv->rules);
638 solv->decisionmap[vv] = v > 0 ? 1 : -1;
639 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
641 Solvable *s = solv->pool->solvables + vv;
643 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "conflicting %s (assertion)\n", solvable2str(solv->pool, s));
645 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "installing %s (assertion)\n", solvable2str(solv->pool, s));
649 if (v > 0 && solv->decisionmap[vv] > 0)
651 if (v < 0 && solv->decisionmap[vv] < 0)
653 /* found a conflict, which can't happen with learned rules. */
657 /* rpm rules don't have assertions, so we can start with the job
659 for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
661 if (!r->w1 || r->w2) /* disabled or no assertion */
665 if (solv->decisionmap[vv] == 0)
667 queue_push(&solv->decisionq, v);
668 queue_push(&solv->decisionq_why, r - solv->rules);
669 solv->decisionmap[vv] = v > 0 ? 1 : -1;
670 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
672 Solvable *s = solv->pool->solvables + vv;
674 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "conflicting %s (assertion)\n", solvable2str(solv->pool, s));
676 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "installing %s (assertion)\n", solvable2str(solv->pool, s));
680 if (v > 0 && solv->decisionmap[vv] > 0)
682 if (v < 0 && solv->decisionmap[vv] < 0)
684 /* found a conflict! */
685 /* ri >= learntrules cannot happen, as this would mean that the
686 * problem was not solvable, so we wouldn't have created the
687 * learnt rule at all */
688 assert(ri < solv->learntrules);
689 /* if we are weak, just disable ourself */
690 if (ri >= solv->weakrules)
692 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "assertion conflict, but I am weak, disabling ");
693 printrule(solv, SAT_DEBUG_UNSOLVABLE, r);
694 disablerule(solv, r);
698 /* only job and system rules left in the decisionq*/
699 /* find the decision which is the "opposite" of the jobrule */
700 for (i = 0; i < solv->decisionq.count; i++)
701 if (solv->decisionq.elements[i] == -v)
703 assert(i < solv->decisionq.count);
704 if (solv->decisionq_why.elements[i] == 0)
706 /* conflict with rpm rule, need only disable our rule */
707 assert(v > 0 || v == -SYSTEMSOLVABLE);
709 queue_push(&solv->problems, solv->learnt_pool.count);
710 queue_push(&solv->learnt_pool, ri);
711 queue_push(&solv->learnt_pool, v != -SYSTEMSOLVABLE ? -v : v);
712 queue_push(&solv->learnt_pool, 0);
713 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "conflict with rpm rule, disabling rule #%d\n", ri);
714 if (ri < solv->systemrules)
715 v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1);
718 queue_push(&solv->problems, v);
719 queue_push(&solv->problems, 0);
720 disableproblem(solv, v);
724 /* conflict with another job or system rule */
726 queue_push(&solv->problems, solv->learnt_pool.count);
727 queue_push(&solv->learnt_pool, ri);
728 queue_push(&solv->learnt_pool, solv->decisionq_why.elements[i]);
729 queue_push(&solv->learnt_pool, 0);
731 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "conflicting system/job assertions over literal %d\n", vv);
732 /* push all of our rules asserting this literal on the problem stack */
733 for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
735 if (!rr->w1 || rr->w2)
737 if (rr->p != vv && rr->p != -vv)
739 /* See the large comment in front of the very first loop in this
740 function at FIXME. */
741 if (i >= solv->learntrules)
743 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i);
745 if (i < solv->systemrules)
746 v = -(solv->ruletojob.elements[i - solv->jobrules] + 1);
747 queue_push(&solv->problems, v);
748 disableproblem(solv, v);
750 queue_push(&solv->problems, 0);
753 while (solv->decisionq.count > decisionstart)
755 v = solv->decisionq.elements[--solv->decisionq.count];
756 --solv->decisionq_why.count;
758 solv->decisionmap[vv] = 0;
760 ri = solv->jobrules - 1;
761 r = solv->rules + ri;
764 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- makeruledecisions end; size decisionq: %d -----\n",solv->decisionq.count);
768 * we have enabled or disabled some of our rules. We now reenable all
769 * of our learnt rules but the ones that were learnt from rules that
773 enabledisablelearntrules(Solver *solv)
775 Pool *pool = solv->pool;
780 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "enabledisablelearntrules called\n");
781 for (i = solv->learntrules, r = solv->rules + i; i < solv->nrules; i++, r++)
783 whyp = solv->learnt_pool.elements + solv->learnt_why.elements[i - solv->learntrules];
784 while ((why = *whyp++) != 0)
787 continue; /* rpm assertion */
789 if (!solv->rules[why].w1)
792 /* why != 0: we found a disabled rule, disable the learnt rule */
795 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
797 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "disabling learnt ");
798 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
800 disablerule(solv, r);
802 else if (!why && !r->w1)
804 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
806 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "re-enabling learnt ");
807 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
815 /* FIXME: bad code ahead, replace as soon as possible */
817 disableupdaterules(Solver *solv, Queue *job, int jobidx)
819 Pool *pool = solv->pool;
821 Id name, how, what, p, *pp;
827 installed = solv->installed;
833 how = job->elements[jobidx];
836 case SOLVER_INSTALL_SOLVABLE:
837 case SOLVER_ERASE_SOLVABLE:
838 case SOLVER_ERASE_SOLVABLE_NAME:
839 case SOLVER_ERASE_SOLVABLE_PROVIDES:
845 /* go through all enabled job rules */
846 MAPZERO(&solv->noupdate);
847 for (i = solv->jobrules; i < solv->systemrules; i++)
850 if (!r->w1) /* disabled? */
852 j = solv->ruletojob.elements[i - solv->jobrules];
856 how = job->elements[j];
857 what = job->elements[j + 1];
860 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
861 s = pool->solvables + what;
862 FOR_PROVIDES(p, pp, s->name)
864 if (pool->solvables[p].name != s->name)
866 if (pool->solvables[p].repo == installed)
867 MAPSET(&solv->noupdate, p - installed->start);
870 case SOLVER_ERASE_SOLVABLE:
871 s = pool->solvables + what;
872 if (s->repo == installed)
873 MAPSET(&solv->noupdate, what - installed->start);
875 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
876 case SOLVER_ERASE_SOLVABLE_PROVIDES:
877 name = (how == SOLVER_ERASE_SOLVABLE_NAME) ? what : 0;
878 while (ISRELDEP(name))
880 Reldep *rd = GETRELDEP(pool, name);
883 FOR_PROVIDES(p, pp, what)
885 if (name && pool->solvables[p].name != name)
887 if (pool->solvables[p].repo == installed)
888 MAPSET(&solv->noupdate, p - installed->start);
896 /* fixup update rule status */
897 if (solv->allowuninstall)
898 return; /* no update rules at all */
902 /* we just disabled job #jobidx. enable all update rules
903 * that aren't disabled by the remaining job rules */
904 how = job->elements[jobidx];
905 what = job->elements[jobidx + 1];
908 case SOLVER_INSTALL_SOLVABLE:
909 s = pool->solvables + what;
910 FOR_PROVIDES(p, pp, s->name)
912 if (pool->solvables[p].name != s->name)
914 if (pool->solvables[p].repo != installed)
916 if (MAPTST(&solv->noupdate, p - installed->start))
918 r = solv->rules + solv->systemrules + (p - installed->start);
922 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
924 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
925 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
929 case SOLVER_ERASE_SOLVABLE:
930 s = pool->solvables + what;
931 if (s->repo != installed)
933 if (MAPTST(&solv->noupdate, what - installed->start))
935 r = solv->rules + solv->systemrules + (what - installed->start);
939 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
941 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
942 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
945 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
946 case SOLVER_ERASE_SOLVABLE_PROVIDES:
947 name = (how == SOLVER_ERASE_SOLVABLE_NAME) ? what : 0;
948 while (ISRELDEP(name))
950 Reldep *rd = GETRELDEP(pool, name);
953 FOR_PROVIDES(p, pp, what)
955 if (name && pool->solvables[p].name != name)
957 if (pool->solvables[p].repo != installed)
959 if (MAPTST(&solv->noupdate, p - installed->start))
961 r = solv->rules + solv->systemrules + (p - installed->start);
965 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
967 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling ");
968 printrule(solv, SAT_DEBUG_SOLUTIONS, r);
978 for (i = 0; i < installed->nsolvables; i++)
980 r = solv->rules + solv->systemrules + i;
981 if (r->w1 && MAPTST(&solv->noupdate, i))
982 disablerule(solv, r); /* was enabled, need to disable */
988 addpatchatomrequires(Solver *solv, Solvable *s, Id *dp, Queue *q, Map *m)
990 Pool *pool = solv->pool;
991 Id fre, *frep, p, *pp, ndp;
997 queue_init_buffer(&fq, qbuf, sizeof(qbuf)/sizeof(*qbuf));
998 queue_push(&fq, -(s - pool->solvables));
1000 queue_push(&fq, *dp);
1001 ndp = pool_queuetowhatprovides(pool, &fq);
1002 frep = s->repo->idarraydata + s->freshens;
1003 while ((fre = *frep++) != 0)
1005 FOR_PROVIDES(p, pp, fre)
1007 ps = pool->solvables + p;
1008 addrule(solv, -p, ndp);
1016 for (i = 1; i < fq.count; i++)
1028 * add (install) rules for solvable
1029 * for unfulfilled requirements, conflicts, obsoletes,....
1030 * add a negative assertion for solvables that are not installable
1034 addrpmrulesforsolvable(Solver *solv, Solvable *s, Map *m)
1036 Pool *pool = solv->pool;
1037 Repo *installed = solv->installed;
1052 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforsolvable -----\n");
1054 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
1055 queue_push(&q, s - pool->solvables); /* push solvable Id */
1061 * s: Pointer to solvable
1064 n = queue_shift(&q);
1065 if (MAPTST(m, n)) /* continue if already done */
1069 s = pool->solvables + n; /* s = Solvable in question */
1072 if (installed /* Installed system available */
1073 && !solv->fixsystem /* NOT repair errors in rpm dependency graph */
1074 && s->repo == installed) /* solvable is installed? */
1076 dontfix = 1; /* dont care about broken rpm deps */
1079 if (!dontfix && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC && !pool_installable(pool, s))
1081 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "package %s [%d] is not installable\n", solvable2str(pool, s), (Id)(s - pool->solvables));
1082 addrule(solv, -n, 0); /* uninstallable */
1086 if (s->freshens && !s->supplements)
1088 const char *name = id2str(pool, s->name);
1089 if (name[0] == 'a' && !strncmp(name, "atom:", 5))
1093 /*-----------------------------------------
1094 * check requires of s
1099 reqp = s->repo->idarraydata + s->requires;
1100 while ((req = *reqp++) != 0) /* go throw all requires */
1102 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
1105 dp = pool_whatprovides(pool, req);
1107 if (*dp == SYSTEMSOLVABLE) /* always installed */
1113 addpatchatomrequires(solv, s, dp, &q, m);
1119 /* the strategy here is to not insist on dependencies
1120 * that are already broken. so if we find one provider
1121 * that was already installed, we know that the
1122 * dependency was not broken before so we enforce it */
1123 for (i = 0; (p = dp[i]) != 0; i++) /* for all providers */
1125 if (pool->solvables[p].repo == installed)
1126 break; /* provider was installed */
1128 if (!p) /* previously broken dependency */
1130 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "ignoring broken requires %s of installed package %s\n", dep2str(pool, req), solvable2str(pool, s));
1137 /* nothing provides req! */
1138 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", solvable2str(pool, s), (Id)(s - pool->solvables), dep2str(pool, req));
1139 addrule(solv, -n, 0); /* mark requestor as uninstallable */
1143 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
1145 POOL_DEBUG(SAT_DEBUG_RULE_CREATION," %s requires %s\n", solvable2str(pool, s), dep2str(pool, req));
1146 for (i = 0; dp[i]; i++)
1147 POOL_DEBUG(SAT_DEBUG_RULE_CREATION, " provided by %s\n", solvable2str(pool, pool->solvables + dp[i]));
1150 /* add 'requires' dependency */
1151 /* rule: (-requestor|provider1|provider2|...|providerN) */
1152 addrule(solv, -n, dp - pool->whatprovidesdata);
1154 /* descend the dependency tree */
1155 for (; *dp; dp++) /* loop through all providers */
1157 if (!MAPTST(m, *dp))
1158 queue_push(&q, *dp);
1161 } /* while, requirements of n */
1163 } /* if, requirements */
1165 /* that's all we check for src packages */
1166 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
1169 /*-----------------------------------------
1170 * check conflicts of s
1175 conp = s->repo->idarraydata + s->conflicts;
1176 while ((con = *conp++) != 0)
1178 FOR_PROVIDES(p, pp, con)
1180 /* dontfix: dont care about conflicts with already installed packs */
1181 if (dontfix && pool->solvables[p].repo == installed)
1183 /* rule: -n|-p: either solvable _or_ provider of conflict */
1184 addrule(solv, -n, -p);
1189 /*-----------------------------------------
1190 * check obsoletes if not installed
1192 if (!installed || pool->solvables[n].repo != installed)
1193 { /* not installed */
1196 obsp = s->repo->idarraydata + s->obsoletes;
1197 while ((obs = *obsp++) != 0)
1199 FOR_PROVIDES(p, pp, obs)
1200 addrule(solv, -n, -p);
1203 FOR_PROVIDES(p, pp, s->name)
1205 if (s->name == pool->solvables[p].name)
1206 addrule(solv, -n, -p);
1210 /*-----------------------------------------
1211 * add recommends to the rule list
1215 recp = s->repo->idarraydata + s->recommends;
1216 while ((rec = *recp++) != 0)
1218 FOR_PROVIDES(p, pp, rec)
1225 sugp = s->repo->idarraydata + s->suggests;
1226 while ((sug = *sugp++) != 0)
1228 FOR_PROVIDES(p, pp, sug)
1235 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforsolvable end -----\n");
1239 addrpmrulesforweak(Solver *solv, Map *m)
1241 Pool *pool = solv->pool;
1246 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforweak -----\n");
1247 for (i = n = 1; n < pool->nsolvables; i++, n++)
1249 if (i == pool->nsolvables)
1253 s = pool->solvables + i;
1254 if (!pool_installable(pool, s))
1259 supp = s->repo->idarraydata + s->supplements;
1260 while ((sup = *supp++) != ID_NULL)
1261 if (dep_possible(solv, sup, m))
1264 if (!sup && s->freshens)
1266 supp = s->repo->idarraydata + s->freshens;
1267 while ((sup = *supp++) != ID_NULL)
1268 if (dep_possible(solv, sup, m))
1271 if (!sup && s->enhances)
1273 supp = s->repo->idarraydata + s->enhances;
1274 while ((sup = *supp++) != ID_NULL)
1275 if (dep_possible(solv, sup, m))
1280 addrpmrulesforsolvable(solv, s, m);
1283 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforweak end -----\n");
1287 addrpmrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allowall)
1289 Pool *pool = solv->pool;
1294 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforupdaters -----\n");
1296 queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1297 policy_findupdatepackages(solv, s, &qs, allowall);
1298 if (!MAPTST(m, s - pool->solvables)) /* add rule for s if not already done */
1299 addrpmrulesforsolvable(solv, s, m);
1300 for (i = 0; i < qs.count; i++)
1301 if (!MAPTST(m, qs.elements[i]))
1302 addrpmrulesforsolvable(solv, pool->solvables + qs.elements[i], m);
1305 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addrpmrulesforupdaters -----\n");
1309 * add rule for update
1310 * (A|A1|A2|A3...) An = update candidates for A
1312 * s = (installed) solvable
1316 addupdaterule(Solver *solv, Solvable *s, int allowall)
1318 /* installed packages get a special upgrade allowed rule */
1319 Pool *pool = solv->pool;
1324 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule -----\n");
1326 queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1327 policy_findupdatepackages(solv, s, &qs, allowall);
1328 if (qs.count == 0) /* no updaters found */
1331 d = pool_queuetowhatprovides(pool, &qs); /* intern computed queue */
1333 addrule(solv, s - pool->solvables, d); /* allow update of s */
1334 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule end -----\n");
1338 /*-----------------------------------------------------------------*/
1347 printWatches(Solver *solv, int type)
1349 Pool *pool = solv->pool;
1352 POOL_DEBUG(type, "Watches: \n");
1354 for (counter = -(pool->nsolvables); counter <= pool->nsolvables; counter ++)
1356 POOL_DEBUG(type, " solvable [%d] -- rule [%d]\n", counter, solv->watches[counter+pool->nsolvables]);
1363 * initial setup for all watches
1367 makewatches(Solver *solv)
1371 int nsolvables = solv->pool->nsolvables;
1373 sat_free(solv->watches);
1374 /* lower half for removals, upper half for installs */
1375 solv->watches = sat_calloc(2 * nsolvables, sizeof(Id));
1377 /* do it reverse so rpm rules get triggered first */
1378 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1380 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1383 if (!r->w1 /* rule is disabled */
1384 || !r->w2) /* rule is assertion */
1387 /* see addwatches(solv, r) */
1388 r->n1 = solv->watches[nsolvables + r->w1];
1389 solv->watches[nsolvables + r->w1] = r - solv->rules;
1391 r->n2 = solv->watches[nsolvables + r->w2];
1392 solv->watches[nsolvables + r->w2] = r - solv->rules;
1398 * add watches (for rule)
1402 addwatches(Solver *solv, Rule *r)
1404 int nsolvables = solv->pool->nsolvables;
1406 r->n1 = solv->watches[nsolvables + r->w1];
1407 solv->watches[nsolvables + r->w1] = r - solv->rules;
1409 r->n2 = solv->watches[nsolvables + r->w2];
1410 solv->watches[nsolvables + r->w2] = r - solv->rules;
1414 /*-----------------------------------------------------------------*/
1415 /* rule propagation */
1417 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1422 * propagate decision to all rules
1423 * return : 0 = everything is OK
1424 * watched rule = there is a conflict
1428 propagate(Solver *solv, int level)
1430 Pool *pool = solv->pool;
1435 Id *decisionmap = solv->decisionmap;
1436 Id *watches = solv->watches + pool->nsolvables;
1438 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "----- propagate -----\n");
1440 while (solv->propagate_index < solv->decisionq.count)
1442 /* negate because our watches trigger if literal goes FALSE */
1443 pkg = -solv->decisionq.elements[solv->propagate_index++];
1444 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
1446 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "popagate for decision %d level %d\n", -pkg, level);
1447 printruleelement(solv, SAT_DEBUG_PROPAGATE, 0, -pkg);
1449 printWatches(solv, SAT_DEBUG_SCHUBI);
1452 for (rp = watches + pkg; *rp; rp = nrp)
1454 r = solv->rules + *rp;
1456 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
1458 POOL_DEBUG(SAT_DEBUG_PROPAGATE," watch triggered ");
1459 printrule(solv, SAT_DEBUG_PROPAGATE, r);
1464 ow = r->w2; /* regard the second watchpoint to come to a solution */
1469 ow = r->w1; /* regard the first watchpoint to come to a solution */
1472 /* if clause is TRUE, nothing to do */
1473 if (DECISIONMAP_TRUE(ow))
1478 /* not a binary clause, check if we need to move our watch */
1479 /* search for a literal that is not ow and not false */
1480 /* (true is also ok, in that case the rule is fulfilled) */
1481 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1484 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1485 if (p != ow && !DECISIONMAP_TRUE(-p))
1489 /* p is free to watch, move watch to p */
1490 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
1493 POOL_DEBUG(SAT_DEBUG_PROPAGATE, " -> move w%d to %s\n", (pkg == r->w1 ? 1 : 2), solvable2str(pool, pool->solvables + p));
1495 POOL_DEBUG(SAT_DEBUG_PROPAGATE," -> move w%d to !%s\n", (pkg == r->w1 ? 1 : 2), solvable2str(pool, pool->solvables - p));
1509 watches[p] = r - solv->rules;
1513 /* unit clause found, set other watch to TRUE */
1514 if (DECISIONMAP_TRUE(-ow))
1515 return r; /* eek, a conflict! */
1516 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
1518 POOL_DEBUG(SAT_DEBUG_PROPAGATE, " unit ");
1519 printrule(solv, SAT_DEBUG_PROPAGATE, r);
1522 decisionmap[ow] = level;
1524 decisionmap[-ow] = -level;
1525 queue_push(&solv->decisionq, ow);
1526 queue_push(&solv->decisionq_why, r - solv->rules);
1527 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
1529 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1531 POOL_DEBUG(SAT_DEBUG_PROPAGATE, " -> decided to install %s\n", solvable2str(pool, s));
1533 POOL_DEBUG(SAT_DEBUG_PROPAGATE, " -> decided to conflict %s\n", solvable2str(pool, s));
1537 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "----- propagate end-----\n");
1539 return 0; /* all is well */
1543 /*-----------------------------------------------------------------*/
1552 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *whyp)
1554 Pool *pool = solv->pool;
1557 Map seen; /* global? */
1560 int num = 0, l1num = 0;
1561 int learnt_why = solv->learnt_pool.count;
1562 Id *decisionmap = solv->decisionmap;
1566 POOL_DEBUG(SAT_DEBUG_ANALYZE, "ANALYZE at %d ----------------------\n", level);
1567 map_init(&seen, pool->nsolvables);
1568 idx = solv->decisionq.count;
1571 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
1572 printruleclass(solv, SAT_DEBUG_ANALYZE, c);
1573 queue_push(&solv->learnt_pool, c - solv->rules);
1574 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1575 /* go through all literals of the rule */
1587 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1589 vv = v > 0 ? v : -v;
1590 if (MAPTST(&seen, vv))
1592 l = solv->decisionmap[vv];
1597 /* a level 1 literal, mark it for later */
1598 MAPSET(&seen, vv); /* mark for scanning in level 1 phase */
1604 num++; /* need to do this one as well */
1615 v = solv->decisionq.elements[--idx];
1616 vv = v > 0 ? v : -v;
1617 if (MAPTST(&seen, vv))
1620 c = solv->rules + solv->decisionq_why.elements[idx];
1625 *pr = -v; /* so that v doesn't get lost */
1627 /* add involved level 1 rules */
1630 POOL_DEBUG(SAT_DEBUG_ANALYZE, "got %d involved level 1 decisions\n", l1num);
1634 v = solv->decisionq.elements[--idx];
1635 vv = v > 0 ? v : -v;
1636 if (!MAPTST(&seen, vv))
1638 why = solv->decisionq_why.elements[idx];
1641 queue_push(&solv->learnt_pool, -vv);
1642 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
1644 POOL_DEBUG(SAT_DEBUG_ANALYZE, "RPM ASSERT Rule:\n");
1645 printruleelement(solv, SAT_DEBUG_ANALYZE, 0, v);
1649 queue_push(&solv->learnt_pool, why);
1650 c = solv->rules + why;
1651 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1652 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
1653 printruleclass(solv, SAT_DEBUG_ANALYZE, c);
1664 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1666 vv = v > 0 ? v : -v;
1667 l = solv->decisionmap[vv];
1668 if (l != 1 && l != -1)
1678 else if (r.count == 1 && r.elements[0] < 0)
1679 *dr = r.elements[0];
1681 *dr = pool_queuetowhatprovides(pool, &r);
1682 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
1684 POOL_DEBUG(SAT_DEBUG_ANALYZE, "learned rule for level %d (am %d)\n", rlevel, level);
1685 printruleelement(solv, SAT_DEBUG_ANALYZE, 0, *pr);
1686 for (i = 0; i < r.count; i++)
1687 printruleelement(solv, SAT_DEBUG_ANALYZE, 0, r.elements[i]);
1689 /* push end marker on learnt reasons stack */
1690 queue_push(&solv->learnt_pool, 0);
1699 * reset the solver decisions to right after the rpm rules.
1700 * called after rules have been enabled/disabled
1704 reset_solver(Solver *solv)
1706 Pool *pool = solv->pool;
1710 /* rewind decisions to direct rpm rule assertions */
1711 for (i = solv->decisionq.count - 1; i >= solv->directdecisions; i--)
1713 v = solv->decisionq.elements[i];
1714 solv->decisionmap[v > 0 ? v : -v] = 0;
1717 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "decisions done reduced from %d to %d\n", solv->decisionq.count, solv->directdecisions);
1719 solv->decisionq_why.count = solv->directdecisions;
1720 solv->decisionq.count = solv->directdecisions;
1721 solv->recommends_index = -1;
1722 solv->propagate_index = 0;
1724 /* adapt learnt rule status to new set of enabled/disabled rules */
1725 enabledisablelearntrules(solv);
1727 /* redo all job/system decisions */
1728 makeruledecisions(solv);
1729 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "decisions so far: %d\n", solv->decisionq.count);
1731 /* recreate watch chains */
1737 * analyze_unsolvable_rule
1741 analyze_unsolvable_rule(Solver *solv, Rule *r)
1743 Pool *pool = solv->pool;
1745 Id why = r - solv->rules;
1746 IF_POOLDEBUG (SAT_DEBUG_UNSOLVABLE)
1747 printruleclass(solv, SAT_DEBUG_UNSOLVABLE, r);
1748 if (solv->learntrules && why >= solv->learntrules)
1750 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1751 if (solv->learnt_pool.elements[i] > 0)
1752 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]);
1755 /* do not add rpm rules to problem */
1756 if (why < solv->jobrules)
1758 /* turn rule into problem */
1759 if (why >= solv->jobrules && why < solv->systemrules)
1760 why = -(solv->ruletojob.elements[why - solv->jobrules] + 1);
1761 /* return if problem already countains our rule */
1762 if (solv->problems.count)
1764 for (i = solv->problems.count - 1; i >= 0; i--)
1765 if (solv->problems.elements[i] == 0) /* end of last problem reached? */
1767 else if (solv->problems.elements[i] == why)
1770 queue_push(&solv->problems, why);
1775 * analyze_unsolvable
1777 * return: 1 - disabled some rules, try again
1782 analyze_unsolvable(Solver *solv, Rule *cr, int disablerules)
1784 Pool *pool = solv->pool;
1786 Map seen; /* global to speed things up? */
1789 Id *decisionmap = solv->decisionmap;
1790 int oldproblemcount;
1791 int oldlearntpoolcount;
1794 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "ANALYZE UNSOLVABLE ----------------------\n");
1795 oldproblemcount = solv->problems.count;
1796 oldlearntpoolcount = solv->learnt_pool.count;
1798 /* make room for proof index */
1799 /* must update it later, as analyze_unsolvable_rule would confuse
1800 * it with a rule index if we put the real value in already */
1801 queue_push(&solv->problems, 0);
1804 map_init(&seen, pool->nsolvables);
1805 queue_push(&solv->learnt_pool, r - solv->rules);
1806 analyze_unsolvable_rule(solv, r);
1807 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1818 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1820 vv = v > 0 ? v : -v;
1821 l = solv->decisionmap[vv];
1826 idx = solv->decisionq.count;
1829 v = solv->decisionq.elements[--idx];
1830 vv = v > 0 ? v : -v;
1831 if (!MAPTST(&seen, vv))
1833 why = solv->decisionq_why.elements[idx];
1836 /* level 1 and no why, must be an rpm assertion */
1837 IF_POOLDEBUG (SAT_DEBUG_UNSOLVABLE)
1839 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "RPM ");
1840 printruleelement(solv, SAT_DEBUG_UNSOLVABLE, 0, v);
1842 /* this is the only positive rpm assertion */
1843 if (v == SYSTEMSOLVABLE)
1846 queue_push(&solv->learnt_pool, v);
1849 queue_push(&solv->learnt_pool, why);
1850 r = solv->rules + why;
1851 analyze_unsolvable_rule(solv, r);
1852 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1863 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1865 vv = v > 0 ? v : -v;
1866 l = solv->decisionmap[vv];
1873 queue_push(&solv->problems, 0); /* mark end of this problem */
1876 if (solv->weakrules != solv->learntrules)
1878 for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
1880 why = solv->problems.elements[i];
1881 if (why < solv->weakrules || why >= solv->learntrules)
1883 if (!lastweak || lastweak < why)
1889 /* disable last weak rule */
1890 solv->problems.count = oldproblemcount;
1891 solv->learnt_pool.count = oldlearntpoolcount;
1892 r = solv->rules + lastweak;
1893 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "disabling weak ");
1894 printrule(solv, SAT_DEBUG_UNSOLVABLE, r);
1895 disablerule(solv, r);
1901 queue_push(&solv->learnt_pool, 0);
1902 solv->problems.elements[oldproblemcount] = oldlearntpoolcount;
1906 for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++)
1907 disableproblem(solv, solv->problems.elements[i]);
1911 POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "UNSOLVABLE\n");
1916 /*-----------------------------------------------------------------*/
1917 /* Decision revert */
1921 * revert decision at level
1925 revert(Solver *solv, int level)
1927 Pool *pool = solv->pool;
1929 while (solv->decisionq.count)
1931 v = solv->decisionq.elements[solv->decisionq.count - 1];
1932 vv = v > 0 ? v : -v;
1933 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1935 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1936 if (v > 0 && solv->recommendations.count && v == solv->recommendations.elements[solv->recommendations.count - 1])
1937 solv->recommendations.count--;
1938 solv->decisionmap[vv] = 0;
1939 solv->decisionq.count--;
1940 solv->decisionq_why.count--;
1941 solv->propagate_index = solv->decisionq.count;
1943 while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] <= -level)
1945 solv->branches.count--;
1946 while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= 0)
1947 solv->branches.count--;
1949 solv->recommends_index = -1;
1954 * watch2onhighest - put watch2 on literal with highest level
1958 watch2onhighest(Solver *solv, Rule *r)
1964 return; /* binary rule, both watches are set */
1965 dp = solv->pool->whatprovidesdata + r->d;
1966 while ((v = *dp++) != 0)
1968 l = solv->decisionmap[v < 0 ? -v : v];
1983 * add free decision to decisionq, increase level and
1984 * propagate decision, return if no conflict.
1985 * in conflict case, analyze conflict rule, add resulting
1986 * rule to learnt rule set, make decision from learnt
1987 * rule (always unit) and re-propagate.
1989 * returns the new solver level or 0 if unsolvable
1994 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1996 Pool *pool = solv->pool;
2005 solv->decisionmap[decision] = level;
2007 solv->decisionmap[-decision] = -level;
2008 queue_push(&solv->decisionq, decision);
2009 queue_push(&solv->decisionq_why, 0);
2013 r = propagate(solv, level);
2017 return analyze_unsolvable(solv, r, disablerules);
2018 POOL_DEBUG(SAT_DEBUG_ANALYZE, "conflict with rule #%d\n", (int)(r - solv->rules));
2019 l = analyze(solv, level, r, &p, &d, &why); /* learnt rule in p and d */
2020 assert(l > 0 && l < level);
2021 POOL_DEBUG(SAT_DEBUG_ANALYZE, "reverting decisions (level %d -> %d)\n", level, l);
2023 revert(solv, level);
2024 r = addrule(solv, p, d); /* p requires d */
2026 assert(solv->learnt_why.count == (r - solv->rules) - solv->learntrules);
2027 queue_push(&solv->learnt_why, why);
2030 /* at least 2 literals, needs watches */
2031 watch2onhighest(solv, r);
2032 addwatches(solv, r);
2034 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
2035 queue_push(&solv->decisionq, p);
2036 queue_push(&solv->decisionq_why, r - solv->rules);
2037 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
2039 POOL_DEBUG(SAT_DEBUG_ANALYZE, "decision: ");
2040 printruleelement(solv, SAT_DEBUG_ANALYZE, 0, p);
2041 POOL_DEBUG(SAT_DEBUG_ANALYZE, "new rule: ");
2042 printrule(solv, SAT_DEBUG_ANALYZE, r);
2050 * install best package from the queue. We add an extra package, inst, if
2051 * provided. See comment in weak install section.
2053 * returns the new solver level or 0 if unsolvable
2057 selectandinstall(Solver *solv, int level, Queue *dq, Id inst, int disablerules)
2059 Pool *pool = solv->pool;
2063 if (dq->count > 1 || inst)
2064 policy_filter_unwanted(solv, dq, inst, POLICY_MODE_CHOOSE);
2069 /* choose the supplemented one */
2070 for (i = 0; i < dq->count; i++)
2071 if (solver_is_supplementing(solv, pool->solvables + dq->elements[i]))
2075 for (i = 1; i < dq->count; i++)
2076 queue_push(&solv->branches, dq->elements[i]);
2077 queue_push(&solv->branches, -level);
2081 p = dq->elements[i];
2083 POOL_DEBUG(SAT_DEBUG_POLICY, "installing %s\n", solvable2str(pool, pool->solvables + p));
2085 return setpropagatelearn(solv, level, p, disablerules);
2089 /*-----------------------------------------------------------------*/
2090 /* Main solver interface */
2095 * create solver structure
2097 * pool: all available solvables
2098 * installed: installed Solvables
2101 * Upon solving, rules are created to flag the Solvables
2102 * of the 'installed' Repo as installed.
2106 solver_create(Pool *pool, Repo *installed)
2109 solv = (Solver *)sat_calloc(1, sizeof(Solver));
2111 solv->installed = installed;
2113 queue_init(&solv->ruletojob);
2114 queue_init(&solv->decisionq);
2115 queue_init(&solv->decisionq_why);
2116 queue_init(&solv->problems);
2117 queue_init(&solv->suggestions);
2118 queue_init(&solv->recommendations);
2119 queue_init(&solv->learnt_why);
2120 queue_init(&solv->learnt_pool);
2121 queue_init(&solv->branches);
2122 queue_init(&solv->covenantq);
2124 map_init(&solv->recommendsmap, pool->nsolvables);
2125 map_init(&solv->suggestsmap, pool->nsolvables);
2126 map_init(&solv->noupdate, installed ? installed->end - installed->start : 0);
2127 solv->recommends_index = 0;
2129 solv->decisionmap = (Id *)sat_calloc(pool->nsolvables, sizeof(Id));
2131 solv->rules = sat_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
2132 memset(solv->rules, 0, sizeof(Rule));
2143 solver_free(Solver *solv)
2145 queue_free(&solv->ruletojob);
2146 queue_free(&solv->decisionq);
2147 queue_free(&solv->decisionq_why);
2148 queue_free(&solv->learnt_why);
2149 queue_free(&solv->learnt_pool);
2150 queue_free(&solv->problems);
2151 queue_free(&solv->suggestions);
2152 queue_free(&solv->recommendations);
2153 queue_free(&solv->branches);
2154 queue_free(&solv->covenantq);
2156 map_free(&solv->recommendsmap);
2157 map_free(&solv->suggestsmap);
2158 map_free(&solv->noupdate);
2160 sat_free(solv->decisionmap);
2161 sat_free(solv->rules);
2162 sat_free(solv->watches);
2163 sat_free(solv->weaksystemrules);
2164 sat_free(solv->obsoletes);
2165 sat_free(solv->obsoletes_data);
2170 /*-------------------------------------------------------*/
2175 * all rules have been set up, now actually run the solver
2180 run_solver(Solver *solv, int disablerules, int doweak)
2188 Pool *pool = solv->pool;
2191 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
2193 POOL_DEBUG (SAT_DEBUG_RULE_CREATION, "number of rules: %d\n", solv->nrules);
2194 for (i = 0; i < solv->nrules; i++)
2195 printrule(solv, SAT_DEBUG_RULE_CREATION, solv->rules + i);
2198 POOL_DEBUG(SAT_DEBUG_STATS, "initial decisions: %d\n", solv->decisionq.count);
2200 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2201 printdecisions(solv);
2203 /* start SAT algorithm */
2205 systemlevel = level + 1;
2206 POOL_DEBUG(SAT_DEBUG_STATS, "solving...\n");
2217 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "propagating (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
2218 if ((r = propagate(solv, level)) != 0)
2220 if (analyze_unsolvable(solv, r, disablerules))
2228 * installed packages
2231 if (level < systemlevel && solv->installed && solv->installed->nsolvables)
2233 if (!solv->updatesystem)
2235 /* try to keep as many packages as possible */
2236 POOL_DEBUG(SAT_DEBUG_STATS, "installing system packages\n");
2237 for (i = solv->installed->start, n = 0; ; i++)
2239 if (n == solv->installed->nsolvables)
2241 if (i == solv->installed->end)
2242 i = solv->installed->start;
2243 s = pool->solvables + i;
2244 if (s->repo != solv->installed)
2247 if (solv->decisionmap[i] != 0)
2249 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "keeping %s\n", solvable2str(pool, s));
2251 level = setpropagatelearn(solv, level, i, disablerules);
2257 if (level <= olevel)
2261 if (solv->weaksystemrules)
2263 POOL_DEBUG(SAT_DEBUG_STATS, "installing weak system packages\n");
2264 for (i = solv->installed->start; i < solv->installed->end; i++)
2266 if (pool->solvables[i].repo != solv->installed)
2268 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->installed->start] == 0))
2270 /* noupdate is set if a job is erasing the installed solvable or installing a specific version */
2271 if (MAPTST(&solv->noupdate, i - solv->installed->start))
2274 if (solv->weaksystemrules[i - solv->installed->start])
2276 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->installed->start];
2277 while ((p = *dp++) != 0)
2279 if (solv->decisionmap[p] > 0)
2281 if (solv->decisionmap[p] == 0)
2285 continue; /* update package already installed */
2287 if (!dq.count && solv->decisionmap[i] != 0)
2290 /* FIXME: i is handled a bit different because we do not want
2291 * to have it pruned just because it is not recommened.
2292 * we should not prune installed packages instead */
2293 level = selectandinstall(solv, level, &dq, (solv->decisionmap[i] ? 0 : i), disablerules);
2299 if (level <= olevel)
2302 if (i < solv->installed->end)
2305 systemlevel = level;
2312 POOL_DEBUG(SAT_DEBUG_STATS, "deciding unresolved rules\n");
2313 for (i = 1, n = 1; ; i++, n++)
2315 if (n == solv->nrules)
2317 if (i == solv->nrules)
2319 r = solv->rules + i;
2320 if (!r->w1) /* ignore disabled rules */
2325 /* binary or unary rule */
2326 /* need two positive undecided literals */
2327 if (r->p < 0 || r->w2 <= 0)
2329 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2331 queue_push(&dq, r->p);
2332 queue_push(&dq, r->w2);
2337 * all negative literals are installed
2338 * no positive literal is installed
2339 * i.e. the rule is not fulfilled and we
2340 * just need to decide on the positive literals
2344 if (solv->decisionmap[-r->p] <= 0)
2349 if (solv->decisionmap[r->p] > 0)
2351 if (solv->decisionmap[r->p] == 0)
2352 queue_push(&dq, r->p);
2354 dp = pool->whatprovidesdata + r->d;
2355 while ((p = *dp++) != 0)
2359 if (solv->decisionmap[-p] <= 0)
2364 if (solv->decisionmap[p] > 0)
2366 if (solv->decisionmap[p] == 0)
2373 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
2375 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "unfulfilled ");
2376 printrule(solv, SAT_DEBUG_PROPAGATE, r);
2378 /* dq.count < 2 cannot happen as this means that
2379 * the rule is unit */
2380 assert(dq.count > 1);
2383 level = selectandinstall(solv, level, &dq, 0, disablerules);
2389 if (level < systemlevel)
2392 } /* for(), decide */
2394 if (n != solv->nrules) /* continue if level < systemlevel */
2397 if (doweak && !solv->problems.count)
2401 POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended packages\n");
2402 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS)
2404 for (i = 1; i < solv->decisionq.count; i++)
2406 p = solv->decisionq.elements[i];
2407 if (p > 0 && pool->solvables[p].repo == solv->installed)
2408 solv->decisionmap[p] = -solv->decisionmap[p];
2412 for (i = 1; i < pool->nsolvables; i++)
2414 if (solv->decisionmap[i] < 0)
2416 if (solv->decisionmap[i] > 0)
2418 Id *recp, rec, *pp, p;
2419 s = pool->solvables + i;
2420 /* installed, check for recommends */
2421 /* XXX need to special case AND ? */
2424 recp = s->repo->idarraydata + s->recommends;
2425 while ((rec = *recp++) != 0)
2428 FOR_PROVIDES(p, pp, rec)
2430 if (solv->decisionmap[p] > 0)
2435 else if (solv->decisionmap[p] == 0)
2437 queue_pushunique(&dq, p);
2445 s = pool->solvables + i;
2446 if (!s->supplements && !s->freshens)
2448 if (!pool_installable(pool, s))
2450 if (solver_is_supplementing(solv, s))
2451 queue_pushunique(&dq, i);
2454 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS)
2456 for (i = 1; i < solv->decisionq.count; i++)
2458 p = solv->decisionq.elements[i];
2459 if (p > 0 && pool->solvables[p].repo == solv->installed)
2460 solv->decisionmap[p] = -solv->decisionmap[p];
2466 policy_filter_unwanted(solv, &dq, 0, POLICY_MODE_RECOMMEND);
2468 POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended %s\n", solvable2str(pool, pool->solvables + p));
2469 queue_push(&solv->recommendations, p);
2470 level = setpropagatelearn(solv, level, p, 0);
2475 if (solv->solution_callback)
2477 solv->solution_callback(solv, solv->solution_callback_data);
2478 if (solv->branches.count)
2480 int i = solv->branches.count - 1;
2481 int l = -solv->branches.elements[i];
2483 if (solv->branches.elements[i - 1] < 0)
2485 p = solv->branches.elements[i];
2486 POOL_DEBUG(SAT_DEBUG_STATS, "branching with %s\n", solvable2str(pool, pool->solvables + p));
2488 for (j = i + 1; j < solv->branches.count; j++)
2489 queue_push(&dq, solv->branches.elements[j]);
2490 solv->branches.count = i;
2492 revert(solv, level);
2494 for (j = 0; j < dq.count; j++)
2495 queue_push(&solv->branches, dq.elements[j]);
2497 level = setpropagatelearn(solv, level, p, disablerules);
2505 /* all branches done, we're finally finished */
2509 /* minimization step */
2510 if (solv->branches.count)
2512 int l = 0, lasti = -1, lastl = -1;
2514 for (i = solv->branches.count - 1; i >= 0; i--)
2516 p = solv->branches.elements[i];
2519 else if (p > 0 && solv->decisionmap[p] > l + 1)
2527 /* kill old solvable so that we do not loop */
2528 p = solv->branches.elements[lasti];
2529 solv->branches.elements[lasti] = 0;
2530 POOL_DEBUG(SAT_DEBUG_STATS, "minimizing %d -> %d with %s\n", solv->decisionmap[p], l, solvable2str(pool, pool->solvables + p));
2533 revert(solv, level);
2535 level = setpropagatelearn(solv, level, p, disablerules);
2546 POOL_DEBUG(SAT_DEBUG_STATS, "done solving.\n\n");
2553 * at this point, all rules that led to conflicts are disabled.
2554 * we re-enable all rules of a problem set but rule "sug", then
2555 * continue to disable more rules until there as again a solution.
2558 /* FIXME: think about conflicting assertions */
2561 refine_suggestion(Solver *solv, Queue *job, Id *problem, Id sug, Queue *refined)
2563 Pool *pool = solv->pool;
2570 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
2572 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion start\n");
2573 for (i = 0; problem[i]; i++)
2575 if (problem[i] == sug)
2576 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "=> ");
2577 printproblem(solv, problem[i]);
2580 queue_init(&disabled);
2581 queue_empty(refined);
2582 queue_push(refined, sug);
2584 /* re-enable all problem rules with the exception of "sug"(gests) */
2588 for (i = 0; problem[i]; i++)
2589 if (problem[i] != sug)
2590 enableproblem(solv, problem[i]);
2593 disableupdaterules(solv, job, -(sug + 1));
2597 /* re-enable as many weak rules as possible */
2598 for (i = solv->weakrules; i < solv->learntrules; i++)
2600 r = solv->rules + i;
2602 enablerule(solv, r);
2605 queue_empty(&solv->problems);
2606 revert(solv, 1); /* XXX move to reset_solver? */
2609 if (!solv->problems.count)
2610 run_solver(solv, 0, 0);
2612 if (!solv->problems.count)
2614 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no more problems!\n");
2615 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2616 printdecisions(solv);
2617 break; /* great, no more problems */
2619 disabledcnt = disabled.count;
2620 /* start with 1 to skip over proof index */
2621 for (i = 1; i < solv->problems.count - 1; i++)
2623 /* ignore solutions in refined */
2624 v = solv->problems.elements[i];
2626 break; /* end of problem reached */
2627 for (j = 0; problem[j]; j++)
2628 if (problem[j] != sug && problem[j] == v)
2632 queue_push(&disabled, v);
2634 if (disabled.count == disabledcnt)
2636 /* no solution found, this was an invalid suggestion! */
2637 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no solution found!\n");
2641 if (disabled.count == disabledcnt + 1)
2643 /* just one suggestion, add it to refined list */
2644 v = disabled.elements[disabledcnt];
2645 queue_push(refined, v);
2646 disableproblem(solv, v);
2648 disableupdaterules(solv, job, -(v + 1));
2652 /* more than one solution, disable all */
2653 /* do not push anything on refine list */
2654 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
2656 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "more than one solution found:\n");
2657 for (i = disabledcnt; i < disabled.count; i++)
2658 printproblem(solv, disabled.elements[i]);
2660 for (i = disabledcnt; i < disabled.count; i++)
2661 disableproblem(solv, disabled.elements[i]);
2664 /* all done, get us back into the same state as before */
2665 /* enable refined rules again */
2666 for (i = 0; i < disabled.count; i++)
2667 enableproblem(solv, disabled.elements[i]);
2668 /* disable problem rules again */
2669 for (i = 0; problem[i]; i++)
2670 disableproblem(solv, problem[i]);
2671 disableupdaterules(solv, job, -1);
2672 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion end\n");
2676 problems_to_solutions(Solver *solv, Queue *job)
2678 Pool *pool = solv->pool;
2686 if (!solv->problems.count)
2688 queue_clone(&problems, &solv->problems);
2689 queue_init(&solution);
2690 queue_init(&solutions);
2691 /* copy over proof index */
2692 queue_push(&solutions, problems.elements[0]);
2693 problem = problems.elements + 1;
2694 for (i = 1; i < problems.count; i++)
2696 Id v = problems.elements[i];
2699 /* mark end of this problem */
2700 queue_push(&solutions, 0);
2701 queue_push(&solutions, 0);
2702 if (i + 1 == problems.count)
2704 /* copy over proof of next problem */
2705 queue_push(&solutions, problems.elements[i + 1]);
2707 problem = problems.elements + i + 1;
2710 refine_suggestion(solv, job, problem, v, &solution);
2711 if (!solution.count)
2712 continue; /* this solution didn't work out */
2714 for (j = 0; j < solution.count; j++)
2716 why = solution.elements[j];
2717 /* must be either job descriptor or system rule */
2718 assert(why < 0 || (why >= solv->systemrules && why < solv->weakrules));
2720 printproblem(solv, why);
2724 /* job descriptor */
2725 queue_push(&solutions, 0);
2726 queue_push(&solutions, -why);
2730 /* system rule, find replacement package */
2732 p = solv->installed->start + (why - solv->systemrules);
2733 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2735 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2738 if (*dp >= solv->installed->start && *dp < solv->installed->start + solv->installed->nsolvables)
2740 if (solv->decisionmap[*dp] > 0)
2747 queue_push(&solutions, p);
2748 queue_push(&solutions, rp);
2751 /* mark end of this solution */
2752 queue_push(&solutions, 0);
2753 queue_push(&solutions, 0);
2755 queue_free(&solution);
2756 queue_free(&problems);
2757 /* copy queue over to solutions */
2758 queue_free(&solv->problems);
2759 queue_clone(&solv->problems, &solutions);
2761 /* bring solver back into problem state */
2762 revert(solv, 1); /* XXX move to reset_solver? */
2765 assert(solv->problems.count == solutions.count);
2766 queue_free(&solutions);
2770 solver_next_problem(Solver *solv, Id problem)
2774 return solv->problems.count ? 1 : 0;
2775 pp = solv->problems.elements + problem;
2776 while (pp[0] || pp[1])
2780 while (pp[0] || pp[1])
2785 problem = pp - solv->problems.elements;
2786 if (problem >= solv->problems.count)
2792 solver_next_solution(Solver *solv, Id problem, Id solution)
2798 pp = solv->problems.elements + solution;
2799 return pp[0] || pp[1] ? solution : 0;
2801 pp = solv->problems.elements + solution;
2802 while (pp[0] || pp[1])
2805 solution = pp - solv->problems.elements;
2806 return pp[0] || pp[1] ? solution : 0;
2810 solver_next_solutionelement(Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp)
2813 element = element ? element + 2 : solution;
2814 pp = solv->problems.elements + element;
2815 if (!(pp[0] || pp[1]))
2824 * create obsoletesmap from solver decisions
2825 * required for decision handling
2829 create_decisions_obsoletesmap(Solver *solv)
2831 Pool *pool = solv->pool;
2832 Repo *installed = solv->installed;
2833 Id p, *obsoletesmap = NULL;
2837 obsoletesmap = (Id *)sat_calloc(pool->nsolvables, sizeof(Id));
2840 for (i = 0; i < solv->decisionq.count; i++)
2844 n = solv->decisionq.elements[i];
2847 if (n == SYSTEMSOLVABLE)
2849 s = pool->solvables + n;
2850 if (s->repo == installed) /* obsoletes don't count for already installed packages */
2852 FOR_PROVIDES(p, pp, s->name)
2853 if (s->name == pool->solvables[p].name)
2855 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
2857 obsoletesmap[p] = n;
2862 for (i = 0; i < solv->decisionq.count; i++)
2867 n = solv->decisionq.elements[i];
2870 if (n == SYSTEMSOLVABLE)
2872 s = pool->solvables + n;
2873 if (s->repo == installed) /* obsoletes don't count for already installed packages */
2877 obsp = s->repo->idarraydata + s->obsoletes;
2878 while ((obs = *obsp++) != 0)
2879 FOR_PROVIDES(p, pp, obs)
2881 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
2883 obsoletesmap[p] = n;
2889 return obsoletesmap;
2898 printdecisions(Solver *solv)
2900 Pool *pool = solv->pool;
2901 Repo *installed = solv->installed;
2902 Id p, *obsoletesmap = create_decisions_obsoletesmap( solv );
2906 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions -----\n");
2908 /* print solvables to be erased */
2912 FOR_REPO_SOLVABLES(installed, p, s)
2914 if (solv->decisionmap[p] >= 0)
2916 if (obsoletesmap[p])
2918 POOL_DEBUG(SAT_DEBUG_RESULT, "erase %s\n", solvable2str(pool, s));
2922 /* print solvables to be installed */
2924 for (i = 0; i < solv->decisionq.count; i++)
2927 p = solv->decisionq.elements[i];
2930 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2933 s = pool->solvables + p;
2934 POOL_DEBUG(SAT_DEBUG_SCHUBI, "level of %s is %d\n", solvable2str(pool, s), p);
2938 if (p == SYSTEMSOLVABLE)
2940 POOL_DEBUG(SAT_DEBUG_SCHUBI, "SYSTEMSOLVABLE\n");
2943 s = pool->solvables + p;
2944 if (installed && s->repo == installed)
2947 if (!obsoletesmap[p])
2949 POOL_DEBUG(SAT_DEBUG_RESULT, "install %s", solvable2str(pool, s));
2953 POOL_DEBUG(SAT_DEBUG_RESULT, "update %s", solvable2str(pool, s));
2954 POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes");
2955 for (j = installed->start; j < installed->end; j++)
2956 if (obsoletesmap[j] == p)
2957 POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j));
2958 POOL_DEBUG(SAT_DEBUG_RESULT, ")");
2960 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
2963 sat_free(obsoletesmap);
2965 if (solv->recommendations.count)
2967 POOL_DEBUG(SAT_DEBUG_RESULT, "\nrecommended packages:\n");
2968 for (i = 0; i < solv->recommendations.count; i++)
2970 s = pool->solvables + solv->recommendations.elements[i];
2971 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s\n", solvable2str(pool, s));
2975 if (solv->suggestions.count)
2977 POOL_DEBUG(SAT_DEBUG_RESULT, "\nsuggested packages:\n");
2978 for (i = 0; i < solv->suggestions.count; i++)
2980 s = pool->solvables + solv->suggestions.elements[i];
2981 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s\n", solvable2str(pool, s));
2984 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions end -----\n");
2987 /* this is basically the reverse of addrpmrulesforsolvable */
2989 solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, Id *targetp)
2991 Pool *pool = solv->pool;
2992 Repo *installed = solv->installed;
2996 Id p, *pp, req, *reqp, con, *conp, obs, *obsp, *dp;
2998 assert(rid < solv->weakrules);
2999 if (rid >= solv->systemrules)
3002 *sourcep = solv->installed->start + (rid - solv->systemrules);
3004 return SOLVER_PROBLEM_UPDATE_RULE;
3006 if (rid >= solv->jobrules)
3009 r = solv->rules + rid;
3010 p = solv->ruletojob.elements[rid - solv->jobrules];
3011 *depp = job->elements[p + 1];
3013 *targetp = job->elements[p];
3014 if (r->d == 0 && r->w2 == 0 && r->p == -SYSTEMSOLVABLE)
3015 return SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP;
3016 return SOLVER_PROBLEM_JOB_RULE;
3020 /* a rpm rule assertion */
3021 assert(rid != -SYSTEMSOLVABLE);
3022 s = pool->solvables - rid;
3023 if (installed && !solv->fixsystem && s->repo == installed)
3025 assert(!dontfix); /* dontfix packages never have a neg assertion */
3026 /* see why the package is not installable */
3027 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC && !pool_installable(pool, s))
3032 return SOLVER_PROBLEM_NOT_INSTALLABLE;
3034 /* check requires */
3035 assert(s->requires);
3036 reqp = s->repo->idarraydata + s->requires;
3037 while ((req = *reqp++) != 0)
3039 if (req == SOLVABLE_PREREQMARKER)
3041 dp = pool_whatprovides(pool, req);
3049 return SOLVER_PROBLEM_NOTHING_PROVIDES_DEP;
3051 r = solv->rules + rid;
3053 if (r->d == 0 && r->w2 == 0)
3055 /* an assertion. we don't store them as rpm rules, so
3059 s = pool->solvables - r->p;
3060 if (installed && !solv->fixsystem && s->repo == installed)
3062 if (r->d == 0 && r->w2 < 0)
3064 /* a package conflict */
3065 Solvable *s2 = pool->solvables - r->w2;
3068 if (installed && !solv->fixsystem && s2->repo == installed)
3071 /* if both packages have the same name and at least one of them
3072 * is not installed, they conflict */
3073 if (s->name == s2->name && (!installed || (s->repo != installed || s2->repo != installed)))
3078 return SOLVER_PROBLEM_SAME_NAME;
3081 /* check conflicts in both directions */
3084 conp = s->repo->idarraydata + s->conflicts;
3085 while ((con = *conp++) != 0)
3087 FOR_PROVIDES(p, pp, con)
3089 if (dontfix && pool->solvables[p].repo == installed)
3096 return SOLVER_PROBLEM_PACKAGE_CONFLICT;
3102 conp = s2->repo->idarraydata + s2->conflicts;
3103 while ((con = *conp++) != 0)
3105 FOR_PROVIDES(p, pp, con)
3107 if (dontfix2 && pool->solvables[p].repo == installed)
3114 return SOLVER_PROBLEM_PACKAGE_CONFLICT;
3118 /* check obsoletes in both directions */
3119 if ((!installed || s->repo != installed) && s->obsoletes)
3121 obsp = s->repo->idarraydata + s->obsoletes;
3122 while ((obs = *obsp++) != 0)
3124 FOR_PROVIDES(p, pp, obs)
3131 return SOLVER_PROBLEM_PACKAGE_OBSOLETES;
3135 if ((!installed || s2->repo != installed) && s2->obsoletes)
3137 obsp = s2->repo->idarraydata + s2->obsoletes;
3138 while ((obs = *obsp++) != 0)
3140 FOR_PROVIDES(p, pp, obs)
3147 return SOLVER_PROBLEM_PACKAGE_OBSOLETES;
3151 /* all cases checked, can't happen */
3154 /* simple requires */
3155 assert(s->requires);
3156 reqp = s->repo->idarraydata + s->requires;
3157 while ((req = *reqp++) != 0)
3159 if (req == SOLVABLE_PREREQMARKER)
3161 dp = pool_whatprovides(pool, req);
3164 if (*dp == r->w2 && dp[1] == 0)
3167 else if (dp - pool->whatprovidesdata == r->d)
3174 return SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE;
3178 findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp)
3181 Id lreqr, lconr, lsysr, ljobr;
3185 lreqr = lconr = lsysr = ljobr = 0;
3186 while ((rid = solv->learnt_pool.elements[idx++]) != 0)
3188 if (rid >= solv->learntrules)
3189 findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr);
3190 else if (rid >= solv->systemrules)
3195 else if (rid >= solv->jobrules)
3202 r = solv->rules + rid;
3203 if (!r->d && r->w2 < 0)
3212 else if (solv->installed && r->p < 0 && solv->pool->solvables[-r->p].repo == solv->installed)
3214 /* prefer rules of installed packages */
3215 Id op = *reqrp >= 0 ? solv->rules[*reqrp].p : -*reqrp;
3216 if (op <= 0 || solv->pool->solvables[op].repo != solv->installed)
3223 /* assertion, counts as require rule */
3224 /* ignore system solvable as we need useful info */
3225 if (rid == -SYSTEMSOLVABLE)
3227 if (!*reqrp || !reqassert)
3232 else if (solv->installed && solv->pool->solvables[-rid].repo == solv->installed)
3234 /* prefer rules of installed packages */
3235 Id op = *reqrp >= 0 ? solv->rules[*reqrp].p : -*reqrp;
3236 if (op <= 0 || solv->pool->solvables[op].repo != solv->installed)
3241 if (!*reqrp && lreqr)
3243 if (!*conrp && lconr)
3245 if (!*jobrp && ljobr)
3247 if (!*sysrp && lsysr)
3252 solver_findproblemrule(Solver *solv, Id problem)
3254 Id reqr, conr, sysr, jobr;
3255 Id idx = solv->problems.elements[problem - 1];
3256 reqr = conr = sysr = jobr = 0;
3257 findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr);
3270 printprobleminfo(Solver *solv, Queue *job, Id problem)
3272 Pool *pool = solv->pool;
3274 Id dep, source, target;
3277 probr = solver_findproblemrule(solv, problem);
3278 switch (solver_problemruleinfo(solv, job, probr, &dep, &source, &target))
3280 case SOLVER_PROBLEM_UPDATE_RULE:
3281 s = pool_id2solvable(pool, source);
3282 POOL_DEBUG(SAT_DEBUG_RESULT, "problem with installed package %s\n", solvable2str(pool, s));
3284 case SOLVER_PROBLEM_JOB_RULE:
3285 POOL_DEBUG(SAT_DEBUG_RESULT, "conflicting requests\n");
3287 case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
3288 POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides requested %s\n", dep2str(pool, dep));
3290 case SOLVER_PROBLEM_NOT_INSTALLABLE:
3291 s = pool_id2solvable(pool, source);
3292 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s is not installable\n", solvable2str(pool, s));
3294 case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
3295 s = pool_id2solvable(pool, source);
3296 POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides %s needed by %s\n", dep2str(pool, dep), solvable2str(pool, s));
3298 case SOLVER_PROBLEM_SAME_NAME:
3299 s = pool_id2solvable(pool, source);
3300 s2 = pool_id2solvable(pool, target);
3301 POOL_DEBUG(SAT_DEBUG_RESULT, "cannot install both %s and %s\n", solvable2str(pool, s), solvable2str(pool, s2));
3303 case SOLVER_PROBLEM_PACKAGE_CONFLICT:
3304 s = pool_id2solvable(pool, source);
3305 s2 = pool_id2solvable(pool, target);
3306 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s conflicts with %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
3308 case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
3309 s = pool_id2solvable(pool, source);
3310 s2 = pool_id2solvable(pool, target);
3311 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s obsoletes %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
3313 case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
3314 s = pool_id2solvable(pool, source);
3315 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s requires %s, but none of the providers can be installed\n", solvable2str(pool, s), dep2str(pool, dep));
3321 printsolutions(Solver *solv, Queue *job)
3323 Pool *pool = solv->pool;
3326 Id problem, solution, element;
3329 POOL_DEBUG(SAT_DEBUG_RESULT, "Encountered problems! Here are the solutions:\n\n");
3332 while ((problem = solver_next_problem(solv, problem)) != 0)
3334 POOL_DEBUG(SAT_DEBUG_RESULT, "Problem %d:\n", pcnt++);
3335 POOL_DEBUG(SAT_DEBUG_RESULT, "====================================\n");
3336 printprobleminfo(solv, job, problem);
3337 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
3339 while ((solution = solver_next_solution(solv, problem, solution)) != 0)
3342 while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
3346 /* job, rp is index into job queue */
3347 what = job->elements[rp];
3348 switch (job->elements[rp - 1])
3350 case SOLVER_INSTALL_SOLVABLE:
3351 s = pool->solvables + what;
3352 if (solv->installed && s->repo == solv->installed)
3353 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not keep %s installed\n", solvable2str(pool, s));
3355 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", solvable2str(pool, s));
3357 case SOLVER_ERASE_SOLVABLE:
3358 s = pool->solvables + what;
3359 if (solv->installed && s->repo == solv->installed)
3360 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", solvable2str(pool, s));
3362 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not forbid installation of %s\n", solvable2str(pool, s));
3364 case SOLVER_INSTALL_SOLVABLE_NAME:
3365 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", dep2str(pool, what));
3367 case SOLVER_ERASE_SOLVABLE_NAME:
3368 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", dep2str(pool, what));
3370 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3371 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install a solvable providing %s\n", dep2str(pool, what));
3373 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3374 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall all solvables providing %s\n", dep2str(pool, what));
3376 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3377 s = pool->solvables + what;
3378 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install most recent version of %s\n", solvable2str(pool, s));
3381 POOL_DEBUG(SAT_DEBUG_RESULT, "- do something different\n");
3387 /* policy, replace p with rp */
3388 s = pool->solvables + p;
3389 sd = rp ? pool->solvables + rp : 0;
3393 if (!solv->allowdowngrade && evrcmp(pool, s->evr, sd->evr, EVRCMP_MATCH_RELEASE) > 0)
3395 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow downgrade of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3398 if (!solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(solv, s, sd))
3400 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow architecture change of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3403 if (!solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(solv, s, sd))
3406 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow vendor change from '%s' (%s) to '%s' (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), id2str(pool, sd->vendor), solvable2str(pool, sd));
3408 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow vendor change from '%s' (%s) to no vendor (%s)\n", id2str(pool, s->vendor), solvable2str(pool, s), solvable2str(pool, sd));
3412 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow replacement of %s with %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3416 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow deinstallation of %s\n", solvable2str(pool, s));
3421 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
3427 /* create reverse obsoletes map for installed solvables
3429 * for each installed solvable find which packages with *different* names
3430 * obsolete the solvable.
3431 * this index is used in policy_findupdatepackages if noupdateprovide is set.
3435 create_obsolete_index(Solver *solv)
3437 Pool *pool = solv->pool;
3439 Repo *installed = solv->installed;
3440 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
3443 if (!installed || !installed->nsolvables)
3445 solv->obsoletes = obsoletes = sat_calloc(installed->end - installed->start, sizeof(Id));
3446 for (i = 1; i < pool->nsolvables; i++)
3448 s = pool->solvables + i;
3449 if (s->repo == installed)
3453 if (!pool_installable(pool, s))
3455 obsp = s->repo->idarraydata + s->obsoletes;
3456 while ((obs = *obsp++) != 0)
3457 FOR_PROVIDES(p, pp, obs)
3459 if (pool->solvables[p].repo != installed)
3461 if (pool->solvables[p].name == s->name)
3463 obsoletes[p - installed->start]++;
3467 for (i = 0; i < installed->nsolvables; i++)
3470 n += obsoletes[i] + 1;
3473 solv->obsoletes_data = obsoletes_data = sat_calloc(n + 1, sizeof(Id));
3474 POOL_DEBUG(SAT_DEBUG_STATS, "obsoletes data: %d entries\n", n + 1);
3475 for (i = pool->nsolvables - 1; i > 0; i--)
3477 s = pool->solvables + i;
3478 if (s->repo == installed)
3482 if (!pool_installable(pool, s))
3484 obsp = s->repo->idarraydata + s->obsoletes;
3485 while ((obs = *obsp++) != 0)
3486 FOR_PROVIDES(p, pp, obs)
3488 if (pool->solvables[p].repo != installed)
3490 if (pool->solvables[p].name == s->name)
3492 p -= installed->start;
3493 if (obsoletes_data[obsoletes[p]] != i)
3494 obsoletes_data[--obsoletes[p]] = i;
3500 /*-----------------------------------------------------------------*/
3510 solver_solve(Solver *solv, Queue *job)
3512 Pool *pool = solv->pool;
3513 Repo *installed = solv->installed;
3516 Map addedmap; /* '1' == have rpm-rules for solvable */
3517 Id how, what, name, p, *pp, d;
3521 /* create whatprovides if not already there */
3522 if (!pool->whatprovides)
3523 pool_createwhatprovides(pool);
3525 /* create obsolete index if needed */
3526 if (solv->noupdateprovide)
3527 create_obsolete_index(solv);
3530 * create basic rule set of all involved packages
3531 * use addedmap bitmap to make sure we don't create rules twice
3535 map_init(&addedmap, pool->nsolvables);
3539 * always install our system solvable
3541 MAPSET(&addedmap, SYSTEMSOLVABLE);
3542 queue_push(&solv->decisionq, SYSTEMSOLVABLE);
3543 queue_push(&solv->decisionq_why, 0);
3544 solv->decisionmap[SYSTEMSOLVABLE] = 1;
3547 * create rules for all package that could be involved with the solving
3548 * so called: rpm rules
3553 oldnrules = solv->nrules;
3554 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for installed solvables ***\n");
3555 FOR_REPO_SOLVABLES(installed, p, s)
3556 addrpmrulesforsolvable(solv, s, &addedmap);
3557 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for installed solvables\n", solv->nrules - oldnrules);
3558 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for updaters of installed solvables ***\n");
3559 oldnrules = solv->nrules;
3560 FOR_REPO_SOLVABLES(installed, p, s)
3561 addrpmrulesforupdaters(solv, s, &addedmap, 1);
3562 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for updaters of installed solvables\n", solv->nrules - oldnrules);
3565 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for packages involved with a job ***\n");
3566 oldnrules = solv->nrules;
3567 for (i = 0; i < job->count; i += 2)
3569 how = job->elements[i];
3570 what = job->elements[i + 1];
3574 case SOLVER_INSTALL_SOLVABLE:
3575 addrpmrulesforsolvable(solv, pool->solvables + what, &addedmap);
3577 case SOLVER_INSTALL_SOLVABLE_NAME:
3578 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3579 name = (how == SOLVER_INSTALL_SOLVABLE_NAME) ? what : 0;
3580 while (ISRELDEP(name))
3582 Reldep *rd = GETRELDEP(pool, name);
3585 FOR_PROVIDES(p, pp, what)
3587 /* if by name, ensure that the name matches */
3588 if (name && pool->solvables[p].name != name)
3590 addrpmrulesforsolvable(solv, pool->solvables + p, &addedmap);
3593 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3594 /* dont allow downgrade */
3595 addrpmrulesforupdaters(solv, pool->solvables + what, &addedmap, 0);
3599 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for packages involved in a job\n", solv->nrules - oldnrules);
3601 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for recommended/suggested packages ***\n");
3603 oldnrules = solv->nrules;
3604 addrpmrulesforweak(solv, &addedmap);
3605 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules because of weak dependencies\n", solv->nrules - oldnrules);
3607 IF_POOLDEBUG (SAT_DEBUG_STATS)
3609 int possible = 0, installable = 0;
3610 for (i = 1; i < pool->nsolvables; i++)
3612 if (pool_installable(pool, pool->solvables + i))
3614 if (MAPTST(&addedmap, i))
3617 POOL_DEBUG(SAT_DEBUG_STATS, "%d of %d installable solvables considered for solving (rules has been generated for)\n", possible, installable);
3621 * first pass done, we now have all the rpm rules we need.
3622 * unify existing rules before going over all job rules and
3624 * at this point the system is always solvable,
3625 * as an empty system (remove all packages) is a valid solution
3628 unifyrules(solv); /* remove duplicate rpm rules */
3629 solv->directdecisions = solv->decisionq.count;
3631 POOL_DEBUG(SAT_DEBUG_STATS, "decisions so far: %d\n", solv->decisionq.count);
3632 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
3633 printdecisions (solv);
3636 * now add all job rules
3639 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** Add JOB rules ***\n");
3641 solv->jobrules = solv->nrules;
3643 for (i = 0; i < job->count; i += 2)
3645 oldnrules = solv->nrules;
3647 how = job->elements[i];
3648 what = job->elements[i + 1];
3651 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
3652 s = pool->solvables + what;
3653 POOL_DEBUG(SAT_DEBUG_JOB, "job: install solvable %s\n", solvable2str(pool, s));
3654 addrule(solv, what, 0); /* install by Id */
3655 queue_push(&solv->ruletojob, i);
3657 case SOLVER_ERASE_SOLVABLE:
3658 s = pool->solvables + what;
3659 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase solvable %s\n", solvable2str(pool, s));
3660 addrule(solv, -what, 0); /* remove by Id */
3661 queue_push(&solv->ruletojob, i);
3663 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
3664 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3665 if (how == SOLVER_INSTALL_SOLVABLE_NAME)
3666 POOL_DEBUG(SAT_DEBUG_JOB, "job: install name %s\n", dep2str(pool, what));
3667 if (how == SOLVER_INSTALL_SOLVABLE_PROVIDES)
3668 POOL_DEBUG(SAT_DEBUG_JOB, "job: install provides %s\n", dep2str(pool, what));
3670 name = (how == SOLVER_INSTALL_SOLVABLE_NAME) ? what : 0;
3671 while (ISRELDEP(name))
3673 Reldep *rd = GETRELDEP(pool, name);
3676 FOR_PROVIDES(p, pp, what)
3678 /* if by name, ensure that the name matches */
3679 if (name && pool->solvables[p].name != name)
3685 /* no provider, make this an impossible rule */
3686 queue_push(&q, -SYSTEMSOLVABLE);
3689 p = queue_shift(&q); /* get first provider */
3691 d = 0; /* single provider ? -> make assertion */
3693 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
3694 addrule(solv, p, d); /* add 'requires' rule */
3695 queue_push(&solv->ruletojob, i);
3697 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
3698 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3699 if (how == SOLVER_ERASE_SOLVABLE_NAME)
3700 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase name %s\n", dep2str(pool, what));
3701 if (how == SOLVER_ERASE_SOLVABLE_PROVIDES)
3702 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase provides %s\n", dep2str(pool, what));
3703 name = (how == SOLVER_ERASE_SOLVABLE_NAME) ? what : 0;
3704 while (ISRELDEP(name))
3706 Reldep *rd = GETRELDEP(pool, name);
3709 FOR_PROVIDES(p, pp, what)
3711 /* if by name, ensure that the name matches */
3712 if (name && pool->solvables[p].name != name)
3714 addrule(solv, -p, 0); /* add 'remove' rule */
3715 queue_push(&solv->ruletojob, i);
3718 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
3719 s = pool->solvables + what;
3720 POOL_DEBUG(SAT_DEBUG_JOB, "job: update %s\n", solvable2str(pool, s));
3721 addupdaterule(solv, s, 0);
3722 queue_push(&solv->ruletojob, i);
3725 IF_POOLDEBUG (SAT_DEBUG_JOB)
3728 if (solv->nrules == oldnrules)
3729 POOL_DEBUG(SAT_DEBUG_JOB, " - no rule created\n");
3730 for (j = oldnrules; j < solv->nrules; j++)
3732 POOL_DEBUG(SAT_DEBUG_JOB, " - job ");
3733 printrule(solv, SAT_DEBUG_JOB, solv->rules + j);
3737 assert(solv->ruletojob.count == solv->nrules - solv->jobrules);
3740 * now add system rules
3744 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** Add system rules ***\n");
3747 solv->systemrules = solv->nrules;
3750 * create rules for updating installed solvables
3754 if (installed && !solv->allowuninstall)
3755 { /* loop over all installed solvables */
3756 /* we create all update rules, but disable some later on depending on the job */
3757 for (i = installed->start, s = pool->solvables + i; i < installed->end; i++, s++)
3759 /* no system rules for patch atoms */
3760 if (s->freshens && !s->supplements)
3762 const char *name = id2str(pool, s->name);
3763 if (name[0] == 'a' && !strncmp(name, "atom:", 5))
3765 addrule(solv, 0, 0);
3769 if (s->repo == installed)
3770 addupdaterule(solv, s, 0); /* allowall = 0 */
3772 addrule(solv, 0, 0); /* create dummy rule */
3774 /* consistency check: we added a rule for _every_ system solvable */
3775 assert(solv->nrules - solv->systemrules == installed->end - installed->start);
3778 /* create special weak system rules */
3779 /* those are used later on to keep a version of the installed packages in
3781 if (installed && installed->nsolvables)
3783 solv->weaksystemrules = sat_calloc(installed->end - installed->start, sizeof(Id));
3784 FOR_REPO_SOLVABLES(installed, p, s)
3786 policy_findupdatepackages(solv, s, &q, 1);
3788 solv->weaksystemrules[p - installed->start] = pool_queuetowhatprovides(pool, &q);
3792 /* free unneeded memory */
3793 map_free(&addedmap);
3796 solv->weakrules = solv->nrules;
3798 /* try real hard to keep packages installed */
3801 FOR_REPO_SOLVABLES(installed, p, s)
3803 /* FIXME: can't work with refine_suggestion! */
3804 /* need to always add the rule but disable it */
3805 if (MAPTST(&solv->noupdate, p - installed->start))
3807 d = solv->weaksystemrules[p - installed->start];
3808 addrule(solv, p, d);
3812 /* all new rules are learnt after this point */
3813 solv->learntrules = solv->nrules;
3815 /* disable system rules that conflict with our job */
3816 disableupdaterules(solv, job, -1);
3818 /* make decisions based on job/system assertions */
3819 makeruledecisions(solv);
3821 /* create watches chains */
3824 POOL_DEBUG(SAT_DEBUG_STATS, "problems so far: %d\n", solv->problems.count);
3827 run_solver(solv, solv->dontinstallrecommended ? 0 : 1, 1);
3829 /* find recommended packages */
3830 if (!solv->problems.count && solv->dontinstallrecommended)
3832 Id rec, *recp, p, *pp;
3834 /* create map of all suggests that are still open */
3835 solv->recommends_index = -1;
3836 MAPZERO(&solv->recommendsmap);
3837 for (i = 0; i < solv->decisionq.count; i++)
3839 p = solv->decisionq.elements[i];
3842 s = pool->solvables + p;
3845 recp = s->repo->idarraydata + s->recommends;
3846 while ((rec = *recp++) != 0)
3848 FOR_PROVIDES(p, pp, rec)
3849 if (solv->decisionmap[p] > 0)
3852 continue; /* already fulfilled */
3853 FOR_PROVIDES(p, pp, rec)
3854 MAPSET(&solv->recommendsmap, p);
3858 for (i = 1; i < pool->nsolvables; i++)
3860 if (solv->decisionmap[i] != 0)
3862 s = pool->solvables + i;
3863 if (!MAPTST(&solv->recommendsmap, i))
3865 if (!s->supplements)
3867 if (!pool_installable(pool, s))
3869 if (!solver_is_supplementing(solv, s))
3872 queue_push(&solv->recommendations, i);
3874 /* we use MODE_SUGGEST here so that repo prio is ignored */
3875 policy_filter_unwanted(solv, &solv->recommendations, 0, POLICY_MODE_SUGGEST);
3878 /* find suggested packages */
3879 if (!solv->problems.count)
3881 Id sug, *sugp, p, *pp;
3883 /* create map of all suggests that are still open */
3884 solv->recommends_index = -1;
3885 MAPZERO(&solv->suggestsmap);
3886 for (i = 0; i < solv->decisionq.count; i++)
3888 p = solv->decisionq.elements[i];
3891 s = pool->solvables + p;
3894 sugp = s->repo->idarraydata + s->suggests;
3895 while ((sug = *sugp++) != 0)
3897 FOR_PROVIDES(p, pp, sug)
3898 if (solv->decisionmap[p] > 0)
3901 continue; /* already fulfilled */
3902 FOR_PROVIDES(p, pp, sug)
3903 MAPSET(&solv->suggestsmap, p);
3907 for (i = 1; i < pool->nsolvables; i++)
3909 if (solv->decisionmap[i] != 0)
3911 s = pool->solvables + i;
3912 if (!MAPTST(&solv->suggestsmap, i))
3916 if (!pool_installable(pool, s))
3918 if (!solver_is_enhancing(solv, s))
3921 queue_push(&solv->suggestions, i);
3923 policy_filter_unwanted(solv, &solv->suggestions, 0, POLICY_MODE_SUGGEST);
3926 if (solv->problems.count)
3927 problems_to_solutions(solv, job);
3930 /***********************************************************************/
3942 struct mptree *mptree;
3952 solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
3954 struct ducbdata *cbd = cbdata;
3957 if (data != cbd->olddata)
3959 Id dn, mp, comp, *dirmap, *dirs;
3961 const char *compstr;
3962 struct mptree *mptree;
3964 /* create map from dir to mptree */
3965 cbd->dirmap = sat_free(cbd->dirmap);
3967 dirmap = sat_calloc(data->dirpool.ndirs, sizeof(Id));
3968 mptree = cbd->mptree;
3970 for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++)
3984 if (!mptree[mp].child)
3989 if (data->localpool)
3990 compstr = stringpool_id2str(&data->spool, comp);
3992 compstr = id2str(data->repo->pool, comp);
3993 compl = strlen(compstr);
3994 for (i = mptree[mp].child; i; i = mptree[i].sibling)
3995 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
3997 dirmap[dn] = i ? i : -mp;
3999 /* change dirmap to point to mountpoint instead of mptree */
4000 for (dn = 0; dn < data->dirpool.ndirs; dn++)
4003 dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint;
4005 cbd->dirmap = dirmap;
4006 cbd->nmap = data->dirpool.ndirs;
4007 cbd->olddata = data;
4009 if (value->id < 0 || value->id >= cbd->nmap)
4011 mp = cbd->dirmap[value->id];
4014 if (cbd->addsub > 0)
4016 cbd->mps[mp].kbytes += value->num;
4017 cbd->mps[mp].files += value->num2;
4021 cbd->mps[mp].kbytes -= value->num;
4022 cbd->mps[mp].files -= value->num2;
4028 propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint)
4031 if (mptree[pos].mountpoint == -1)
4032 mptree[pos].mountpoint = mountpoint;
4034 mountpoint = mptree[pos].mountpoint;
4035 for (i = mptree[pos].child; i; i = mptree[i].sibling)
4036 propagate_mountpoints(mptree, i, mountpoint);
4039 #define MPTREE_BLOCK 15
4042 solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
4044 Pool *pool = solv->pool;
4047 const char *path, *compstr;
4048 struct mptree *mptree;
4053 struct ducbdata cbd;
4061 mptree = sat_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK);
4064 mptree[0].sibling = 0;
4065 mptree[0].child = 0;
4067 mptree[0].compl = 0;
4068 mptree[0].mountpoint = -1;
4071 /* create component tree */
4072 for (mp = 0; mp < nmps; mp++)
4077 path = mps[mp].path;
4082 if ((p = strchr(path, '/')) == 0)
4085 compl = strlen(compstr);
4096 for (i = mptree[pos].child; i; i = mptree[i].sibling)
4097 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
4101 /* create new node */
4102 mptree = sat_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK);
4104 mptree[i].sibling = mptree[pos].child;
4105 mptree[i].child = 0;
4106 mptree[i].comp = compstr;
4107 mptree[i].compl = compl;
4108 mptree[i].mountpoint = -1;
4109 mptree[pos].child = i;
4113 mptree[pos].mountpoint = mp;
4116 propagate_mountpoints(mptree, 0, mptree[0].mountpoint);
4119 for (i = 0; i < nmptree; i++)
4121 printf("#%d sibling: %d\n", i, mptree[i].sibling);
4122 printf("#%d child: %d\n", i, mptree[i].child);
4123 printf("#%d comp: %s\n", i, mptree[i].comp);
4124 printf("#%d compl: %d\n", i, mptree[i].compl);
4125 printf("#%d mountpont: %d\n", i, mptree[i].mountpoint);
4129 cbd.mptree = mptree;
4131 /* create list of solvables that have to be installed */
4132 /* (this is actually just a simple sort) */
4133 map_init(&installmap, pool->nsolvables);
4134 for (i = 1; i < solv->decisionq.count; i++)
4136 Id sp = solv->decisionq.elements[i];
4139 s = pool->solvables + sp;
4142 if (solv->installed && s->repo == solv->installed)
4144 MAPSET(&installmap, sp);
4146 /* run through install solvable dudata */
4148 for (i = 1; i < pool->nsolvables; i++)
4150 if (!MAPTST(&installmap, i))
4152 s = pool->solvables + i;
4153 repo_search(s->repo, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
4155 map_free(&installmap);
4156 /* run through erase solvable dudata */
4157 if (solv->installed)
4160 FOR_REPO_SOLVABLES(solv->installed, i, s)
4162 if (solv->decisionmap[i] >= 0)
4164 repo_search(solv->installed, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
4167 sat_free(cbd.dirmap);
4172 solver_calc_installsizechange(Solver *solv)
4174 Pool *pool = solv->pool;
4180 for (i = 1; i < solv->decisionq.count; i++)
4182 Id p = solv->decisionq.elements[i];
4185 s = pool->solvables + p;
4188 if (solv->installed && s->repo == solv->installed)
4190 change += repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
4192 if (solv->installed)
4194 FOR_REPO_SOLVABLES(solv->installed, p, s)
4195 if (solv->decisionmap[p] < 0)
4196 change -= repo_lookup_num(s, SOLVABLE_INSTALLSIZE);