4 * SAT based dependency solver
18 #define RULES_BLOCK 63
20 static Pool *prune_best_version_arch_sortcmp_data;
22 /*-----------------------------------------------------------------*/
25 * prep for prune_best_version_arch
30 prune_best_version_arch_sortcmp(const void *ap, const void *bp)
32 Pool *pool = prune_best_version_arch_sortcmp_data;
35 return pool->solvables[a].name - pool->solvables[b].name;
41 replaces_system(Solver *solv, Id id)
43 Pool *pool = solv->pool;
44 Source *system = solv->system;
45 Id *name = pool->solvables[id].name;
47 FOR_PROVIDES(p, pp, id)
49 s = pool->solvables + p;
52 if (p >= system->start && p < system->start + system->nsolvables)
59 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 (!dep_installed(solv, rd->name))
71 return dep_installed(solv, rd->evr);
73 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
74 return dep_installed(solv, rd->evr);
76 FOR_PROVIDES(p, pp, dep)
78 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
85 dep_fulfilled(Solver *solv, Id dep)
87 Pool *pool = solv->pool;
92 Reldep *rd = GETRELDEP(pool, dep);
93 if (rd->flags == REL_AND)
95 if (!dep_fulfilled(solv, rd->name))
97 return dep_fulfilled(solv, rd->evr);
99 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
100 return dep_installed(solv, rd->evr);
102 FOR_PROVIDES(p, pp, dep)
104 if (solv->decisionmap[p] > 0)
111 dep_possible(Solver *solv, Id dep, Map *m)
113 Pool *pool = solv->pool;
118 Reldep *rd = GETRELDEP(pool, dep);
119 if (rd->flags == REL_AND)
121 if (!dep_possible(solv, rd->name, m))
123 return dep_possible(solv, rd->evr, m);
125 if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_INSTALLED)
126 return dep_installed(solv, rd->evr);
128 FOR_PROVIDES(p, pp, dep)
137 prune_to_highest_prio(Pool *pool, Queue *plist)
143 /* prune to highest priority */
144 for (i = 0; i < plist->count; i++)
146 s = pool->solvables + plist->elements[i];
147 if (i == 0 || s->source->priority > bestprio)
148 bestprio = s->source->priority;
150 for (i = j = 0; i < plist->count; i++)
152 s = pool->solvables + plist->elements[i];
153 if (s->source->priority == bestprio)
154 plist->elements[j++] = plist->elements[i];
160 * prune_to_recommended
162 * XXX: should we prune to requires/suggests that are already
163 * fulfilled by other packages?
166 prune_to_recommended(Solver *solv, Queue *plist)
168 Pool *pool = solv->pool;
171 Id p, *pp, sup, *supp, rec, *recp, sug, *sugp, enh, *enhp;
173 if (solv->recommends_index < 0)
175 MAPZERO(&solv->recommendsmap);
176 MAPZERO(&solv->suggestsmap);
177 solv->recommends_index = 0;
179 while (solv->recommends_index < solv->decisionq.count)
181 p = solv->decisionq.elements[solv->recommends_index++];
184 s = pool->solvables + p;
187 recp = s->source->idarraydata + s->recommends;
188 while ((rec = *recp++) != 0)
189 FOR_PROVIDES(p, pp, rec)
190 MAPSET(&solv->recommendsmap, p);
194 sugp = s->source->idarraydata + s->suggests;
195 while ((sug = *sugp++) != 0)
196 FOR_PROVIDES(p, pp, sug)
197 MAPSET(&solv->suggestsmap, p);
200 /* prune to recommended/supplemented */
201 for (i = j = 0; i < plist->count; i++)
203 p = plist->elements[i];
204 if (MAPTST(&solv->recommendsmap, p))
206 plist->elements[j++] = p;
209 s = pool->solvables + p;
210 if (!s->supplements && !s->freshens)
214 supp = s->source->idarraydata + s->supplements;
215 while ((sup = *supp++) != 0)
216 if (dep_fulfilled(solv, sup))
223 supp = s->source->idarraydata + s->freshens;
224 while ((sup = *supp++) != 0)
225 if (dep_fulfilled(solv, sup))
230 plist->elements[j++] = s - pool->solvables;
235 /* prune to suggested/enhanced*/
236 if (plist->count < 2)
238 for (i = j = 0; i < plist->count; i++)
240 p = plist->elements[i];
241 if (MAPTST(&solv->suggestsmap, p))
243 plist->elements[j++] = p;
246 s = pool->solvables + p;
249 enhp = s->source->idarraydata + s->enhances;
250 while ((enh = *enhp++) != 0)
251 if (dep_fulfilled(solv, enh))
255 plist->elements[j++] = s - pool->solvables;
262 * prune_best_version_arch
264 * sort list of packages (given through plist) by name and evr
265 * return result through plist
269 /* FIXME: must also look at update packages */
272 prune_best_version_arch(Pool *pool, Queue *plist)
279 if (plist->count < 2) /* no need to prune for a single entry */
281 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
283 /* prune to best architecture */
287 for (i = 0; i < plist->count; i++)
289 s = pool->solvables + plist->elements[i];
291 a = a <= pool->lastarch ? pool->id2arch[a] : 0;
292 if (a && a != 1 && (!bestscore || a < bestscore))
295 for (i = j = 0; i < plist->count; i++)
297 s = pool->solvables + plist->elements[i];
299 if (a > pool->lastarch)
301 a = pool->id2arch[a];
302 /* a == 1 -> noarch */
303 if (a != 1 && ((a ^ bestscore) & 0xffff0000) != 0)
305 plist->elements[j++] = plist->elements[i];
311 prune_best_version_arch_sortcmp_data = pool;
312 /* sort by name first */
313 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
315 /* now find best 'per name' */
316 /* FIXME: also check obsoletes! */
317 for (i = j = 0; i < plist->count; i++)
319 s = pool->solvables + plist->elements[i];
321 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
323 if (!best) /* if no best yet, the current is best */
325 best = plist->elements[i];
329 /* name switch: re-init */
330 if (pool->solvables[best].name != s->name) /* new name */
332 plist->elements[j++] = best; /* move old best to front */
333 best = plist->elements[i]; /* take current as new best */
337 if (pool->solvables[best].evr != s->evr) /* compare evr */
339 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
340 best = plist->elements[i];
345 best = plist->elements[0];
347 plist->elements[j++] = best;
352 /*-----------------------------------------------------------------*/
359 printruleelement(Solver *solv, Rule *r, Id v)
361 Pool *pool = solv->pool;
365 s = pool->solvables + -v;
366 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
370 s = pool->solvables + v;
371 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
380 if (solv->decisionmap[s - pool->solvables] > 0)
381 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
382 if (solv->decisionmap[s - pool->solvables] < 0)
383 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
393 printrule(Solver *solv, Rule *r)
398 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
399 printf("Rule #%d:\n", (int)(r - solv->rules));
401 printf("Rule:\n"); /* r is any rule */
406 else if (r->d == ID_NULL)
413 v = solv->pool->whatprovidesdata[r->d + i - 1];
416 printruleelement(solv, r, v);
418 printf(" next: %d %d\n", r->n1, r->n2);
422 /*-----------------------------------------------------------------*/
428 static Pool *unifyrules_sortcmp_data;
431 * compare rules for unification sort
435 unifyrules_sortcmp(const void *ap, const void *bp)
437 Pool *pool = unifyrules_sortcmp_data;
438 Rule *a = (Rule *)ap;
439 Rule *b = (Rule *)bp;
445 return x; /* p differs */
448 if (a->d == 0 && b->d == 0)
449 return a->w2 - b->w2; /* assertion: return w2 diff */
451 if (a->d == 0) /* a is assertion, b not */
453 x = a->w2 - pool->whatprovidesdata[b->d];
457 if (b->d == 0) /* b is assertion, a not */
459 x = pool->whatprovidesdata[a->d] - b->w2;
463 /* compare whatprovidesdata */
464 ad = pool->whatprovidesdata + a->d;
465 bd = pool->whatprovidesdata + b->d;
467 if ((x = *ad++ - *bd++) != 0)
478 unifyrules(Solver *solv)
483 if (solv->nrules <= 1) /* nothing to unify */
486 /* sort rules first */
487 unifyrules_sortcmp_data = solv->pool;
488 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
495 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
497 if (jr && !unifyrules_sortcmp(ir, jr))
498 continue; /* prune! */
499 jr = solv->rules + j++; /* keep! */
504 /* reduced count from nrules to j rules */
505 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
507 /* adapt rule buffer */
508 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
517 for (i = 1; i < solv->nrules; i++)
520 if (r->d == 0) /* assertion */
525 dp = solv->pool->whatprovidesdata + r->d;
529 if (solv->pool->verbose)
531 printf(" binary: %d\n", binr);
532 printf(" normal: %d\n", solv->nrules - 1 - binr);
533 printf(" normal lits: %d\n", dc);
546 hashrule(Solver *solv, Id p, Id d, int n)
548 unsigned int x = (unsigned int)p;
552 return (x * 37) ^ (unsigned int)d;
553 dp = solv->pool->whatprovidesdata + d;
555 x = (x * 37) ^ (unsigned int)*dp++;
563 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
564 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
567 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
569 * p < 0 : rule from rpm (installed pkg)
570 * d > 0 : Offset in whatprovidesdata (list of providers)
572 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
573 * d < 0: Id of solvable (e.g. B1)
575 * d == 0: unary rule, assertion => (A) or (-A)
577 * Install: p > 0, d = 0 (A) user requested install
578 * Remove: p < 0, d = 0 (-A) user requested remove
579 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
580 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
581 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
582 * ? p > 0, d < 0 (A|-B)
583 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
587 addrule(Solver *solv, Id p, Id d)
592 int n = 0; /* number of literals in rule - 1
593 0 = direct assertion (single literal)
597 /* it often happenes that requires lead to adding the same rpm rule
598 * multiple times, so we prune those duplicates right away to make
599 * the work for unifyrules a bit easier */
601 if (solv->nrules && !solv->jobrules)
603 r = solv->rules + solv->nrules - 1; /* get the last added rule */
604 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
611 return 0; /* ignore self conflict */
614 else if (d == 0) /* user requested */
618 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
620 return 0; /* rule is self-fulfilling */
625 if (n == 0) /* direct assertion */
629 /* this is a rpm rule assertion, we do not have to allocate it */
630 /* it can be identified by a level of 1 and a zero reason */
633 if (solv->decisionmap[-p] > 0 || solv->decisionmap[-p] < -1)
635 if (solv->decisionmap[-p])
637 queuepush(&solv->decisionq, p);
638 queuepush(&solv->decisionq_why, 0);
639 solv->decisionmap[-p] = -1;
643 else if (n == 1 && p > d)
645 /* smallest literal first so we can find dups */
649 n = 1; /* re-set n, was used as temp var */
652 /* check if the last added rule is exactly the same as what we're looking for. */
653 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
656 if (r && n > 1 && r->d && r->p == p)
661 dp2 = solv->pool->whatprovidesdata + r->d;
662 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
673 /* check and extend rule buffer */
674 if ((solv->nrules & RULES_BLOCK) == 0)
676 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
679 r = solv->rules + solv->nrules++; /* point to rule space */
684 /* direct assertion, no watch needed */
700 r->w2 = solv->pool->whatprovidesdata[d];
708 /* go through system and job rules and add direct assertions
709 * to the decisionqueue. If we find a conflict, disable rules and
710 * add them to problem queue.
713 makeruledecisions(Solver *solv)
719 /* no learnt rules for now */
720 if (solv->learntrules && solv->learntrules != solv->nrules)
723 for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
729 if (solv->decisionmap[vv] == 0)
731 queuepush(&solv->decisionq, v);
732 queuepush(&solv->decisionq_why, r - solv->rules);
733 solv->decisionmap[vv] = v > 0 ? 1 : -1;
736 if (v > 0 && solv->decisionmap[vv] > 0)
738 if (v < 0 && solv->decisionmap[vv] < 0)
740 /* found a conflict! */
741 /* if we are weak, just disable ourself */
742 if (ri >= solv->weakrules)
744 printf("conflict, but I am weak, disabling ");
749 for (i = 0; i < solv->decisionq.count; i++)
750 if (solv->decisionq.elements[i] == -v)
752 if (i == solv->decisionq.count)
754 if (solv->decisionq_why.elements[i] == 0)
756 /* conflict with rpm rule, need only disable our rule */
757 printf("conflict with rpm rule, disabling rule #%d\n", ri);
758 queuepush(&solv->problems, r - solv->rules);
759 queuepush(&solv->problems, 0);
760 r->w1 = 0; /* disable */
763 /* conflict with another job or system rule */
764 /* remove old decision */
765 printf("conflicting system/job rules over literal %d\n", vv);
766 solv->decisionmap[vv] = 0;
767 for (; i + 1 < solv->decisionq.count; i++)
769 solv->decisionq.elements[i] = solv->decisionq.elements[i + 1];
770 solv->decisionq_why.elements[i] = solv->decisionq_why.elements[i + 1];
772 solv->decisionq.count--;
773 solv->decisionq_why.count--;
774 /* push all of our rules asserting this literal on the problem stack */
775 for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
777 if (!rr->w1 || rr->w2)
779 if (rr->p != v && rr->p != -v)
781 printf(" - disabling rule #%d\n", i);
782 queuepush(&solv->problems, i);
783 rr->w1 = 0; /* disable */
785 queuepush(&solv->problems, 0);
791 * add (install) rules for solvable
796 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
798 Pool *pool = solv->pool;
799 Source *system = solv->system;
813 queueinit_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
814 queuepush(&q, s - pool->solvables); /* push solvable Id */
820 * s: Pointer to solvable
824 if (MAPTST(m, n)) /* continue if already done */
828 s = pool->solvables + n; /* s = Solvable in question */
833 && n >= system->start /* is it installed? */
834 && n < system->start + system->nsolvables)
836 dontfix = 1; /* dont care about broken rpm deps */
839 /*-----------------------------------------
840 * check requires of s
845 reqp = s->source->idarraydata + s->requires;
846 while ((req = *reqp++) != 0)
848 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
851 dp = GET_PROVIDESP(req, p); /* get providers of req */
853 if (dontfix) /* dont care about breakage */
855 /* the strategy here is to not insist on dependencies
856 * that are already broken. so if we find one provider
857 * that was already installed, we know that the
858 * dependency was not broken before so we enforce it */
859 for (i = 0; dp[i]; i++) /* for all providers */
861 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
862 break; /* provider is installed */
864 if (!dp[i]) /* previously broken dependency */
866 if (pool->verbose) printf("ignoring broken requires %s of system package %s-%s.%s\n", dep2str(pool, req), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
873 /* nothing provides req! */
875 if (pool->verbose) printf("package %s-%s.%s [%ld] is not installable (%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables), dep2str(pool, req));
877 addrule(solv, -n, 0); /* mark requestor as uninstallable */
879 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), source_name(s->source));
883 if (*dp == SYSTEMSOLVABLE) /* always installed */
886 printf("addrule %s-%s.%s %s %d %d\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req), -n, dp - pool->whatprovidesdata);
887 for (i = 0; dp[i]; i++)
888 printf(" %s-%s.%s\n", id2str(pool, pool->solvables[dp[i]].name), id2str(pool, pool->solvables[dp[i]].evr), id2str(pool, pool->solvables[dp[i]].arch));
890 /* add 'requires' dependency */
891 /* rule: (-requestor|provider1|provider2|...|providerN) */
892 addrule(solv, -n, dp - pool->whatprovidesdata);
894 /* descend the dependency tree */
895 for (; *dp; dp++) /* loop through all providers */
901 } /* while, requirements of n */
903 } /* if, requirements */
906 /*-----------------------------------------
907 * check conflicts of s
912 conp = s->source->idarraydata + s->conflicts;
913 while ((con = *conp++) != 0)
915 FOR_PROVIDES(p, pp, con)
917 /* dontfix: dont care about conflicts with already installed packs */
918 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
920 /* rule: -n|-p: either solvable _or_ provider of conflict */
921 addrule(solv, -n, -p);
926 /*-----------------------------------------
927 * check obsoletes if not installed
929 if (!system || n < system->start || n >= (system->start + system->nsolvables))
930 { /* not installed */
933 obsp = s->source->idarraydata + s->obsoletes;
934 while ((obs = *obsp++) != 0)
936 FOR_PROVIDES(p, pp, obs)
937 addrule(solv, -n, -p);
940 FOR_PROVIDES(p, pp, s->name)
942 if (s->name == pool->solvables[p].name)
943 addrule(solv, -n, -p);
947 /*-----------------------------------------
948 * add recommends to the rule list
952 recp = s->source->idarraydata + s->recommends;
953 while ((rec = *recp++) != 0)
955 FOR_PROVIDES(p, pp, rec)
962 sugp = s->source->idarraydata + s->suggests;
963 while ((sug = *sugp++) != 0)
965 FOR_PROVIDES(p, pp, sug)
975 addrulesforweak(Solver *solv, Map *m)
977 Pool *pool = solv->pool;
982 if (pool->verbose) printf("addrulesforweak... (%d)\n", solv->nrules);
983 for (i = n = 1; n < pool->nsolvables; i++, n++)
985 if (i == pool->nsolvables)
989 s = pool->solvables + i;
990 if (!pool_installable(pool, s))
995 supp = s->source->idarraydata + s->supplements;
996 while ((sup = *supp++) != ID_NULL)
997 if (dep_possible(solv, sup, m))
1000 if (!sup && s->freshens)
1002 supp = s->source->idarraydata + s->freshens;
1003 while ((sup = *supp++) != ID_NULL)
1004 if (dep_possible(solv, sup, m))
1007 if (!sup && s->enhances)
1009 supp = s->source->idarraydata + s->enhances;
1010 while ((sup = *supp++) != ID_NULL)
1011 if (dep_possible(solv, sup, m))
1016 addrulesforsolvable(solv, s, m);
1019 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
1023 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
1025 Id a1 = s1->arch, a2 = s2->arch;
1027 /* we allow changes to/from noarch */
1028 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
1032 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
1033 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
1034 if (((a1 ^ a2) & 0xffff0000) != 0)
1041 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
1043 /* system packages get a special upgrade allowed rule */
1044 Pool *pool = solv->pool;
1045 Id p, *pp, n, p2, *pp2;
1054 n = s - pool->solvables;
1055 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
1056 addrulesforsolvable(solv, s, m);
1059 * look for updates for s
1061 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
1063 if (p == n) /* skip itself */
1066 ps = pool->solvables + p;
1067 if (s->name == ps->name) /* name match */
1069 if (!allowdowngrade /* consider downgrades ? */
1070 && evrcmp(pool, s->evr, ps->evr) > 0)
1073 if (!allowarchchange && archchanges(pool, s, ps))
1076 else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */
1078 obsp = ps->source->idarraydata + ps->obsoletes;
1079 while ((obs = *obsp++) != 0) /* for all obsoletes */
1081 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
1083 if (p2 == n) /* match ! */
1086 if (p2) /* match! */
1089 if (!obs) /* continue if no match */
1091 /* here we have 'p' with a matching provides/obsoletes combination
1092 * thus flagging p as a valid update candidate for s
1099 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1100 addrulesforsolvable(solv, pool->solvables + p, m);
1102 if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->system->start])
1104 for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->system->start]; (p = *pp++) != 0;)
1107 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1108 addrulesforsolvable(solv, pool->solvables + p, m);
1114 * add rule for update
1115 * (A|A1|A2|A3...) An = update candidates for A
1117 * s = (installed) solvable
1118 * m = 'addedmap', bit set if 'install' rule for solvable exists
1122 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
1124 /* system packages get a special upgrade allowed rule */
1125 Pool *pool = solv->pool;
1131 queueinit_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1132 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
1133 p = s - pool->solvables;
1134 if (dontaddrule) /* we consider update candidates but dont force them */
1140 if (qs.count == 0) /* no updates found */
1143 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1145 addrule(solv, p, 0); /* request 'install' of s */
1150 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1152 r = addrule(solv, p, d); /* allow update of s */
1154 printf("new update rule ");
1161 /*-----------------------------------------------------------------*/
1168 * initial setup for all watches
1172 makewatches(Solver *solv)
1176 int nsolvables = solv->pool->nsolvables;
1178 xfree(solv->watches);
1179 /* lower half for removals, upper half for installs */
1180 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1182 /* do it reverse so rpm rules get triggered first */
1183 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1185 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1188 if (!r->w1 /* rule is disabled */
1189 || !r->w2) /* rule is assertion */
1192 /* see addwatches(solv, r) */
1193 r->n1 = solv->watches[nsolvables + r->w1];
1194 solv->watches[nsolvables + r->w1] = r - solv->rules;
1196 r->n2 = solv->watches[nsolvables + r->w2];
1197 solv->watches[nsolvables + r->w2] = r - solv->rules;
1203 * add watches (for rule)
1207 addwatches(Solver *solv, Rule *r)
1209 int nsolvables = solv->pool->nsolvables;
1211 r->n1 = solv->watches[nsolvables + r->w1];
1212 solv->watches[nsolvables + r->w1] = r - solv->rules;
1214 r->n2 = solv->watches[nsolvables + r->w2];
1215 solv->watches[nsolvables + r->w2] = r - solv->rules;
1219 /*-----------------------------------------------------------------*/
1220 /* rule propagation */
1222 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1227 * propagate decision to all rules
1231 propagate(Solver *solv, int level)
1233 Pool *pool = solv->pool;
1238 Id *decisionmap = solv->decisionmap;
1239 Id *watches = solv->watches + pool->nsolvables;
1241 while (solv->propagate_index < solv->decisionq.count)
1243 /* negative because our watches trigger if literal goes FALSE */
1244 pkg = -solv->decisionq.elements[solv->propagate_index++];
1246 printf("popagate for decision %d level %d\n", -pkg, level);
1247 printruleelement(solv, 0, -pkg);
1249 for (rp = watches + pkg; *rp; rp = nrp)
1251 r = solv->rules + *rp;
1253 printf(" watch triggered ");
1266 /* if clause is TRUE, nothing to do */
1267 if (DECISIONMAP_TRUE(ow))
1272 /* not a binary clause, check if we need to move our watch */
1273 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1276 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1277 if (p != ow && !DECISIONMAP_TRUE(-p))
1281 /* p is free to watch, move watch to p */
1284 printf(" -> move w%d to %s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[p].name), id2str(pool, pool->solvables[p].evr), id2str(pool, pool->solvables[p].arch));
1286 printf(" -> move w%d to !%s-%s.%s\n", (pkg == r->w1 ? 1 : 2), id2str(pool, pool->solvables[-p].name), id2str(pool, pool->solvables[-p].evr), id2str(pool, pool->solvables[-p].arch));
1300 watches[p] = r - solv->rules;
1304 /* unit clause found, set other watch to TRUE */
1305 if (DECISIONMAP_TRUE(-ow))
1306 return r; /* eek, a conflict! */
1312 decisionmap[ow] = level;
1314 decisionmap[-ow] = -level;
1315 queuepush(&solv->decisionq, ow);
1316 queuepush(&solv->decisionq_why, r - solv->rules);
1319 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1321 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1323 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1328 return 0; /* all is well */
1332 /*-----------------------------------------------------------------*/
1341 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1343 Pool *pool = solv->pool;
1346 Map seen; /* global? */
1350 int learnt_why = solv->learnt_pool.count;
1351 Id *decisionmap = solv->decisionmap;
1355 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1356 mapinit(&seen, pool->nsolvables);
1357 idx = solv->decisionq.count;
1361 queuepush(&solv->learnt_pool, c - solv->rules);
1362 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1373 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1375 vv = v > 0 ? v : -v;
1376 if (MAPTST(&seen, vv))
1378 l = solv->decisionmap[vv];
1385 for (j = 0; j < solv->decisionq.count; j++)
1386 if (solv->decisionq.elements[j] == v)
1388 if (j == solv->decisionq.count)
1390 queuepush(&rulq, -(j + 1));
1392 continue; /* initial setting */
1396 num++; /* need to do this one as well */
1401 printf("PUSH %d ", v);
1402 printruleelement(solv, 0, v);
1409 printf("num = %d\n", num);
1415 v = solv->decisionq.elements[--idx];
1416 vv = v > 0 ? v : -v;
1417 if (MAPTST(&seen, vv))
1420 c = solv->rules + solv->decisionq_why.elements[idx];
1428 else if (r.count == 1 && r.elements[0] < 0)
1429 *dr = r.elements[0];
1431 *dr = pool_queuetowhatprovides(pool, &r);
1434 printf("learned rule for level %d (am %d)\n", rlevel, level);
1435 printruleelement(solv, 0, -v);
1436 for (i = 0; i < r.count; i++)
1439 printruleelement(solv, 0, v);
1443 queuepush(&solv->learnt_pool, 0);
1445 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1447 printf("learnt_why ");
1448 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1459 * reset the solver decisions to right after the rpm rules
1463 reset_solver(Solver *solv)
1468 /* delete all learnt rules */
1469 solv->nrules = solv->learntrules;
1470 QUEUEEMPTY(&solv->learnt_why);
1471 QUEUEEMPTY(&solv->learnt_pool);
1473 /* redo all direct rpm rule decisions */
1474 /* we break at the first decision with a why attached, this is
1475 * either a job/system rule decision of a propagated decision */
1476 for (i = 0; i < solv->decisionq.count; i++)
1478 v = solv->decisionq.elements[i];
1479 solv->decisionmap[v > 0 ? v : -v] = 0;
1481 for (i = 0; i < solv->decisionq_why.count; i++)
1482 if (solv->decisionq_why.elements[i])
1486 v = solv->decisionq.elements[i];
1487 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1490 if (solv->pool->verbose)
1491 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1493 solv->decisionq_why.count = i;
1494 solv->decisionq.count = i;
1495 solv->recommends_index = -1;
1496 solv->propagate_index = 0;
1498 /* redo all job/system decisions */
1499 makeruledecisions(solv);
1500 if (solv->pool->verbose)
1501 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1502 /* recreate watches */
1508 * analyze_unsolvable_rule
1512 analyze_unsolvable_rule(Solver *solv, Rule *r)
1515 Id why = r - solv->rules;
1517 if (why >= solv->jobrules && why < solv->systemrules)
1519 if (why >= solv->systemrules && why < solv->weakrules)
1520 printf("SYSTEM %d ", why - solv->systemrules);
1521 if (why >= solv->weakrules && why < solv->learntrules)
1523 if (solv->learntrules && why >= solv->learntrules)
1527 if (solv->learntrules && why >= solv->learntrules)
1529 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1530 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]);
1533 /* do not add rpm rules to problem */
1534 if (why < solv->jobrules)
1536 /* return if problem already countains the rule */
1537 if (solv->problems.count)
1539 for (i = solv->problems.count - 1; i >= 0; i--)
1540 if (solv->problems.elements[i] == 0)
1542 else if (solv->problems.elements[i] == why)
1545 queuepush(&solv->problems, why);
1550 * analyze_unsolvable
1552 * return: 1 - disabled some rules, try again
1557 analyze_unsolvable(Solver *solv, Rule *r, int disablerules)
1559 Pool *pool = solv->pool;
1560 Map seen; /* global? */
1563 Id *decisionmap = solv->decisionmap;
1564 int oldproblemcount;
1568 printf("ANALYZE UNSOLVABLE ----------------------\n");
1570 oldproblemcount = solv->problems.count;
1571 mapinit(&seen, pool->nsolvables);
1572 analyze_unsolvable_rule(solv, r);
1573 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1584 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1586 vv = v > 0 ? v : -v;
1587 l = solv->decisionmap[vv];
1592 idx = solv->decisionq.count;
1595 v = solv->decisionq.elements[--idx];
1596 vv = v > 0 ? v : -v;
1597 if (!MAPTST(&seen, vv))
1599 why = solv->decisionq_why.elements[idx];
1604 printruleelement(solv, 0, v);
1608 r = solv->rules + why;
1609 analyze_unsolvable_rule(solv, r);
1610 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1621 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1623 vv = v > 0 ? v : -v;
1624 l = solv->decisionmap[vv];
1631 queuepush(&solv->problems, 0); /* mark end of this problem */
1634 if (solv->weakrules != solv->learntrules)
1636 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1638 why = solv->problems.elements[i];
1639 if (why < solv->weakrules || why >= solv->learntrules)
1641 if (!lastweak || lastweak < why)
1647 /* disable last weak rule */
1648 solv->problems.count = oldproblemcount;
1649 r = solv->rules + lastweak;
1650 printf("disabling weak ");
1656 else if (disablerules)
1658 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1660 r = solv->rules + solv->problems.elements[i];
1670 /*-----------------------------------------------------------------*/
1671 /* Decision revert */
1675 * revert decision at level
1679 revert(Solver *solv, int level)
1682 while (solv->decisionq.count)
1684 v = solv->decisionq.elements[solv->decisionq.count - 1];
1685 vv = v > 0 ? v : -v;
1686 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1689 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1691 solv->decisionmap[vv] = 0;
1692 solv->decisionq.count--;
1693 solv->decisionq_why.count--;
1694 solv->propagate_index = solv->decisionq.count;
1696 solv->recommends_index = -1;
1701 * watch2onhighest - put watch2 on literal with highest level
1705 watch2onhighest(Solver *solv, Rule *r)
1711 return; /* binary rule, both watches are set */
1712 dp = solv->pool->whatprovidesdata + r->d;
1713 while ((v = *dp++) != 0)
1715 l = solv->decisionmap[v < 0 ? -v : v];
1732 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1742 solv->decisionmap[decision] = level;
1744 solv->decisionmap[-decision] = -level;
1745 queuepush(&solv->decisionq, decision);
1746 queuepush(&solv->decisionq_why, 0);
1750 r = propagate(solv, level);
1754 return analyze_unsolvable(solv, r, disablerules);
1755 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1756 l = analyze(solv, level, r, &p, &d, &why);
1757 if (l >= level || l <= 0)
1759 printf("reverting decisions (level %d -> %d)\n", level, l);
1761 revert(solv, level);
1762 r = addrule(solv, p, d); /* p requires d */
1765 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1767 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1770 queuepush(&solv->learnt_why, why);
1773 /* at least 2 literals, needs watches */
1774 watch2onhighest(solv, r);
1775 addwatches(solv, r);
1777 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1778 queuepush(&solv->decisionq, p);
1779 queuepush(&solv->decisionq_why, r - solv->rules);
1780 printf("decision: ");
1781 printruleelement(solv, 0, p);
1782 printf("new rule: ");
1788 /*-----------------------------------------------------------------*/
1789 /* Main solver interface */
1794 * create solver structure
1796 * pool: all available solvables
1797 * system: installed Solvables
1800 * Upon solving, rules are created to flag the Solvables
1801 * of the 'system' Source as installed.
1805 solver_create(Pool *pool, Source *system)
1808 solv = (Solver *)xcalloc(1, sizeof(Solver));
1810 solv->system = system;
1813 queueinit(&solv->ruletojob);
1814 queueinit(&solv->decisionq);
1815 queueinit(&solv->decisionq_why);
1816 queueinit(&solv->problems);
1817 queueinit(&solv->suggestions);
1818 queueinit(&solv->learnt_why);
1819 queueinit(&solv->learnt_pool);
1821 mapinit(&solv->recommendsmap, pool->nsolvables);
1822 mapinit(&solv->suggestsmap, pool->nsolvables);
1823 solv->recommends_index = 0;
1825 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1826 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1827 memset(solv->rules, 0, sizeof(Rule));
1839 solver_free(Solver *solv)
1841 queuefree(&solv->ruletojob);
1842 queuefree(&solv->decisionq);
1843 queuefree(&solv->decisionq_why);
1844 queuefree(&solv->learnt_why);
1845 queuefree(&solv->learnt_pool);
1846 queuefree(&solv->problems);
1847 queuefree(&solv->suggestions);
1849 mapfree(&solv->recommendsmap);
1850 mapfree(&solv->suggestsmap);
1851 xfree(solv->decisionmap);
1853 xfree(solv->watches);
1854 xfree(solv->weaksystemrules);
1855 xfree(solv->obsoletes);
1856 xfree(solv->obsoletes_data);
1861 /*-------------------------------------------------------*/
1866 * all rules have been set up, not actually run the solver
1871 run_solver(Solver *solv, int disablerules, int doweak)
1879 Pool *pool = solv->pool;
1883 printf("number of rules: %d\n", solv->nrules);
1886 for (i = 0; i < solv->nrules; i++)
1888 printrule(solv, solv->rules + i);
1893 /* all new rules are learnt after this point */
1894 solv->learntrules = solv->nrules;
1895 /* crate watches lists */
1898 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1900 /* start SAT algorithm */
1902 systemlevel = level + 1;
1903 if (pool->verbose) printf("solving...\n");
1914 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1915 if ((r = propagate(solv, level)) != 0)
1917 if (analyze_unsolvable(solv, r, disablerules))
1919 printf("UNSOLVABLE\n");
1929 if (level < systemlevel && solv->system->nsolvables)
1931 if (!solv->updatesystem)
1933 /* try to keep as many packages as possible */
1934 if (pool->verbose) printf("installing system packages\n");
1935 for (i = solv->system->start, n = 0; ; i++, n++)
1937 if (n == solv->system->nsolvables)
1939 if (i == solv->system->start + solv->system->nsolvables)
1940 i = solv->system->start;
1941 s = pool->solvables + i;
1942 if (solv->decisionmap[i] != 0)
1945 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1948 level = setpropagatelearn(solv, level, i, disablerules);
1951 printf("UNSOLVABLE\n");
1955 if (level <= olevel)
1959 if (solv->weaksystemrules)
1961 if (pool->verbose) printf("installing weak system packages\n");
1962 for (i = solv->system->start, n = 0; ; i++, n++)
1964 if (n == solv->system->nsolvables)
1966 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->system->start] == 0))
1969 if (solv->decisionmap[i] == 0)
1971 if (solv->weaksystemrules[i - solv->system->start])
1973 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1974 while ((p = *dp++) != 0)
1976 if (solv->decisionmap[p] > 0)
1978 if (solv->decisionmap[p] == 0)
1982 continue; /* rule is already true */
1988 prune_to_highest_prio(pool, &dq);
1990 prune_to_recommended(solv, &dq);
1992 prune_best_version_arch(pool, &dq);
1994 s = pool->solvables + dq.elements[0];
1995 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1998 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
2001 printf("UNSOLVABLE\n");
2005 if (level <= olevel)
2011 if (n != solv->system->nsolvables)
2014 systemlevel = level;
2021 if (pool->verbose) printf("deciding unresolved rules\n");
2022 for (i = 1, n = 1; ; i++, n++)
2024 if (n == solv->nrules)
2026 if (i == solv->nrules)
2028 r = solv->rules + i;
2034 /* binary or unary rule */
2035 /* need two positive undecided literals */
2036 if (r->p < 0 || r->w2 <= 0)
2038 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2040 queuepush(&dq, r->p);
2041 queuepush(&dq, r->w2);
2046 * all negative literals are installed
2047 * no positive literal is installed
2048 * i.e. the rule is not fulfilled and we
2049 * just need to decide on the positive literals
2053 if (solv->decisionmap[-r->p] <= 0)
2058 if (solv->decisionmap[r->p] > 0)
2060 if (solv->decisionmap[r->p] == 0)
2061 queuepush(&dq, r->p);
2063 dp = pool->whatprovidesdata + r->d;
2064 while ((p = *dp++) != 0)
2068 if (solv->decisionmap[-p] <= 0)
2073 if (solv->decisionmap[p] > 0)
2075 if (solv->decisionmap[p] == 0)
2084 /* cannot happen as this means that
2085 * the rule is unit */
2089 prune_to_highest_prio(pool, &dq);
2091 prune_to_recommended(solv, &dq);
2093 prune_best_version_arch(pool, &dq);
2094 p = dq.elements[dq.count - 1];
2095 s = pool->solvables + p;
2097 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2100 level = setpropagatelearn(solv, level, p, disablerules);
2103 printf("UNSOLVABLE\n");
2107 if (level < systemlevel)
2110 } /* for(), decide */
2112 if (n != solv->nrules) /* continue if level < systemlevel */
2115 if (doweak && !solv->problems.count)
2119 if (pool->verbose) printf("installing recommended packages\n");
2121 for (i = 1; i < pool->nsolvables; i++)
2123 if (solv->decisionmap[i] < 0)
2125 if (solv->decisionmap[i] > 0)
2127 Id *recp, rec, *pp, p;
2128 s = pool->solvables + i;
2129 /* installed, check for recommends */
2130 /* XXX need to special case AND ? */
2133 recp = s->source->idarraydata + s->recommends;
2134 while ((rec = *recp++) != 0)
2137 FOR_PROVIDES(p, pp, rec)
2139 if (solv->decisionmap[p] > 0)
2144 else if (solv->decisionmap[p] == 0)
2145 queuepushunique(&dq, p);
2153 s = pool->solvables + i;
2154 if (!s->supplements && !s->freshens)
2156 if (!pool_installable(pool, s))
2160 supp = s->source->idarraydata + s->supplements;
2161 while ((sup = *supp++) != 0)
2162 if (dep_fulfilled(solv, sup))
2169 supp = s->source->idarraydata + s->freshens;
2170 while ((sup = *supp++) != 0)
2171 if (dep_fulfilled(solv, sup))
2176 queuepushunique(&dq, i);
2182 prune_to_highest_prio(pool, &dq);
2184 prune_best_version_arch(pool, &dq);
2185 p = dq.elements[dq.count - 1];
2186 s = pool->solvables + p;
2188 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2190 level = setpropagatelearn(solv, level, p, 0);
2205 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2208 int i, j, sugseen, sugjob = -1;
2213 printf("refine_suggestion start\n");
2215 if (sug >= solv->jobrules && sug < solv->systemrules)
2216 sugjob = solv->ruletojob.elements[sug - solv->jobrules];
2218 queueinit(&disabled);
2219 QUEUEEMPTY(refined);
2220 queuepush(refined, sug);
2222 /* re-enable all rules but rule "sug" of the problem */
2228 r = solv->rules + sug;
2232 for (i = 0; problem[i]; i++)
2234 if (problem[i] == sug)
2239 if (sugjob >= 0 && problem[i] >= solv->jobrules && problem[i] < solv->systemrules && sugjob == solv->ruletojob.elements[problem[i] - solv->jobrules])
2241 /* rule belongs to same job */
2244 r = solv->rules + problem[i];
2251 /* direct assertion */
2252 if (r->p == sugassert && sugseen)
2254 /* also leave this assertion disabled */
2257 v = r->p > 0 ? r->p : -r->p;
2258 if (solv->decisionmap[v])
2260 if ((solv->decisionmap[v] > 0 && r->p < 0) ||
2261 (solv->decisionmap[v] < 0 && r->p > 0))
2263 printf("direct assertion failure, no solution found!\n");
2266 r = solv->rules + problem[i];
2273 if (r->d == 0 || r->w2 != r->p)
2276 r->w1 = solv->pool->whatprovidesdata[r->d];
2280 /* re-enable as many weak rules as possible */
2281 for (i = solv->weakrules; i < solv->learntrules; i++)
2283 r = solv->rules + i;
2286 if (r->d == 0 || r->w2 != r->p)
2289 r->w1 = solv->pool->whatprovidesdata[r->d];
2292 QUEUEEMPTY(&solv->problems);
2293 revert(solv, 1); /* XXX move to reset_solver? */
2295 run_solver(solv, 0, 0);
2296 if (!solv->problems.count)
2298 printf("no more problems!\n");
2300 printdecisions(solv);
2302 break; /* great, no more problems */
2304 disabledcnt = disabled.count;
2305 for (i = 0; i < solv->problems.elements[i]; i++)
2307 /* ignore solutions in refined */
2308 v = solv->problems.elements[i];
2309 for (j = 0; problem[j]; j++)
2310 if (problem[j] != sug && problem[j] == v)
2314 queuepush(&disabled, v);
2315 queuepush(&disabled, 0); /* room for watch */
2317 if (disabled.count == disabledcnt)
2319 /* no solution found, this was an invalid suggestion! */
2320 printf("no solution found!\n");
2324 if (disabled.count == disabledcnt + 2)
2326 /* just one suggestion, add it to refined list */
2327 queuepush(refined, disabled.elements[disabledcnt]);
2331 printf("############################################## more than one solution found.\n");
2333 for (i = 0; i < solv->problems.elements[i]; i++)
2334 printrule(solv, solv->rules + solv->problems.elements[i]);
2335 printf("##############################################\n");
2337 /* more than one solution, keep all disabled */
2339 for (i = disabledcnt; i < disabled.count; i += 2)
2342 r = solv->rules + disabled.elements[i];
2343 disabled.elements[i + 1] = r->w1;
2351 /* enable refined rules again */
2352 for (i = 0; i < disabled.count; i += 2)
2354 r = solv->rules + disabled.elements[i];
2355 r->w1 = disabled.elements[i + 1];
2357 /* disable problem rules again so that we are in the same state as before */
2358 for (i = 0; problem[i]; i++)
2360 r = solv->rules + problem[i];
2363 printf("refine_suggestion end\n");
2372 id2rc(Solver *solv, Id id)
2375 if (solv->rc_output != 2)
2377 evr = id2str(solv->pool, id);
2378 if (*evr < '0' || *evr > '9')
2380 while (*evr >= '0' && *evr <= '9')
2388 printdecisions(Solver *solv)
2390 Pool *pool = solv->pool;
2391 Id p, *obsoletesmap;
2395 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2396 for (i = 0; i < solv->decisionq.count; i++)
2401 n = solv->decisionq.elements[i];
2404 if (n == SYSTEMSOLVABLE)
2406 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2408 s = pool->solvables + n;
2411 obsp = s->source->idarraydata + s->obsoletes;
2412 while ((obs = *obsp++) != 0)
2413 FOR_PROVIDES(p, pp, obs)
2415 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2417 obsoletesmap[p] = n;
2422 FOR_PROVIDES(p, pp, s->name)
2423 if (s->name == pool->solvables[p].name)
2425 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2427 obsoletesmap[p] = n;
2433 if (solv->rc_output)
2434 printf(">!> Solution #1:\n");
2436 int installs = 0, uninstalls = 0, upgrades = 0;
2438 /* print solvables to be erased */
2440 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2442 if (solv->decisionmap[i] > 0)
2444 if (obsoletesmap[i])
2446 s = pool->solvables + i;
2447 if (solv->rc_output == 2)
2448 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2449 else if (solv->rc_output)
2450 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2452 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2456 /* print solvables to be installed */
2458 for (i = 0; i < solv->decisionq.count; i++)
2461 p = solv->decisionq.elements[i];
2464 if (p == SYSTEMSOLVABLE)
2466 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2468 s = pool->solvables + p;
2470 if (!obsoletesmap[p])
2472 if (solv->rc_output)
2474 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2475 if (solv->rc_output != 2)
2476 printf(".%s", id2str(pool, s->arch));
2479 else if (!solv->rc_output)
2481 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2482 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2484 if (obsoletesmap[j] != p)
2486 s = pool->solvables + j;
2487 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2494 Solvable *f, *fn = 0;
2495 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2497 if (obsoletesmap[j] != p)
2499 f = pool->solvables + j;
2500 if (fn || f->name != s->name)
2502 if (solv->rc_output == 2)
2503 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2504 else if (solv->rc_output)
2505 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2513 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2514 if (solv->rc_output != 2)
2515 printf(".%s", id2str(pool, s->arch));
2520 if (solv->rc_output == 2)
2521 printf(">!> upgrade %s-%s => %s-%s%s", id2str(pool, fn->name), id2str(pool, fn->evr), id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2523 printf(">!> upgrade %s-%s.%s => %s-%s.%s", id2str(pool, fn->name), id2str(pool, fn->evr), id2str(pool, fn->arch), id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2527 if (solv->rc_output)
2529 Source *source = s->source;
2530 if (source && strcmp(source_name(source), "locales"))
2531 printf("[%s]", source_name(source));
2536 if (solv->rc_output)
2537 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2539 xfree(obsoletesmap);
2543 create_obsolete_index(Solver *solv)
2545 Pool *pool = solv->pool;
2547 Source *system = solv->system;
2548 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
2551 /* create reverse obsoletes map for system solvables */
2552 solv->obsoletes = obsoletes = xcalloc(system->nsolvables, sizeof(Id));
2553 for (i = 1; i < pool->nsolvables; i++)
2555 s = pool->solvables + i;
2558 if (!pool_installable(pool, s))
2560 obsp = s->source->idarraydata + s->obsoletes;
2561 while ((obs = *obsp++) != 0)
2562 FOR_PROVIDES(p, pp, obs)
2564 if (p < system->start || p >= system->start + system->nsolvables)
2566 if (pool->solvables[p].name == s->name)
2568 obsoletes[p - system->start]++;
2572 for (i = 0; i < system->nsolvables; i++)
2575 n += obsoletes[i] + 1;
2578 solv->obsoletes_data = obsoletes_data = xcalloc(n + 1, sizeof(Id));
2579 if (pool->verbose) printf("obsoletes data: %d entries\n", n + 1);
2580 for (i = pool->nsolvables - 1; i > 0; i--)
2582 s = pool->solvables + i;
2585 if (!pool_installable(pool, s))
2587 obsp = s->source->idarraydata + s->obsoletes;
2588 while ((obs = *obsp++) != 0)
2589 FOR_PROVIDES(p, pp, obs)
2591 if (p < system->start || p >= system->start + system->nsolvables)
2593 if (pool->solvables[p].name == s->name)
2596 if (obsoletes_data[obsoletes[p]] != i)
2597 obsoletes_data[--obsoletes[p]] = i;
2602 /*-----------------------------------------------------------------*/
2612 solve(Solver *solv, Queue *job)
2614 Pool *pool = solv->pool;
2616 Map addedmap; /* '1' == have rule for solvable */
2617 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2618 Id how, what, p, *pp, d;
2624 * create basic rule set of all involved packages
2629 mapinit(&addedmap, pool->nsolvables);
2630 mapinit(&noupdaterule, pool->nsolvables);
2635 * always install our system solvable
2637 MAPSET(&addedmap, SYSTEMSOLVABLE);
2638 queuepush(&solv->decisionq, SYSTEMSOLVABLE);
2639 queuepush(&solv->decisionq_why, 0);
2640 solv->decisionmap[SYSTEMSOLVABLE] = 1;
2643 * create rules for installed solvables -> keep them installed
2644 * so called: rpm rules
2648 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2649 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2652 * create install rules
2654 * two passes, as we want to keep the rpm rules distinct from the job rules
2658 if (solv->noupdateprovide && solv->system->nsolvables)
2659 create_obsolete_index(solv);
2663 * process job rules for solvables
2666 for (i = 0; i < job->count; i += 2)
2668 how = job->elements[i];
2669 what = job->elements[i + 1];
2673 case SOLVER_INSTALL_SOLVABLE:
2674 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2676 case SOLVER_INSTALL_SOLVABLE_NAME:
2677 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2679 FOR_PROVIDES(p, pp, what)
2681 /* if by name, ensure that the name matches */
2682 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2684 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2687 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2688 /* dont allow downgrade */
2689 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2695 * if unstalls are disallowed, add update rules for every
2696 * installed solvables in the hope to circumvent uninstall
2702 if (!solv->allowuninstall)
2704 /* add update rule for every installed package */
2705 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2706 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2708 #else /* this is just to add the needed rpm rules to our set */
2709 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2710 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2713 addrulesforweak(solv, &addedmap);
2717 int possible = 0, installable = 0;
2718 for (i = 1; i < pool->nsolvables; i++)
2720 if (pool_installable(pool, pool->solvables + i))
2722 if (MAPTST(&addedmap, i))
2725 printf("%d of %d installable solvables used for solving\n", possible, installable);
2732 * unify existing rules before going over all job rules
2736 unifyrules(solv); /* remove duplicate rpm rules */
2739 * at this point the system is always solvable,
2740 * as an empty system (remove all packages) is a valid solution
2742 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2745 * now add all job rules
2748 solv->jobrules = solv->nrules;
2750 for (i = 0; i < job->count; i += 2)
2752 how = job->elements[i];
2753 what = job->elements[i + 1];
2756 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2757 if (solv->rc_output) {
2758 Solvable *s = pool->solvables + what;
2759 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(s->source));
2761 addrule(solv, what, 0); /* install by Id */
2762 queuepush(&solv->ruletojob, i);
2764 case SOLVER_ERASE_SOLVABLE:
2765 addrule(solv, -what, 0); /* remove by Id */
2766 queuepush(&solv->ruletojob, i);
2767 MAPSET(&noupdaterule, what);
2769 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2770 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2772 FOR_PROVIDES(p, pp, what)
2774 /* if by name, ensure that the name matches */
2775 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2781 /* no provider, make this an impossible rule */
2782 queuepush(&q, -SYSTEMSOLVABLE);
2785 p = queueshift(&q); /* get first provider */
2787 d = 0; /* single provider ? -> make assertion */
2789 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2790 addrule(solv, p, d); /* add 'requires' rule */
2791 queuepush(&solv->ruletojob, i);
2793 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2794 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2795 FOR_PROVIDES(p, pp, what)
2797 /* if by name, ensure that the name matches */
2798 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2801 addrule(solv, -p, 0); /* add 'remove' rule */
2802 queuepush(&solv->ruletojob, i);
2803 MAPSET(&noupdaterule, p);
2806 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2807 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2808 queuepush(&solv->ruletojob, i);
2813 if (solv->ruletojob.count != solv->nrules - solv->jobrules)
2816 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2819 * now add policy rules
2823 solv->systemrules = solv->nrules;
2826 * create rules for updating installed solvables
2832 if (!solv->allowuninstall)
2833 { /* loop over all installed solvables */
2834 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2836 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2837 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2839 addrule(solv, 0, 0); /* place holder */
2841 /* consistency check: we added a rule for _every_ system solvable */
2842 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2846 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2848 /* create special weak system rules */
2849 if (solv->system->nsolvables)
2851 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2852 for (i = 0; i < solv->system->nsolvables; i++)
2854 if (MAPTST(&noupdaterule, solv->system->start + i))
2856 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2858 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2862 /* free unneeded memory */
2864 mapfree(&noupdaterule);
2867 solv->weakrules = solv->nrules;
2869 /* try real hard to keep packages installed */
2872 for (i = 0; i < solv->system->nsolvables; i++)
2874 d = solv->weaksystemrules[i];
2875 addrule(solv, solv->system->start + i, d);
2884 makeruledecisions(solv);
2885 run_solver(solv, 1, 1);
2887 /* find suggested packages */
2888 if (!solv->problems.count)
2890 Id sug, *sugp, enh, *enhp, p, *pp;
2892 /* create map of all suggests that are still open */
2893 solv->recommends_index = -1;
2894 MAPZERO(&solv->suggestsmap);
2895 for (i = 0; i < solv->decisionq.count; i++)
2897 p = solv->decisionq.elements[i];
2900 s = pool->solvables + p;
2903 sugp = s->source->idarraydata + s->suggests;
2904 while ((sug = *sugp++) != 0)
2906 FOR_PROVIDES(p, pp, sug)
2907 if (solv->decisionmap[p] > 0)
2910 continue; /* already fulfilled */
2911 FOR_PROVIDES(p, pp, sug)
2912 MAPSET(&solv->suggestsmap, p);
2916 for (i = 1; i < pool->nsolvables; i++)
2918 if (solv->decisionmap[i] != 0)
2920 s = pool->solvables + i;
2921 if (!MAPTST(&solv->suggestsmap, i))
2925 if (!pool_installable(pool, s))
2927 enhp = s->source->idarraydata + s->enhances;
2928 while ((enh = *enhp++) != 0)
2929 if (dep_fulfilled(solv, enh))
2934 queuepush(&solv->suggestions, i);
2936 prune_best_version_arch(pool, &solv->suggestions);
2941 * print solver result
2945 if (pool->verbose) printf("-------------------------------------------------------------\n");
2947 if (solv->problems.count)
2957 clonequeue(&problems, &solv->problems);
2958 queueinit(&solution);
2959 printf("Encountered problems! Here are the solutions:\n");
2960 problem = problems.elements;
2961 for (i = 0; i < problems.count; i++)
2963 Id v = problems.elements[i];
2966 printf("====================================\n");
2967 problem = problems.elements + i + 1;
2970 if (v >= solv->jobrules && v < solv->systemrules)
2972 ji = solv->ruletojob.elements[v - solv->jobrules];
2975 if (problem[j] >= solv->jobrules && problem[j] < solv->systemrules && ji == solv->ruletojob.elements[problem[j] - solv->jobrules])
2978 if (problem + j < problems.elements + i)
2981 refine_suggestion(solv, problem, v, &solution);
2982 for (j = 0; j < solution.count; j++)
2984 r = solv->rules + solution.elements[j];
2985 why = solution.elements[j];
2989 if (why >= solv->jobrules && why < solv->systemrules)
2991 ji = solv->ruletojob.elements[why - solv->jobrules];
2992 what = job->elements[ji + 1];
2993 switch (job->elements[ji])
2995 case SOLVER_INSTALL_SOLVABLE:
2996 s = pool->solvables + what;
2997 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2999 case SOLVER_ERASE_SOLVABLE:
3000 s = pool->solvables + what;
3001 printf("- do not deinstall %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3003 case SOLVER_INSTALL_SOLVABLE_NAME:
3004 printf("- do not install %s\n", id2str(pool, what));
3006 case SOLVER_ERASE_SOLVABLE_NAME:
3007 printf("- do not deinstall %s\n", id2str(pool, what));
3009 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
3010 printf("- do not install a solvable providing %s\n", dep2str(pool, what));
3012 case SOLVER_ERASE_SOLVABLE_PROVIDES:
3013 printf("- do not deinstall all solvables providing %s\n", dep2str(pool, what));
3015 case SOLVER_INSTALL_SOLVABLE_UPDATE:
3016 s = pool->solvables + what;
3017 printf("- do not install most recent version of %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
3020 printf("- do something different\n");
3024 else if (why >= solv->systemrules && why < solv->weakrules)
3027 s = pool->solvables + solv->system->start + (why - solv->systemrules);
3028 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
3030 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
3033 if (*dp >= solv->system->start && *dp < solv->system->start + solv->system->nsolvables)
3035 if (solv->decisionmap[*dp] > 0)
3037 sd = pool->solvables + *dp;
3045 if (evrcmp(pool, sd->evr, s->evr) < 0)
3047 printf("- allow downgrade of %s-%s.%s to %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3050 if (!solv->allowarchchange && archchanges(pool, sd, s))
3052 printf("- allow architecture change of %s-%s.%s to %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3056 printf("- allow replacement of %s-%s.%s with %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), id2str(pool, sd->name), id2str(pool, sd->evr), id2str(pool, sd->arch));
3060 printf("- allow deinstallation of %s-%s.%s [%ld]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), (long int)(s - pool->solvables));
3068 printf("------------------------------------\n");
3069 queuefree(&problems);
3070 queuefree(&solution);
3075 printdecisions(solv);
3076 if (solv->suggestions.count)
3078 printf("\nsuggested packages:\n");
3079 for (i = 0; i < solv->suggestions.count; i++)
3081 s = pool->solvables + solv->suggestions.elements[i];
3082 printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));