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 solv->decisionmap[vv] = 0;
1937 solv->decisionq.count--;
1938 solv->decisionq_why.count--;
1939 solv->propagate_index = solv->decisionq.count;
1941 while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] <= -level)
1943 solv->branches.count--;
1944 while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= 0)
1945 solv->branches.count--;
1947 solv->recommends_index = -1;
1952 * watch2onhighest - put watch2 on literal with highest level
1956 watch2onhighest(Solver *solv, Rule *r)
1962 return; /* binary rule, both watches are set */
1963 dp = solv->pool->whatprovidesdata + r->d;
1964 while ((v = *dp++) != 0)
1966 l = solv->decisionmap[v < 0 ? -v : v];
1981 * add free decision to decisionq, increase level and
1982 * propagate decision, return if no conflict.
1983 * in conflict case, analyze conflict rule, add resulting
1984 * rule to learnt rule set, make decision from learnt
1985 * rule (always unit) and re-propagate.
1987 * returns the new solver level or 0 if unsolvable
1992 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1994 Pool *pool = solv->pool;
2003 solv->decisionmap[decision] = level;
2005 solv->decisionmap[-decision] = -level;
2006 queue_push(&solv->decisionq, decision);
2007 queue_push(&solv->decisionq_why, 0);
2011 r = propagate(solv, level);
2015 return analyze_unsolvable(solv, r, disablerules);
2016 POOL_DEBUG(SAT_DEBUG_ANALYZE, "conflict with rule #%d\n", (int)(r - solv->rules));
2017 l = analyze(solv, level, r, &p, &d, &why); /* learnt rule in p and d */
2018 assert(l > 0 && l < level);
2019 POOL_DEBUG(SAT_DEBUG_ANALYZE, "reverting decisions (level %d -> %d)\n", level, l);
2021 revert(solv, level);
2022 r = addrule(solv, p, d); /* p requires d */
2024 assert(solv->learnt_why.count == (r - solv->rules) - solv->learntrules);
2025 queue_push(&solv->learnt_why, why);
2028 /* at least 2 literals, needs watches */
2029 watch2onhighest(solv, r);
2030 addwatches(solv, r);
2032 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
2033 queue_push(&solv->decisionq, p);
2034 queue_push(&solv->decisionq_why, r - solv->rules);
2035 IF_POOLDEBUG (SAT_DEBUG_ANALYZE)
2037 POOL_DEBUG(SAT_DEBUG_ANALYZE, "decision: ");
2038 printruleelement(solv, SAT_DEBUG_ANALYZE, 0, p);
2039 POOL_DEBUG(SAT_DEBUG_ANALYZE, "new rule: ");
2040 printrule(solv, SAT_DEBUG_ANALYZE, r);
2048 * install best package from the queue. We add an extra package, inst, if
2049 * provided. See comment in weak install section.
2051 * returns the new solver level or 0 if unsolvable
2055 selectandinstall(Solver *solv, int level, Queue *dq, Id inst, int disablerules)
2057 Pool *pool = solv->pool;
2061 if (dq->count > 1 || inst)
2062 policy_filter_unwanted(solv, dq, inst, POLICY_MODE_CHOOSE);
2067 /* choose the supplemented one */
2068 for (i = 0; i < dq->count; i++)
2069 if (solver_is_supplementing(solv, pool->solvables + dq->elements[i]))
2073 for (i = 1; i < dq->count; i++)
2074 queue_push(&solv->branches, dq->elements[i]);
2075 queue_push(&solv->branches, -level);
2079 p = dq->elements[i];
2081 POOL_DEBUG(SAT_DEBUG_POLICY, "installing %s\n", solvable2str(pool, pool->solvables + p));
2083 return setpropagatelearn(solv, level, p, disablerules);
2087 /*-----------------------------------------------------------------*/
2088 /* Main solver interface */
2093 * create solver structure
2095 * pool: all available solvables
2096 * installed: installed Solvables
2099 * Upon solving, rules are created to flag the Solvables
2100 * of the 'installed' Repo as installed.
2104 solver_create(Pool *pool, Repo *installed)
2107 solv = (Solver *)sat_calloc(1, sizeof(Solver));
2109 solv->installed = installed;
2111 queue_init(&solv->ruletojob);
2112 queue_init(&solv->decisionq);
2113 queue_init(&solv->decisionq_why);
2114 queue_init(&solv->problems);
2115 queue_init(&solv->suggestions);
2116 queue_init(&solv->learnt_why);
2117 queue_init(&solv->learnt_pool);
2118 queue_init(&solv->branches);
2119 queue_init(&solv->covenantq);
2121 map_init(&solv->recommendsmap, pool->nsolvables);
2122 map_init(&solv->suggestsmap, pool->nsolvables);
2123 map_init(&solv->noupdate, installed ? installed->end - installed->start : 0);
2124 solv->recommends_index = 0;
2126 solv->decisionmap = (Id *)sat_calloc(pool->nsolvables, sizeof(Id));
2128 solv->rules = sat_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK);
2129 memset(solv->rules, 0, sizeof(Rule));
2140 solver_free(Solver *solv)
2142 queue_free(&solv->ruletojob);
2143 queue_free(&solv->decisionq);
2144 queue_free(&solv->decisionq_why);
2145 queue_free(&solv->learnt_why);
2146 queue_free(&solv->learnt_pool);
2147 queue_free(&solv->problems);
2148 queue_free(&solv->suggestions);
2149 queue_free(&solv->branches);
2150 queue_free(&solv->covenantq);
2152 map_free(&solv->recommendsmap);
2153 map_free(&solv->suggestsmap);
2154 map_free(&solv->noupdate);
2156 sat_free(solv->decisionmap);
2157 sat_free(solv->rules);
2158 sat_free(solv->watches);
2159 sat_free(solv->weaksystemrules);
2160 sat_free(solv->obsoletes);
2161 sat_free(solv->obsoletes_data);
2166 /*-------------------------------------------------------*/
2171 * all rules have been set up, now actually run the solver
2176 run_solver(Solver *solv, int disablerules, int doweak)
2184 Pool *pool = solv->pool;
2187 IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION)
2189 POOL_DEBUG (SAT_DEBUG_RULE_CREATION, "number of rules: %d\n", solv->nrules);
2190 for (i = 0; i < solv->nrules; i++)
2191 printrule(solv, SAT_DEBUG_RULE_CREATION, solv->rules + i);
2194 POOL_DEBUG(SAT_DEBUG_STATS, "initial decisions: %d\n", solv->decisionq.count);
2196 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2197 printdecisions(solv);
2199 /* start SAT algorithm */
2201 systemlevel = level + 1;
2202 POOL_DEBUG(SAT_DEBUG_STATS, "solving...\n");
2213 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "propagating (propagate_index: %d; size decisionq: %d)...\n", solv->propagate_index, solv->decisionq.count);
2214 if ((r = propagate(solv, level)) != 0)
2216 if (analyze_unsolvable(solv, r, disablerules))
2224 * installed packages
2227 if (level < systemlevel && solv->installed && solv->installed->nsolvables)
2229 if (!solv->updatesystem)
2231 /* try to keep as many packages as possible */
2232 POOL_DEBUG(SAT_DEBUG_STATS, "installing system packages\n");
2233 for (i = solv->installed->start, n = 0; ; i++)
2235 if (n == solv->installed->nsolvables)
2237 if (i == solv->installed->end)
2238 i = solv->installed->start;
2239 s = pool->solvables + i;
2240 if (s->repo != solv->installed)
2243 if (solv->decisionmap[i] != 0)
2245 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "keeping %s\n", solvable2str(pool, s));
2247 level = setpropagatelearn(solv, level, i, disablerules);
2253 if (level <= olevel)
2257 if (solv->weaksystemrules)
2259 POOL_DEBUG(SAT_DEBUG_STATS, "installing weak system packages\n");
2260 for (i = solv->installed->start; i < solv->installed->end; i++)
2262 if (pool->solvables[i].repo != solv->installed)
2264 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->installed->start] == 0))
2266 /* noupdate is set if a job is erasing the installed solvable or installing a specific version */
2267 if (MAPTST(&solv->noupdate, i - solv->installed->start))
2270 if (solv->weaksystemrules[i - solv->installed->start])
2272 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->installed->start];
2273 while ((p = *dp++) != 0)
2275 if (solv->decisionmap[p] > 0)
2277 if (solv->decisionmap[p] == 0)
2281 continue; /* update package already installed */
2283 if (!dq.count && solv->decisionmap[i] != 0)
2286 /* FIXME: i is handled a bit different because we do not want
2287 * to have it pruned just because it is not recommened.
2288 * we should not prune installed packages instead */
2289 level = selectandinstall(solv, level, &dq, (solv->decisionmap[i] ? 0 : i), disablerules);
2295 if (level <= olevel)
2298 if (i < solv->installed->end)
2301 systemlevel = level;
2308 POOL_DEBUG(SAT_DEBUG_STATS, "deciding unresolved rules\n");
2309 for (i = 1, n = 1; ; i++, n++)
2311 if (n == solv->nrules)
2313 if (i == solv->nrules)
2315 r = solv->rules + i;
2316 if (!r->w1) /* ignore disabled rules */
2321 /* binary or unary rule */
2322 /* need two positive undecided literals */
2323 if (r->p < 0 || r->w2 <= 0)
2325 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2327 queue_push(&dq, r->p);
2328 queue_push(&dq, r->w2);
2333 * all negative literals are installed
2334 * no positive literal is installed
2335 * i.e. the rule is not fulfilled and we
2336 * just need to decide on the positive literals
2340 if (solv->decisionmap[-r->p] <= 0)
2345 if (solv->decisionmap[r->p] > 0)
2347 if (solv->decisionmap[r->p] == 0)
2348 queue_push(&dq, r->p);
2350 dp = pool->whatprovidesdata + r->d;
2351 while ((p = *dp++) != 0)
2355 if (solv->decisionmap[-p] <= 0)
2360 if (solv->decisionmap[p] > 0)
2362 if (solv->decisionmap[p] == 0)
2369 /* dq.count < 2 cannot happen as this means that
2370 * the rule is unit */
2371 assert(dq.count > 1);
2372 IF_POOLDEBUG (SAT_DEBUG_PROPAGATE)
2374 POOL_DEBUG(SAT_DEBUG_PROPAGATE, "unfulfilled ");
2375 printrule(solv, SAT_DEBUG_PROPAGATE, r);
2379 level = selectandinstall(solv, level, &dq, 0, disablerules);
2385 if (level < systemlevel)
2388 } /* for(), decide */
2390 if (n != solv->nrules) /* continue if level < systemlevel */
2393 if (doweak && !solv->problems.count)
2397 POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended packages\n");
2398 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS)
2400 for (i = 1; i < solv->decisionq.count; i++)
2402 p = solv->decisionq.elements[i];
2403 if (p > 0 && pool->solvables[p].repo == solv->installed)
2404 solv->decisionmap[p] = -solv->decisionmap[p];
2408 for (i = 1; i < pool->nsolvables; i++)
2410 if (solv->decisionmap[i] < 0)
2412 if (solv->decisionmap[i] > 0)
2414 Id *recp, rec, *pp, p;
2415 s = pool->solvables + i;
2416 /* installed, check for recommends */
2417 /* XXX need to special case AND ? */
2420 recp = s->repo->idarraydata + s->recommends;
2421 while ((rec = *recp++) != 0)
2424 FOR_PROVIDES(p, pp, rec)
2426 if (solv->decisionmap[p] > 0)
2431 else if (solv->decisionmap[p] == 0)
2433 queue_pushunique(&dq, p);
2441 s = pool->solvables + i;
2442 if (!s->supplements && !s->freshens)
2444 if (!pool_installable(pool, s))
2446 if (solver_is_supplementing(solv, s))
2447 queue_pushunique(&dq, i);
2450 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS)
2452 for (i = 1; i < solv->decisionq.count; i++)
2454 p = solv->decisionq.elements[i];
2455 if (p > 0 && pool->solvables[p].repo == solv->installed)
2456 solv->decisionmap[p] = -solv->decisionmap[p];
2462 policy_filter_unwanted(solv, &dq, 0, POLICY_MODE_RECOMMEND);
2464 POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended %s\n", solvable2str(pool, pool->solvables + p));
2465 level = setpropagatelearn(solv, level, p, 0);
2470 if (solv->solution_callback)
2472 solv->solution_callback(solv, solv->solution_callback_data);
2473 if (solv->branches.count)
2475 int i = solv->branches.count - 1;
2476 int l = -solv->branches.elements[i];
2478 if (solv->branches.elements[i - 1] < 0)
2480 p = solv->branches.elements[i];
2481 POOL_DEBUG(SAT_DEBUG_STATS, "branching with %s\n", solvable2str(pool, pool->solvables + p));
2483 for (j = i + 1; j < solv->branches.count; j++)
2484 queue_push(&dq, solv->branches.elements[j]);
2485 solv->branches.count = i;
2487 revert(solv, level);
2489 for (j = 0; j < dq.count; j++)
2490 queue_push(&solv->branches, dq.elements[j]);
2492 level = setpropagatelearn(solv, level, p, disablerules);
2500 /* all branches done, we're finally finished */
2504 /* minimization step */
2505 if (solv->branches.count)
2507 int l = 0, lasti = -1, lastl = -1;
2509 for (i = solv->branches.count - 1; i >= 0; i--)
2511 p = solv->branches.elements[i];
2514 else if (p > 0 && solv->decisionmap[p] > l + 1)
2522 /* kill old solvable so that we do not loop */
2523 p = solv->branches.elements[lasti];
2524 solv->branches.elements[lasti] = 0;
2525 POOL_DEBUG(SAT_DEBUG_STATS, "minimizing %d -> %d with %s\n", solv->decisionmap[p], l, solvable2str(pool, pool->solvables + p));
2528 revert(solv, level);
2530 level = setpropagatelearn(solv, level, p, disablerules);
2547 * at this point, all rules that led to conflicts are disabled.
2548 * we re-enable all rules of a problem set but rule "sug", then
2549 * continue to disable more rules until there as again a solution.
2552 /* FIXME: think about conflicting assertions */
2555 refine_suggestion(Solver *solv, Queue *job, Id *problem, Id sug, Queue *refined)
2557 Pool *pool = solv->pool;
2564 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
2566 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion start\n");
2567 for (i = 0; problem[i]; i++)
2569 if (problem[i] == sug)
2570 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "=> ");
2571 printproblem(solv, problem[i]);
2574 queue_init(&disabled);
2575 queue_empty(refined);
2576 queue_push(refined, sug);
2578 /* re-enable all problem rules with the exception of "sug"(gests) */
2582 for (i = 0; problem[i]; i++)
2583 if (problem[i] != sug)
2584 enableproblem(solv, problem[i]);
2587 disableupdaterules(solv, job, -(sug + 1));
2591 /* re-enable as many weak rules as possible */
2592 for (i = solv->weakrules; i < solv->learntrules; i++)
2594 r = solv->rules + i;
2596 enablerule(solv, r);
2599 queue_empty(&solv->problems);
2600 revert(solv, 1); /* XXX move to reset_solver? */
2603 if (!solv->problems.count)
2604 run_solver(solv, 0, 0);
2606 if (!solv->problems.count)
2608 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no more problems!\n");
2609 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2610 printdecisions(solv);
2611 break; /* great, no more problems */
2613 disabledcnt = disabled.count;
2614 /* start with 1 to skip over proof index */
2615 for (i = 1; i < solv->problems.count - 1; i++)
2617 /* ignore solutions in refined */
2618 v = solv->problems.elements[i];
2620 break; /* end of problem reached */
2621 for (j = 0; problem[j]; j++)
2622 if (problem[j] != sug && problem[j] == v)
2626 queue_push(&disabled, v);
2628 if (disabled.count == disabledcnt)
2630 /* no solution found, this was an invalid suggestion! */
2631 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "no solution found!\n");
2635 if (disabled.count == disabledcnt + 1)
2637 /* just one suggestion, add it to refined list */
2638 v = disabled.elements[disabledcnt];
2639 queue_push(refined, v);
2640 disableproblem(solv, v);
2642 disableupdaterules(solv, job, -(v + 1));
2646 /* more than one solution, disable all */
2647 /* do not push anything on refine list */
2648 IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS)
2650 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "more than one solution found:\n");
2651 for (i = disabledcnt; i < disabled.count; i++)
2652 printproblem(solv, disabled.elements[i]);
2654 for (i = disabledcnt; i < disabled.count; i++)
2655 disableproblem(solv, disabled.elements[i]);
2658 /* all done, get us back into the same state as before */
2659 /* enable refined rules again */
2660 for (i = 0; i < disabled.count; i++)
2661 enableproblem(solv, disabled.elements[i]);
2662 /* disable problem rules again */
2663 for (i = 0; problem[i]; i++)
2664 disableproblem(solv, problem[i]);
2665 disableupdaterules(solv, job, -1);
2666 POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "refine_suggestion end\n");
2670 problems_to_solutions(Solver *solv, Queue *job)
2672 Pool *pool = solv->pool;
2680 if (!solv->problems.count)
2682 queue_clone(&problems, &solv->problems);
2683 queue_init(&solution);
2684 queue_init(&solutions);
2685 /* copy over proof index */
2686 queue_push(&solutions, problems.elements[0]);
2687 problem = problems.elements + 1;
2688 for (i = 1; i < problems.count; i++)
2690 Id v = problems.elements[i];
2693 /* mark end of this problem */
2694 queue_push(&solutions, 0);
2695 queue_push(&solutions, 0);
2696 if (i + 1 == problems.count)
2698 /* copy over proof of next problem */
2699 queue_push(&solutions, problems.elements[i + 1]);
2701 problem = problems.elements + i + 1;
2704 refine_suggestion(solv, job, problem, v, &solution);
2705 if (!solution.count)
2706 continue; /* this solution didn't work out */
2708 for (j = 0; j < solution.count; j++)
2710 why = solution.elements[j];
2711 /* must be either job descriptor or system rule */
2712 assert(why < 0 || (why >= solv->systemrules && why < solv->weakrules));
2714 printproblem(solv, why);
2718 /* job descriptor */
2719 queue_push(&solutions, 0);
2720 queue_push(&solutions, -why);
2724 /* system rule, find replacement package */
2726 p = solv->installed->start + (why - solv->systemrules);
2727 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2729 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2732 if (*dp >= solv->installed->start && *dp < solv->installed->start + solv->installed->nsolvables)
2734 if (solv->decisionmap[*dp] > 0)
2741 queue_push(&solutions, p);
2742 queue_push(&solutions, rp);
2745 /* mark end of this solution */
2746 queue_push(&solutions, 0);
2747 queue_push(&solutions, 0);
2749 queue_free(&solution);
2750 queue_free(&problems);
2751 /* copy queue over to solutions */
2752 queue_free(&solv->problems);
2753 queue_clone(&solv->problems, &solutions);
2755 /* bring solver back into problem state */
2756 revert(solv, 1); /* XXX move to reset_solver? */
2759 assert(solv->problems.count == solutions.count);
2760 queue_free(&solutions);
2764 solver_next_problem(Solver *solv, Id problem)
2768 return solv->problems.count ? 1 : 0;
2769 pp = solv->problems.elements + problem;
2770 while (pp[0] || pp[1])
2774 while (pp[0] || pp[1])
2779 problem = pp - solv->problems.elements;
2780 if (problem >= solv->problems.count)
2786 solver_next_solution(Solver *solv, Id problem, Id solution)
2792 pp = solv->problems.elements + solution;
2793 return pp[0] || pp[1] ? solution : 0;
2795 pp = solv->problems.elements + solution;
2796 while (pp[0] || pp[1])
2799 solution = pp - solv->problems.elements;
2800 return pp[0] || pp[1] ? solution : 0;
2804 solver_next_solutionelement(Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp)
2807 element = element ? element + 2 : solution;
2808 pp = solv->problems.elements + element;
2809 if (!(pp[0] || pp[1]))
2818 * create obsoletesmap from solver decisions
2819 * required for decision handling
2823 create_decisions_obsoletesmap(Solver *solv)
2825 Pool *pool = solv->pool;
2826 Repo *installed = solv->installed;
2827 Id p, *obsoletesmap = NULL;
2831 obsoletesmap = (Id *)sat_calloc(pool->nsolvables, sizeof(Id));
2834 for (i = 0; i < solv->decisionq.count; i++)
2838 n = solv->decisionq.elements[i];
2841 if (n == SYSTEMSOLVABLE)
2843 s = pool->solvables + n;
2844 if (s->repo == installed) /* obsoletes don't count for already installed packages */
2846 FOR_PROVIDES(p, pp, s->name)
2847 if (s->name == pool->solvables[p].name)
2849 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
2851 obsoletesmap[p] = n;
2856 for (i = 0; i < solv->decisionq.count; i++)
2861 n = solv->decisionq.elements[i];
2864 if (n == SYSTEMSOLVABLE)
2866 s = pool->solvables + n;
2867 if (s->repo == installed) /* obsoletes don't count for already installed packages */
2871 obsp = s->repo->idarraydata + s->obsoletes;
2872 while ((obs = *obsp++) != 0)
2873 FOR_PROVIDES(p, pp, obs)
2875 if (pool->solvables[p].repo == installed && !obsoletesmap[p])
2877 obsoletesmap[p] = n;
2883 return obsoletesmap;
2892 printdecisions(Solver *solv)
2894 Pool *pool = solv->pool;
2895 Repo *installed = solv->installed;
2896 Id p, *obsoletesmap = create_decisions_obsoletesmap( solv );
2900 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions -----\n");
2902 /* print solvables to be erased */
2906 FOR_REPO_SOLVABLES(installed, p, s)
2908 if (solv->decisionmap[p] >= 0)
2910 if (obsoletesmap[p])
2912 POOL_DEBUG(SAT_DEBUG_RESULT, "erase %s\n", solvable2str(pool, s));
2916 /* print solvables to be installed */
2918 for (i = 0; i < solv->decisionq.count; i++)
2921 p = solv->decisionq.elements[i];
2924 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
2927 s = pool->solvables + p;
2928 POOL_DEBUG(SAT_DEBUG_SCHUBI, "level of %s is %d\n", solvable2str(pool, s), p);
2932 if (p == SYSTEMSOLVABLE)
2934 POOL_DEBUG(SAT_DEBUG_SCHUBI, "SYSTEMSOLVABLE\n");
2937 s = pool->solvables + p;
2938 if (installed && s->repo == installed)
2941 if (!obsoletesmap[p])
2943 POOL_DEBUG(SAT_DEBUG_RESULT, "install %s", solvable2str(pool, s));
2947 POOL_DEBUG(SAT_DEBUG_RESULT, "update %s", solvable2str(pool, s));
2948 POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes");
2949 for (j = installed->start; j < installed->end; j++)
2950 if (obsoletesmap[j] == p)
2951 POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j));
2952 POOL_DEBUG(SAT_DEBUG_RESULT, ")");
2954 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
2957 sat_free(obsoletesmap);
2959 if (solv->suggestions.count)
2961 POOL_DEBUG(SAT_DEBUG_RESULT, "\nsuggested packages:\n");
2962 for (i = 0; i < solv->suggestions.count; i++)
2964 s = pool->solvables + solv->suggestions.elements[i];
2965 POOL_DEBUG(SAT_DEBUG_RESULT, "- %s\n", solvable2str(pool, s));
2968 POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- Decisions end -----\n");
2971 /* this is basically the reverse of addrpmrulesforsolvable */
2973 solver_problemruleinfo(Solver *solv, Queue *job, Id rid, Id *depp, Id *sourcep, Id *targetp)
2975 Pool *pool = solv->pool;
2976 Repo *installed = solv->installed;
2980 Id p, *pp, req, *reqp, con, *conp, obs, *obsp, *dp;
2982 assert(rid < solv->weakrules);
2983 if (rid >= solv->systemrules)
2986 *sourcep = solv->installed->start + (rid - solv->systemrules);
2988 return SOLVER_PROBLEM_UPDATE_RULE;
2990 if (rid >= solv->jobrules)
2993 r = solv->rules + rid;
2994 p = solv->ruletojob.elements[rid - solv->jobrules];
2995 *depp = job->elements[p + 1];
2997 *targetp = job->elements[p];
2998 if (r->d == 0 && r->w2 == 0 && r->p == -SYSTEMSOLVABLE)
2999 return SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP;
3000 return SOLVER_PROBLEM_JOB_RULE;
3004 /* a rpm rule assertion */
3005 assert(rid != -SYSTEMSOLVABLE);
3006 s = pool->solvables - rid;
3007 if (installed && !solv->fixsystem && s->repo == installed)
3009 assert(!dontfix); /* dontfix packages never have a neg assertion */
3010 /* see why the package is not installable */
3011 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC && !pool_installable(pool, s))
3016 return SOLVER_PROBLEM_NOT_INSTALLABLE;
3018 /* check requires */
3019 assert(s->requires);
3020 reqp = s->repo->idarraydata + s->requires;
3021 while ((req = *reqp++) != 0)
3023 if (req == SOLVABLE_PREREQMARKER)
3025 dp = pool_whatprovides(pool, req);
3033 return SOLVER_PROBLEM_NOTHING_PROVIDES_DEP;
3035 r = solv->rules + rid;
3037 if (r->d == 0 && r->w2 == 0)
3039 /* an assertion. we don't store them as rpm rules, so
3043 s = pool->solvables - r->p;
3044 if (installed && !solv->fixsystem && s->repo == installed)
3046 if (r->d == 0 && r->w2 < 0)
3048 /* a package conflict */
3049 Solvable *s2 = pool->solvables - r->w2;
3052 if (installed && !solv->fixsystem && s2->repo == installed)
3055 /* if both packages have the same name and at least one of them
3056 * is not installed, they conflict */
3057 if (s->name == s2->name && (!installed || (s->repo != installed || s2->repo != installed)))
3062 return SOLVER_PROBLEM_SAME_NAME;
3065 /* check conflicts in both directions */
3068 conp = s->repo->idarraydata + s->conflicts;
3069 while ((con = *conp++) != 0)
3071 FOR_PROVIDES(p, pp, con)
3073 if (dontfix && pool->solvables[p].repo == installed)
3080 return SOLVER_PROBLEM_PACKAGE_CONFLICT;
3086 conp = s2->repo->idarraydata + s2->conflicts;
3087 while ((con = *conp++) != 0)
3089 FOR_PROVIDES(p, pp, con)
3091 if (dontfix2 && pool->solvables[p].repo == installed)
3098 return SOLVER_PROBLEM_PACKAGE_CONFLICT;
3102 /* check obsoletes in both directions */
3103 if ((!installed || s->repo != installed) && s->obsoletes)
3105 obsp = s->repo->idarraydata + s->obsoletes;
3106 while ((obs = *obsp++) != 0)
3108 FOR_PROVIDES(p, pp, obs)
3115 return SOLVER_PROBLEM_PACKAGE_OBSOLETES;
3119 if ((!installed || s2->repo != installed) && s2->obsoletes)
3121 obsp = s2->repo->idarraydata + s2->obsoletes;
3122 while ((obs = *obsp++) != 0)
3124 FOR_PROVIDES(p, pp, obs)
3131 return SOLVER_PROBLEM_PACKAGE_OBSOLETES;
3135 /* all cases checked, can't happen */
3138 /* simple requires */
3139 assert(s->requires);
3140 reqp = s->repo->idarraydata + s->requires;
3141 while ((req = *reqp++) != 0)
3143 if (req == SOLVABLE_PREREQMARKER)
3145 dp = pool_whatprovides(pool, req);
3148 if (*dp == r->w2 && dp[1] == 0)
3151 else if (dp - pool->whatprovidesdata == r->d)
3158 return SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE;
3162 findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, Id *jobrp)
3165 Id lreqr, lconr, lsysr, ljobr;
3169 lreqr = lconr = lsysr = ljobr = 0;
3170 while ((rid = solv->learnt_pool.elements[idx++]) != 0)
3172 if (rid >= solv->learntrules)
3173 findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr);
3174 else if (rid >= solv->systemrules)
3179 else if (rid >= solv->jobrules)
3186 r = solv->rules + rid;
3187 if (!r->d && r->w2 < 0)
3200 /* assertion, counts as require rule */
3201 /* ignore system solvable as we need useful info */
3202 if (rid == -SYSTEMSOLVABLE)
3204 if (!*reqrp || !reqassert)
3211 if (!*reqrp && lreqr)
3213 if (!*conrp && lconr)
3215 if (!*jobrp && ljobr)
3217 if (!*sysrp && lsysr)
3222 solver_findproblemrule(Solver *solv, Id problem)
3224 Id reqr, conr, sysr, jobr;
3225 Id idx = solv->problems.elements[problem - 1];
3226 reqr = conr = sysr = jobr = 0;
3227 findproblemrule_internal(solv, idx, &reqr, &conr, &sysr, &jobr);
3240 printprobleminfo(Solver *solv, Queue *job, Id problem)
3242 Pool *pool = solv->pool;
3244 Id dep, source, target;
3247 probr = solver_findproblemrule(solv, problem);
3248 switch (solver_problemruleinfo(solv, job, probr, &dep, &source, &target))
3250 case SOLVER_PROBLEM_UPDATE_RULE:
3251 s = pool_id2solvable(pool, source);
3252 POOL_DEBUG(SAT_DEBUG_RESULT, "problem with installed package %s\n", solvable2str(pool, s));
3254 case SOLVER_PROBLEM_JOB_RULE:
3255 POOL_DEBUG(SAT_DEBUG_RESULT, "conflicting requests\n");
3257 case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
3258 POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides requested %s\n", dep2str(pool, dep));
3260 case SOLVER_PROBLEM_NOT_INSTALLABLE:
3261 s = pool_id2solvable(pool, source);
3262 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s is not installable\n", solvable2str(pool, s));
3264 case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
3265 s = pool_id2solvable(pool, source);
3266 POOL_DEBUG(SAT_DEBUG_RESULT, "nothing provides %s needed by %s\n", dep2str(pool, dep), solvable2str(pool, s));
3268 case SOLVER_PROBLEM_SAME_NAME:
3269 s = pool_id2solvable(pool, source);
3270 s2 = pool_id2solvable(pool, target);
3271 POOL_DEBUG(SAT_DEBUG_RESULT, "cannot install both %s and %s\n", solvable2str(pool, s), solvable2str(pool, s2));
3273 case SOLVER_PROBLEM_PACKAGE_CONFLICT:
3274 s = pool_id2solvable(pool, source);
3275 s2 = pool_id2solvable(pool, target);
3276 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s conflicts with %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
3278 case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
3279 s = pool_id2solvable(pool, source);
3280 s2 = pool_id2solvable(pool, target);
3281 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s obsoletes %s provided by %s\n", solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
3283 case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
3284 s = pool_id2solvable(pool, source);
3285 POOL_DEBUG(SAT_DEBUG_RESULT, "package %s requires %s, but none of the providers can be installed\n", solvable2str(pool, s), dep2str(pool, dep));
3291 printsolutions(Solver *solv, Queue *job)
3293 Pool *pool = solv->pool;
3296 Id problem, solution, element;
3299 POOL_DEBUG(SAT_DEBUG_RESULT, "Encountered problems! Here are the solutions:\n\n");
3302 while ((problem = solver_next_problem(solv, problem)) != 0)
3304 POOL_DEBUG(SAT_DEBUG_RESULT, "Problem %d:\n", pcnt++);
3305 POOL_DEBUG(SAT_DEBUG_RESULT, "====================================\n");
3306 printprobleminfo(solv, job, problem);
3307 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
3309 while ((solution = solver_next_solution(solv, problem, solution)) != 0)
3312 while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0)
3316 /* job, rp is index into job queue */
3317 what = job->elements[rp];
3318 switch (job->elements[rp - 1])
3320 case SOLVER_INSTALL_SOLVABLE:
3321 s = pool->solvables + what;
3322 if (solv->installed && s->repo == solv->installed)
3323 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not keep %s installed\n", solvable2str(pool, s));
3325 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", solvable2str(pool, s));
3327 case SOLVER_ERASE_SOLVABLE:
3328 s = pool->solvables + what;
3329 if (solv->installed && s->repo == solv->installed)
3330 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", solvable2str(pool, s));
3332 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not forbid installation of %s\n", solvable2str(pool, s));
3334 case SOLVER_INSTALL_SOLVABLE_NAME:
3335 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install %s\n", dep2str(pool, what));
3337 case SOLVER_ERASE_SOLVABLE_NAME:
3338 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall %s\n", dep2str(pool, what));
3340 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3341 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install a solvable providing %s\n", dep2str(pool, what));
3343 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3344 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not deinstall all solvables providing %s\n", dep2str(pool, what));
3346 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3347 s = pool->solvables + what;
3348 POOL_DEBUG(SAT_DEBUG_RESULT, "- do not install most recent version of %s\n", solvable2str(pool, s));
3351 POOL_DEBUG(SAT_DEBUG_RESULT, "- do something different\n");
3357 /* policy, replace p with rp */
3358 s = pool->solvables + p;
3359 sd = rp ? pool->solvables + rp : 0;
3363 if (!solv->allowdowngrade && evrcmp(pool, s->evr, sd->evr, EVRCMP_MATCH_RELEASE) > 0)
3365 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow downgrade of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3368 if (!solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(solv, s, sd))
3370 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow architecture change of %s to %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3373 if (!solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(solv, s, sd))
3376 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));
3378 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));
3382 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow replacement of %s with %s\n", solvable2str(pool, s), solvable2str(pool, sd));
3386 POOL_DEBUG(SAT_DEBUG_RESULT, "- allow deinstallation of %s\n", solvable2str(pool, s));
3391 POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
3397 /* create reverse obsoletes map for installed solvables
3399 * for each installed solvable find which packages with *different* names
3400 * obsolete the solvable.
3401 * this index is used in policy_findupdatepackages if noupdateprovide is set.
3405 create_obsolete_index(Solver *solv)
3407 Pool *pool = solv->pool;
3409 Repo *installed = solv->installed;
3410 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
3413 if (!installed || !installed->nsolvables)
3415 solv->obsoletes = obsoletes = sat_calloc(installed->end - installed->start, sizeof(Id));
3416 for (i = 1; i < pool->nsolvables; i++)
3418 s = pool->solvables + i;
3419 if (s->repo == installed)
3423 if (!pool_installable(pool, s))
3425 obsp = s->repo->idarraydata + s->obsoletes;
3426 while ((obs = *obsp++) != 0)
3427 FOR_PROVIDES(p, pp, obs)
3429 if (pool->solvables[p].repo != installed)
3431 if (pool->solvables[p].name == s->name)
3433 obsoletes[p - installed->start]++;
3437 for (i = 0; i < installed->nsolvables; i++)
3440 n += obsoletes[i] + 1;
3443 solv->obsoletes_data = obsoletes_data = sat_calloc(n + 1, sizeof(Id));
3444 POOL_DEBUG(SAT_DEBUG_STATS, "obsoletes data: %d entries\n", n + 1);
3445 for (i = pool->nsolvables - 1; i > 0; i--)
3447 s = pool->solvables + i;
3448 if (s->repo == installed)
3452 if (!pool_installable(pool, s))
3454 obsp = s->repo->idarraydata + s->obsoletes;
3455 while ((obs = *obsp++) != 0)
3456 FOR_PROVIDES(p, pp, obs)
3458 if (pool->solvables[p].repo != installed)
3460 if (pool->solvables[p].name == s->name)
3462 p -= installed->start;
3463 if (obsoletes_data[obsoletes[p]] != i)
3464 obsoletes_data[--obsoletes[p]] = i;
3470 /*-----------------------------------------------------------------*/
3480 solver_solve(Solver *solv, Queue *job)
3482 Pool *pool = solv->pool;
3483 Repo *installed = solv->installed;
3486 Map addedmap; /* '1' == have rpm-rules for solvable */
3487 Id how, what, name, p, *pp, d;
3491 /* create whatprovides if not already there */
3492 if (!pool->whatprovides)
3493 pool_createwhatprovides(pool);
3495 /* create obsolete index if needed */
3496 if (solv->noupdateprovide)
3497 create_obsolete_index(solv);
3500 * create basic rule set of all involved packages
3501 * use addedmap bitmap to make sure we don't create rules twice
3505 map_init(&addedmap, pool->nsolvables);
3509 * always install our system solvable
3511 MAPSET(&addedmap, SYSTEMSOLVABLE);
3512 queue_push(&solv->decisionq, SYSTEMSOLVABLE);
3513 queue_push(&solv->decisionq_why, 0);
3514 solv->decisionmap[SYSTEMSOLVABLE] = 1;
3517 * create rules for all package that could be involved with the solving
3518 * so called: rpm rules
3523 oldnrules = solv->nrules;
3524 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for installed solvables ***\n");
3525 FOR_REPO_SOLVABLES(installed, p, s)
3526 addrpmrulesforsolvable(solv, s, &addedmap);
3527 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for installed solvables\n", solv->nrules - oldnrules);
3528 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for updaters of installed solvables ***\n");
3529 oldnrules = solv->nrules;
3530 FOR_REPO_SOLVABLES(installed, p, s)
3531 addrpmrulesforupdaters(solv, s, &addedmap, 1);
3532 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for updaters of installed solvables\n", solv->nrules - oldnrules);
3535 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for packages involved with a job ***\n");
3536 oldnrules = solv->nrules;
3537 for (i = 0; i < job->count; i += 2)
3539 how = job->elements[i];
3540 what = job->elements[i + 1];
3544 case SOLVER_INSTALL_SOLVABLE:
3545 addrpmrulesforsolvable(solv, pool->solvables + what, &addedmap);
3547 case SOLVER_INSTALL_SOLVABLE_NAME:
3548 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3549 name = (how == SOLVER_INSTALL_SOLVABLE_NAME) ? what : 0;
3550 while (ISRELDEP(name))
3552 Reldep *rd = GETRELDEP(pool, name);
3555 FOR_PROVIDES(p, pp, what)
3557 /* if by name, ensure that the name matches */
3558 if (name && pool->solvables[p].name != name)
3560 addrpmrulesforsolvable(solv, pool->solvables + p, &addedmap);
3563 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3564 /* dont allow downgrade */
3565 addrpmrulesforupdaters(solv, pool->solvables + what, &addedmap, 0);
3569 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules for packages involved in a job\n", solv->nrules - oldnrules);
3571 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** create rpm rules for recommended/suggested packages ***\n");
3573 oldnrules = solv->nrules;
3574 addrpmrulesforweak(solv, &addedmap);
3575 POOL_DEBUG(SAT_DEBUG_STATS, "added %d rpm rules because of weak dependencies\n", solv->nrules - oldnrules);
3577 IF_POOLDEBUG (SAT_DEBUG_STATS)
3579 int possible = 0, installable = 0;
3580 for (i = 1; i < pool->nsolvables; i++)
3582 if (pool_installable(pool, pool->solvables + i))
3584 if (MAPTST(&addedmap, i))
3587 POOL_DEBUG(SAT_DEBUG_STATS, "%d of %d installable solvables considered for solving (rules has been generated for)\n", possible, installable);
3591 * first pass done, we now have all the rpm rules we need.
3592 * unify existing rules before going over all job rules and
3594 * at this point the system is always solvable,
3595 * as an empty system (remove all packages) is a valid solution
3598 unifyrules(solv); /* remove duplicate rpm rules */
3599 solv->directdecisions = solv->decisionq.count;
3601 POOL_DEBUG(SAT_DEBUG_STATS, "decisions so far: %d\n", solv->decisionq.count);
3602 IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
3603 printdecisions (solv);
3606 * now add all job rules
3609 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** Add JOB rules ***\n");
3611 solv->jobrules = solv->nrules;
3613 for (i = 0; i < job->count; i += 2)
3615 oldnrules = solv->nrules;
3617 how = job->elements[i];
3618 what = job->elements[i + 1];
3621 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
3622 s = pool->solvables + what;
3623 POOL_DEBUG(SAT_DEBUG_JOB, "job: install solvable %s\n", solvable2str(pool, s));
3624 addrule(solv, what, 0); /* install by Id */
3625 queue_push(&solv->ruletojob, i);
3627 case SOLVER_ERASE_SOLVABLE:
3628 s = pool->solvables + what;
3629 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase solvable %s\n", solvable2str(pool, s));
3630 addrule(solv, -what, 0); /* remove by Id */
3631 queue_push(&solv->ruletojob, i);
3633 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
3634 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3635 if (how == SOLVER_INSTALL_SOLVABLE_NAME)
3636 POOL_DEBUG(SAT_DEBUG_JOB, "job: install name %s\n", dep2str(pool, what));
3637 if (how == SOLVER_INSTALL_SOLVABLE_PROVIDES)
3638 POOL_DEBUG(SAT_DEBUG_JOB, "job: install provides %s\n", dep2str(pool, what));
3640 name = (how == SOLVER_INSTALL_SOLVABLE_NAME) ? what : 0;
3641 while (ISRELDEP(name))
3643 Reldep *rd = GETRELDEP(pool, name);
3646 FOR_PROVIDES(p, pp, what)
3648 /* if by name, ensure that the name matches */
3649 if (name && pool->solvables[p].name != name)
3655 /* no provider, make this an impossible rule */
3656 queue_push(&q, -SYSTEMSOLVABLE);
3659 p = queue_shift(&q); /* get first provider */
3661 d = 0; /* single provider ? -> make assertion */
3663 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
3664 addrule(solv, p, d); /* add 'requires' rule */
3665 queue_push(&solv->ruletojob, i);
3667 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
3668 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3669 if (how == SOLVER_ERASE_SOLVABLE_NAME)
3670 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase name %s\n", dep2str(pool, what));
3671 if (how == SOLVER_ERASE_SOLVABLE_PROVIDES)
3672 POOL_DEBUG(SAT_DEBUG_JOB, "job: erase provides %s\n", dep2str(pool, what));
3673 name = (how == SOLVER_ERASE_SOLVABLE_NAME) ? what : 0;
3674 while (ISRELDEP(name))
3676 Reldep *rd = GETRELDEP(pool, name);
3679 FOR_PROVIDES(p, pp, what)
3681 /* if by name, ensure that the name matches */
3682 if (name && pool->solvables[p].name != name)
3684 addrule(solv, -p, 0); /* add 'remove' rule */
3685 queue_push(&solv->ruletojob, i);
3688 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
3689 s = pool->solvables + what;
3690 POOL_DEBUG(SAT_DEBUG_JOB, "job: update %s\n", solvable2str(pool, s));
3691 addupdaterule(solv, s, 0);
3692 queue_push(&solv->ruletojob, i);
3695 IF_POOLDEBUG (SAT_DEBUG_JOB)
3698 if (solv->nrules == oldnrules)
3699 POOL_DEBUG(SAT_DEBUG_JOB, " - no rule created\n");
3700 for (j = oldnrules; j < solv->nrules; j++)
3702 POOL_DEBUG(SAT_DEBUG_JOB, " - job ");
3703 printrule(solv, SAT_DEBUG_JOB, solv->rules + j);
3707 assert(solv->ruletojob.count == solv->nrules - solv->jobrules);
3710 * now add system rules
3714 POOL_DEBUG(SAT_DEBUG_SCHUBI, "*** Add system rules ***\n");
3717 solv->systemrules = solv->nrules;
3720 * create rules for updating installed solvables
3724 if (installed && !solv->allowuninstall)
3725 { /* loop over all installed solvables */
3726 /* we create all update rules, but disable some later on depending on the job */
3727 for (i = installed->start, s = pool->solvables + i; i < installed->end; i++, s++)
3729 /* no system rules for patch atoms */
3730 if (s->freshens && !s->supplements)
3732 const char *name = id2str(pool, s->name);
3733 if (name[0] == 'a' && !strncmp(name, "atom:", 5))
3735 addrule(solv, 0, 0);
3739 if (s->repo == installed)
3740 addupdaterule(solv, s, 0); /* allowall = 0 */
3742 addrule(solv, 0, 0); /* create dummy rule */
3744 /* consistency check: we added a rule for _every_ system solvable */
3745 assert(solv->nrules - solv->systemrules == installed->end - installed->start);
3748 /* create special weak system rules */
3749 /* those are used later on to keep a version of the installed packages in
3751 if (installed && installed->nsolvables)
3753 solv->weaksystemrules = sat_calloc(installed->end - installed->start, sizeof(Id));
3754 FOR_REPO_SOLVABLES(installed, p, s)
3756 policy_findupdatepackages(solv, s, &q, 1);
3758 solv->weaksystemrules[p - installed->start] = pool_queuetowhatprovides(pool, &q);
3762 /* free unneeded memory */
3763 map_free(&addedmap);
3766 solv->weakrules = solv->nrules;
3768 /* try real hard to keep packages installed */
3771 FOR_REPO_SOLVABLES(installed, p, s)
3773 /* FIXME: can't work with refine_suggestion! */
3774 /* need to always add the rule but disable it */
3775 if (MAPTST(&solv->noupdate, p - installed->start))
3777 d = solv->weaksystemrules[p - installed->start];
3778 addrule(solv, p, d);
3782 /* all new rules are learnt after this point */
3783 solv->learntrules = solv->nrules;
3785 /* disable system rules that conflict with our job */
3786 disableupdaterules(solv, job, -1);
3788 /* make decisions based on job/system assertions */
3789 makeruledecisions(solv);
3791 /* create watches chains */
3794 POOL_DEBUG(SAT_DEBUG_STATS, "problems so far: %d\n", solv->problems.count);
3797 run_solver(solv, 1, 1);
3799 /* find suggested packages */
3800 if (!solv->problems.count)
3802 Id sug, *sugp, p, *pp;
3804 /* create map of all suggests that are still open */
3805 solv->recommends_index = -1;
3806 MAPZERO(&solv->suggestsmap);
3807 for (i = 0; i < solv->decisionq.count; i++)
3809 p = solv->decisionq.elements[i];
3812 s = pool->solvables + p;
3815 sugp = s->repo->idarraydata + s->suggests;
3816 while ((sug = *sugp++) != 0)
3818 FOR_PROVIDES(p, pp, sug)
3819 if (solv->decisionmap[p] > 0)
3822 continue; /* already fulfilled */
3823 FOR_PROVIDES(p, pp, sug)
3824 MAPSET(&solv->suggestsmap, p);
3828 for (i = 1; i < pool->nsolvables; i++)
3830 if (solv->decisionmap[i] != 0)
3832 s = pool->solvables + i;
3833 if (!MAPTST(&solv->suggestsmap, i))
3837 if (!pool_installable(pool, s))
3839 if (!solver_is_enhancing(solv, s))
3842 queue_push(&solv->suggestions, i);
3844 policy_filter_unwanted(solv, &solv->suggestions, 0, POLICY_MODE_SUGGEST);
3847 if (solv->problems.count)
3848 problems_to_solutions(solv, job);
3851 /***********************************************************************/
3863 struct mptree *mptree;
3873 solver_fill_DU_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *value)
3875 struct ducbdata *cbd = cbdata;
3878 if (data != cbd->olddata)
3880 Id dn, mp, comp, *dirmap, *dirs;
3882 const char *compstr;
3883 struct mptree *mptree;
3885 /* create map from dir to mptree */
3886 cbd->dirmap = sat_free(cbd->dirmap);
3888 dirmap = sat_calloc(data->dirpool.ndirs, sizeof(Id));
3889 mptree = cbd->mptree;
3891 for (dn = 2, dirs = data->dirpool.dirs + dn; dn < data->dirpool.ndirs; dn++)
3905 if (!mptree[mp].child)
3910 if (data->localpool)
3911 compstr = stringpool_id2str(&data->spool, comp);
3913 compstr = id2str(data->repo->pool, comp);
3914 compl = strlen(compstr);
3915 for (i = mptree[mp].child; i; i = mptree[i].sibling)
3916 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
3918 dirmap[dn] = i ? i : -mp;
3920 /* change dirmap to point to mountpoint instead of mptree */
3921 for (dn = 0; dn < data->dirpool.ndirs; dn++)
3924 dirmap[dn] = mptree[mp > 0 ? mp : -mp].mountpoint;
3926 cbd->dirmap = dirmap;
3927 cbd->nmap = data->dirpool.ndirs;
3928 cbd->olddata = data;
3930 if (value->id < 0 || value->id >= cbd->nmap)
3932 mp = cbd->dirmap[value->id];
3935 if (cbd->addsub > 0)
3937 cbd->mps[mp].kbytes += value->num;
3938 cbd->mps[mp].files += value->num2;
3942 cbd->mps[mp].kbytes -= value->num;
3943 cbd->mps[mp].files -= value->num2;
3949 propagate_mountpoints(struct mptree *mptree, int pos, Id mountpoint)
3952 if (mptree[pos].mountpoint == -1)
3953 mptree[pos].mountpoint = mountpoint;
3955 mountpoint = mptree[pos].mountpoint;
3956 for (i = mptree[pos].child; i; i = mptree[i].sibling)
3957 propagate_mountpoints(mptree, i, mountpoint);
3960 #define MPTREE_BLOCK 15
3963 solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps)
3965 Pool *pool = solv->pool;
3968 const char *path, *compstr;
3969 struct mptree *mptree;
3974 struct ducbdata cbd;
3982 mptree = sat_extend_resize(0, 1, sizeof(struct mptree), MPTREE_BLOCK);
3985 mptree[0].sibling = 0;
3986 mptree[0].child = 0;
3988 mptree[0].compl = 0;
3989 mptree[0].mountpoint = -1;
3992 /* create component tree */
3993 for (mp = 0; mp < nmps; mp++)
3998 path = mps[mp].path;
4003 if ((p = strchr(path, '/')) == 0)
4006 compl = strlen(compstr);
4017 for (i = mptree[pos].child; i; i = mptree[i].sibling)
4018 if (mptree[i].compl == compl && !strncmp(mptree[i].comp, compstr, compl))
4022 /* create new node */
4023 mptree = sat_extend(mptree, nmptree, 1, sizeof(struct mptree), MPTREE_BLOCK);
4025 mptree[i].sibling = mptree[pos].child;
4026 mptree[i].child = 0;
4027 mptree[i].comp = compstr;
4028 mptree[i].compl = compl;
4029 mptree[i].mountpoint = -1;
4030 mptree[pos].child = i;
4034 mptree[pos].mountpoint = mp;
4037 propagate_mountpoints(mptree, 0, mptree[0].mountpoint);
4040 for (i = 0; i < nmptree; i++)
4042 printf("#%d sibling: %d\n", i, mptree[i].sibling);
4043 printf("#%d child: %d\n", i, mptree[i].child);
4044 printf("#%d comp: %s\n", i, mptree[i].comp);
4045 printf("#%d compl: %d\n", i, mptree[i].compl);
4046 printf("#%d mountpont: %d\n", i, mptree[i].mountpoint);
4050 cbd.mptree = mptree;
4052 /* create list of solvables that have to be installed */
4053 /* (this is actually just a simple sort) */
4054 map_init(&installmap, pool->nsolvables);
4055 for (i = 1; i < solv->decisionq.count; i++)
4057 Id sp = solv->decisionq.elements[i];
4060 s = pool->solvables + sp;
4063 if (solv->installed && s->repo == solv->installed)
4065 MAPSET(&installmap, sp);
4067 /* run through install solvable dudata */
4069 for (i = 1; i < pool->nsolvables; i++)
4071 if (!MAPTST(&installmap, i))
4073 s = pool->solvables + i;
4074 repo_search(s->repo, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
4076 map_free(&installmap);
4077 /* run through erase solvable dudata */
4078 if (solv->installed)
4081 FOR_REPO_SOLVABLES(solv->installed, i, s)
4083 if (solv->decisionmap[i] >= 0)
4085 repo_search(solv->installed, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd);
4088 sat_free(cbd.dirmap);
4093 solver_calc_installsizechange(Solver *solv)
4095 Pool *pool = solv->pool;
4101 for (i = 1; i < solv->decisionq.count; i++)
4103 Id p = solv->decisionq.elements[i];
4106 s = pool->solvables + p;
4109 if (solv->installed && s->repo == solv->installed)
4111 change += repo_lookup_num(s, SOLVABLE_INSTALLSIZE);
4113 if (solv->installed)
4115 FOR_REPO_SOLVABLES(solv->installed, p, s)
4116 if (solv->decisionmap[p] < 0)
4117 change -= repo_lookup_num(s, SOLVABLE_INSTALLSIZE);