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_recommended
139 * XXX: should we prune to requires/suggests that are already
140 * fulfilled by other packages?
143 prune_to_recommended(Solver *solv, Queue *plist)
145 Pool *pool = solv->pool;
148 Id p, *pp, sup, *supp, rec, *recp, sug, *sugp, enh, *enhp;
150 if (solv->recommends_index < 0)
152 MAPZERO(&solv->recommendsmap);
153 MAPZERO(&solv->suggestsmap);
154 solv->recommends_index = 0;
156 while (solv->recommends_index < solv->decisionq.count)
158 p = solv->decisionq.elements[solv->recommends_index++];
161 s = pool->solvables + p;
164 recp = s->source->idarraydata + s->recommends;
165 while ((rec = *recp++) != 0)
166 FOR_PROVIDES(p, pp, rec)
167 MAPSET(&solv->recommendsmap, p);
171 sugp = s->source->idarraydata + s->suggests;
172 while ((sug = *sugp++) != 0)
173 FOR_PROVIDES(p, pp, sug)
174 MAPSET(&solv->suggestsmap, p);
177 /* prune to recommended/supplemented */
178 for (i = j = 0; i < plist->count; i++)
180 p = plist->elements[i];
181 if (MAPTST(&solv->recommendsmap, p))
183 plist->elements[j++] = p;
186 s = pool->solvables + p;
187 if (!s->supplements && !s->freshens)
191 supp = s->source->idarraydata + s->supplements;
192 while ((sup = *supp++) != 0)
193 if (dep_fulfilled(solv, sup))
200 supp = s->source->idarraydata + s->freshens;
201 while ((sup = *supp++) != 0)
202 if (dep_fulfilled(solv, sup))
207 plist->elements[j++] = s - pool->solvables;
212 /* prune to suggested/enhanced*/
213 if (plist->count < 2)
215 for (i = j = 0; i < plist->count; i++)
217 p = plist->elements[i];
218 if (MAPTST(&solv->suggestsmap, p))
220 plist->elements[j++] = p;
223 s = pool->solvables + p;
226 enhp = s->source->idarraydata + s->enhances;
227 while ((enh = *enhp++) != 0)
228 if (dep_fulfilled(solv, enh))
232 plist->elements[j++] = s - pool->solvables;
239 * prune_best_version_arch
241 * sort list of packages (given through plist) by name and evr
242 * return result through plist
246 /* FIXME: must also look at update packages */
249 prune_best_version_arch(Pool *pool, Queue *plist)
256 if (plist->count < 2) /* no need to prune for a single entry */
258 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
260 /* prune to best architecture */
264 for (i = 0; i < plist->count; i++)
266 s = pool->solvables + plist->elements[i];
268 if (a > pool->lastarch)
270 a = pool->id2arch[a];
271 if (!bestscore || (a & 0xffff0000) < bestscore)
272 bestscore = a & 0xffff0000;
274 for (i = j = 0; i < plist->count; i++)
276 s = pool->solvables + plist->elements[i];
278 if (a > pool->lastarch)
280 a = pool->id2arch[a];
281 /* a == 1 -> noarch */
282 if (a != 1 && (a & 0xffff0000) != bestscore)
284 plist->elements[j++] = plist->elements[i];
291 prune_best_version_arch_sortcmp_data = pool;
292 /* sort by name first */
293 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
295 /* now find best 'per name' */
296 for (i = j = 0; i < plist->count; i++)
298 s = pool->solvables + plist->elements[i];
300 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
302 if (!best) /* if no best yet, the current is best */
304 best = plist->elements[i];
308 /* name switch: re-init */
309 if (pool->solvables[best].name != s->name) /* new name */
311 if (pool->verbose) printf("BEST: %s-%s.%s\n", id2str(pool, pool->solvables[best].name), id2str(pool, pool->solvables[best].evr), id2str(pool, pool->solvables[best].arch));
312 plist->elements[j++] = best; /* move old best to front */
313 best = plist->elements[i]; /* take current as new best */
317 if (pool->solvables[best].evr != s->evr) /* compare evr */
319 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
320 best = plist->elements[i];
325 best = plist->elements[0];
327 /* XXX also check obsoletes! */
328 if (pool->verbose) printf("BEST: %s-%s.%s\n", id2str(pool, pool->solvables[best].name), id2str(pool, pool->solvables[best].evr), id2str(pool, pool->solvables[best].arch));
330 plist->elements[j++] = best;
335 /*-----------------------------------------------------------------*/
342 printruleelement(Solver *solv, Rule *r, Id v)
344 Pool *pool = solv->pool;
348 s = pool->solvables + -v;
349 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
353 s = pool->solvables + v;
354 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
363 if (solv->decisionmap[s - pool->solvables] > 0)
364 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
365 if (solv->decisionmap[s - pool->solvables] < 0)
366 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
376 printrule(Solver *solv, Rule *r)
381 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
382 printf("Rule #%d:\n", (int)(r - solv->rules));
384 printf("Rule:\n"); /* r is any rule */
389 else if (r->d == ID_NULL)
396 v = solv->pool->whatprovidesdata[r->d + i - 1];
399 printruleelement(solv, r, v);
401 printf(" next: %d %d\n", r->n1, r->n2);
405 /*-----------------------------------------------------------------*/
411 static Pool *unifyrules_sortcmp_data;
414 * compare rules for unification sort
418 unifyrules_sortcmp(const void *ap, const void *bp)
420 Pool *pool = unifyrules_sortcmp_data;
421 Rule *a = (Rule *)ap;
422 Rule *b = (Rule *)bp;
428 return x; /* p differs */
431 if (a->d == 0 && b->d == 0)
432 return a->w2 - b->w2; /* assertion: return w2 diff */
434 if (a->d == 0) /* a is assertion, b not */
436 x = a->w2 - pool->whatprovidesdata[b->d];
440 if (b->d == 0) /* b is assertion, a not */
442 x = pool->whatprovidesdata[a->d] - b->w2;
446 /* compare whatprovidesdata */
447 ad = pool->whatprovidesdata + a->d;
448 bd = pool->whatprovidesdata + b->d;
450 if ((x = *ad++ - *bd++) != 0)
461 unifyrules(Solver *solv)
466 if (solv->nrules <= 1) /* nothing to unify */
469 /* sort rules first */
470 unifyrules_sortcmp_data = solv->pool;
471 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
478 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
480 if (jr && !unifyrules_sortcmp(ir, jr))
481 continue; /* prune! */
482 jr = solv->rules + j++; /* keep! */
487 /* reduced count from nrules to j rules */
488 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
490 /* adapt rule buffer */
491 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
500 for (i = 1; i < solv->nrules; i++)
503 if (r->d == 0) /* assertion */
508 dp = solv->pool->whatprovidesdata + r->d;
512 if (solv->pool->verbose)
514 printf(" binary: %d\n", binr);
515 printf(" normal: %d\n", solv->nrules - 1 - binr);
516 printf(" normal lits: %d\n", dc);
529 hashrule(Solver *solv, Id p, Id d, int n)
531 unsigned int x = (unsigned int)p;
535 return (x * 37) ^ (unsigned int)d;
536 dp = solv->pool->whatprovidesdata + d;
538 x = (x * 37) ^ (unsigned int)*dp++;
546 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
547 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
550 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
552 * p < 0 : rule from rpm (installed pkg)
553 * d > 0 : Offset in whatprovidesdata (list of providers)
555 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
556 * d < 0: Id of solvable (e.g. B1)
558 * d == 0: unary rule, assertion => (A) or (-A)
560 * Install: p > 0, d = 0 (A) user requested install
561 * Remove: p < 0, d = 0 (-A) user requested remove
562 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
563 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
564 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
565 * ? p > 0, d < 0 (A|-B)
566 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
570 addrule(Solver *solv, Id p, Id d)
575 int n = 0; /* number of literals in rule - 1
576 0 = direct assertion (single literal)
580 /* it often happenes that requires lead to adding the same rpm rule
581 * multiple times, so we prune those duplicates right away to make
582 * the work for unifyrules a bit easier */
584 if (solv->nrules && !solv->jobrules)
586 r = solv->rules + solv->nrules - 1; /* get the last added rule */
587 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
594 return 0; /* ignore self conflict */
597 else if (d == 0) /* user requested */
601 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
603 return 0; /* rule is self-fulfilling */
608 if (n == 0) /* direct assertion */
612 /* this is a rpm rule assertion, we do not have to allocate it */
613 /* it can be identified by a level of 1 and a zero reason */
616 if (solv->decisionmap[-p] > 0 || solv->decisionmap[-p] < -1)
618 if (solv->decisionmap[-p])
620 queuepush(&solv->decisionq, p);
621 queuepush(&solv->decisionq_why, 0);
622 solv->decisionmap[-p] = -1;
626 else if (n == 1 && p > d)
628 /* smallest literal first so we can find dups */
632 n = 1; /* re-set n, was used as temp var */
635 /* check if the last added rule is exactly the same as what we're looking for. */
636 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
639 if (r && n > 1 && r->d && r->p == p)
644 dp2 = solv->pool->whatprovidesdata + r->d;
645 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
656 /* check and extend rule buffer */
657 if ((solv->nrules & RULES_BLOCK) == 0)
659 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
662 r = solv->rules + solv->nrules++; /* point to rule space */
667 /* direct assertion, no watch needed */
683 r->w2 = solv->pool->whatprovidesdata[d];
691 /* go through system and job rules and add direct assertions
692 * to the decisionqueue. If we find a conflict, disable rules and
693 * add them to problem queue.
696 makeruledecisions(Solver *solv)
702 /* no learnt rules for now */
703 if (solv->learntrules && solv->learntrules != solv->nrules)
706 for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
712 if (solv->decisionmap[vv] == 0)
714 queuepush(&solv->decisionq, v);
715 queuepush(&solv->decisionq_why, r - solv->rules);
716 solv->decisionmap[vv] = v > 0 ? 1 : -1;
719 if (v > 0 && solv->decisionmap[vv] > 0)
721 if (v < 0 && solv->decisionmap[vv] < 0)
723 /* found a conflict! */
724 /* if we are weak, just disable ourself */
725 if (ri >= solv->weakrules)
727 printf("conflict, but I am weak, disabling ");
732 for (i = 0; i < solv->decisionq.count; i++)
733 if (solv->decisionq.elements[i] == -v)
735 if (i == solv->decisionq.count)
737 if (solv->decisionq_why.elements[i] == 0)
739 /* conflict with rpm rule, need only disable our rule */
740 printf("conflict with rpm rule, disabling rule #%d\n", ri);
741 queuepush(&solv->problems, r - solv->rules);
742 queuepush(&solv->problems, 0);
743 r->w1 = 0; /* disable */
746 /* conflict with another job or system rule */
747 /* remove old decision */
748 printf("conflicting system/job rules over literal %d\n", vv);
749 solv->decisionmap[vv] = 0;
750 for (; i + 1 < solv->decisionq.count; i++)
752 solv->decisionq.elements[i] = solv->decisionq.elements[i + 1];
753 solv->decisionq_why.elements[i] = solv->decisionq_why.elements[i + 1];
755 solv->decisionq.count--;
756 solv->decisionq_why.count--;
757 /* push all of our rules asserting this literal on the problem stack */
758 for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
760 if (!rr->w1 || rr->w2)
762 if (rr->p != v && rr->p != -v)
764 printf(" - disabling rule #%d\n", i);
765 queuepush(&solv->problems, i);
766 rr->w1 = 0; /* disable */
768 queuepush(&solv->problems, 0);
774 * add (install) rules for solvable
779 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
781 Pool *pool = solv->pool;
782 Source *system = solv->system;
795 queueinit_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
796 queuepush(&q, s - pool->solvables); /* push solvable Id */
802 * s: Pointer to solvable
806 if (MAPTST(m, n)) /* continue if already done */
810 s = pool->solvables + n; /* s = Solvable in question */
815 && n >= system->start /* is it installed? */
816 && n < system->start + system->nsolvables)
818 dontfix = 1; /* dont care about broken rpm deps */
821 /*-----------------------------------------
822 * check requires of s
827 reqp = s->source->idarraydata + s->requires;
828 while ((req = *reqp++) != 0)
830 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
833 dp = GET_PROVIDESP(req, p); /* get providers of req */
835 if (!*dp /* dont care if noone provides rpmlib() */
836 && !strncmp(id2str(pool, req), "rpmlib(", 7))
841 if (dontfix) /* dont care about breakage */
843 /* the strategy here is to not insist on dependencies
844 * that are already broken. so if we find one provider
845 * that was already installed, we know that the
846 * dependency was not broken before so we enforce it */
847 for (i = 0; dp[i]; i++) /* for all providers */
849 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
850 break; /* provider is installed */
852 if (!dp[i]) /* previously broken dependency */
854 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));
861 /* nothing provides req! */
863 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));
865 addrule(solv, -n, 0); /* mark requestor as uninstallable */
867 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), source_name(s->source));
871 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);
872 for (i = 0; dp[i]; i++)
873 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));
875 /* add 'requires' dependency */
876 /* rule: (-requestor|provider1|provider2|...|providerN) */
877 addrule(solv, -n, dp - pool->whatprovidesdata);
879 /* descend the dependency tree */
880 for (; *dp; dp++) /* loop through all providers */
886 } /* while, requirements of n */
888 } /* if, requirements */
891 /*-----------------------------------------
892 * check conflicts of s
897 conp = s->source->idarraydata + s->conflicts;
898 while ((con = *conp++) != 0)
900 FOR_PROVIDES(p, pp, con)
902 /* dontfix: dont care about conflicts with already installed packs */
903 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
905 /* rule: -n|-p: either solvable _or_ provider of conflict */
906 addrule(solv, -n, -p);
911 /*-----------------------------------------
912 * check obsoletes if not installed
914 if (!system || n < system->start || n >= (system->start + system->nsolvables))
915 { /* not installed */
918 obsp = s->source->idarraydata + s->obsoletes;
919 while ((obs = *obsp++) != 0)
921 FOR_PROVIDES(p, pp, obs)
922 addrule(solv, -n, -p);
925 FOR_PROVIDES(p, pp, s->name)
927 if (s->name == pool->solvables[p].name)
928 addrule(solv, -n, -p);
932 /*-----------------------------------------
933 * add recommends to the rule list
937 recp = s->source->idarraydata + s->recommends;
938 while ((rec = *recp++) != 0)
940 FOR_PROVIDES(p, pp, rec)
950 addrulesforsupplements(Solver *solv, Map *m)
952 Pool *pool = solv->pool;
957 if (pool->verbose) printf("addrulesforsupplements... (%d)\n", solv->nrules);
958 for (i = n = 1; n < pool->nsolvables; i++, n++)
960 if (i == pool->nsolvables)
964 s = pool->solvables + i;
965 if (!pool_installable(pool, s))
970 supp = s->source->idarraydata + s->supplements;
971 while ((sup = *supp++) != ID_NULL)
972 if (dep_possible(solv, sup, m))
975 if (!sup && s->freshens)
977 supp = s->source->idarraydata + s->freshens;
978 while ((sup = *supp++) != ID_NULL)
979 if (dep_possible(solv, sup, m))
984 addrulesforsolvable(solv, s, m);
987 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
991 addrulesforenhances(Solver *solv, Map *m)
993 Pool *pool = solv->pool;
996 Id p, *pp, enh, *enhp, obs, *obsp, con, *conp;
998 if (pool->verbose) printf("addrulesforenhances... (%d)\n", solv->nrules);
999 for (i = 1; i < pool->nsolvables; i++)
1003 s = pool->solvables + i;
1006 if (!pool_installable(pool, s))
1008 enhp = s->source->idarraydata + s->enhances;
1009 while ((enh = *enhp++) != ID_NULL)
1010 if (dep_possible(solv, enh, m))
1016 conp = s->source->idarraydata + s->conflicts;
1017 while ((con = *conp++) != 0)
1018 FOR_PROVIDES(p, pp, con)
1019 addrule(solv, -i, -p);
1023 obsp = s->source->idarraydata + s->obsoletes;
1024 while ((obs = *obsp++) != ID_NULL)
1025 FOR_PROVIDES(p, pp, obs)
1026 addrule(solv, -i, -p);
1028 FOR_PROVIDES(p, pp, s->name)
1029 if (s->name == pool->solvables[p].name)
1030 addrule(solv, -i, -p);
1036 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
1038 Id a1 = s1->arch, a2 = s2->arch;
1040 /* we allow changes to/from noarch */
1041 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
1045 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
1046 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
1047 if (((a1 ^ a2) & 0xffff0000) != 0)
1054 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
1056 /* system packages get a special upgrade allowed rule */
1057 Pool *pool = solv->pool;
1058 Id p, *pp, n, p2, *pp2;
1067 n = s - pool->solvables;
1068 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
1069 addrulesforsolvable(solv, s, m);
1072 * look for updates for s
1074 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
1076 if (p == n) /* skip itself */
1079 ps = pool->solvables + p;
1080 if (s->name == ps->name) /* name match */
1082 if (!allowdowngrade /* consider downgrades ? */
1083 && evrcmp(pool, s->evr, ps->evr) > 0)
1086 if (!allowarchchange && archchanges(pool, s, ps))
1089 else if (!solv->noupdateprovide && ps->obsoletes) /* provides/obsoletes combination ? */
1091 obsp = ps->source->idarraydata + ps->obsoletes;
1092 while ((obs = *obsp++) != 0) /* for all obsoletes */
1094 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
1096 if (p2 == n) /* match ! */
1099 if (p2) /* match! */
1102 if (!obs) /* continue if no match */
1104 /* here we have 'p' with a matching provides/obsoletes combination
1105 * thus flagging p as a valid update candidate for s
1112 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1113 addrulesforsolvable(solv, pool->solvables + p, m);
1115 if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->system->start])
1117 for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->system->start]; (p = *pp++) != 0;)
1120 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1121 addrulesforsolvable(solv, pool->solvables + p, m);
1127 * add rule for update
1128 * (A|A1|A2|A3...) An = update candidates for A
1130 * s = (installed) solvable
1131 * m = 'addedmap', bit set if 'install' rule for solvable exists
1135 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
1137 /* system packages get a special upgrade allowed rule */
1138 Pool *pool = solv->pool;
1144 queueinit_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1145 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
1146 p = s - pool->solvables;
1147 if (dontaddrule) /* we consider update candidates but dont force them */
1153 if (qs.count == 0) /* no updates found */
1156 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1158 addrule(solv, p, 0); /* request 'install' of s */
1163 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1165 r = addrule(solv, p, d); /* allow update of s */
1167 printf("new update rule ");
1174 /*-----------------------------------------------------------------*/
1181 * initial setup for all watches
1185 makewatches(Solver *solv)
1189 int nsolvables = solv->pool->nsolvables;
1191 xfree(solv->watches);
1192 /* lower half for removals, upper half for installs */
1193 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1195 /* do it reverse so rpm rules get triggered first */
1196 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1198 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1201 if (!r->w1 /* rule is disabled */
1202 || !r->w2) /* rule is assertion */
1205 /* see addwatches(solv, r) */
1206 r->n1 = solv->watches[nsolvables + r->w1];
1207 solv->watches[nsolvables + r->w1] = r - solv->rules;
1209 r->n2 = solv->watches[nsolvables + r->w2];
1210 solv->watches[nsolvables + r->w2] = r - solv->rules;
1216 * add watches (for rule)
1220 addwatches(Solver *solv, Rule *r)
1222 int nsolvables = solv->pool->nsolvables;
1224 r->n1 = solv->watches[nsolvables + r->w1];
1225 solv->watches[nsolvables + r->w1] = r - solv->rules;
1227 r->n2 = solv->watches[nsolvables + r->w2];
1228 solv->watches[nsolvables + r->w2] = r - solv->rules;
1232 /*-----------------------------------------------------------------*/
1233 /* rule propagation */
1235 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1240 * propagate decision to all rules
1244 propagate(Solver *solv, int level)
1246 Pool *pool = solv->pool;
1251 Id *decisionmap = solv->decisionmap;
1252 Id *watches = solv->watches + pool->nsolvables;
1254 while (solv->propagate_index < solv->decisionq.count)
1256 /* negative because our watches trigger if literal goes FALSE */
1257 pkg = -solv->decisionq.elements[solv->propagate_index++];
1259 printf("popagate for decision %d level %d\n", -pkg, level);
1260 printruleelement(solv, 0, -pkg);
1262 for (rp = watches + pkg; *rp; rp = nrp)
1264 r = solv->rules + *rp;
1266 printf(" watch triggered ");
1279 /* if clause is TRUE, nothing to do */
1280 if (DECISIONMAP_TRUE(ow))
1285 /* not a binary clause, check if we need to move our watch */
1286 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1289 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1290 if (p != ow && !DECISIONMAP_TRUE(-p))
1294 /* p is free to watch, move watch to p */
1297 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));
1299 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));
1313 watches[p] = r - solv->rules;
1317 /* unit clause found, set other watch to TRUE */
1318 if (DECISIONMAP_TRUE(-ow))
1319 return r; /* eek, a conflict! */
1325 decisionmap[ow] = level;
1327 decisionmap[-ow] = -level;
1328 queuepush(&solv->decisionq, ow);
1329 queuepush(&solv->decisionq_why, r - solv->rules);
1332 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1334 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1336 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1341 return 0; /* all is well */
1345 /*-----------------------------------------------------------------*/
1354 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1356 Pool *pool = solv->pool;
1359 Map seen; /* global? */
1363 int learnt_why = solv->learnt_pool.count;
1364 Id *decisionmap = solv->decisionmap;
1368 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1369 mapinit(&seen, pool->nsolvables);
1370 idx = solv->decisionq.count;
1374 queuepush(&solv->learnt_pool, c - solv->rules);
1375 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1386 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1388 vv = v > 0 ? v : -v;
1389 if (MAPTST(&seen, vv))
1391 l = solv->decisionmap[vv];
1398 for (j = 0; j < solv->decisionq.count; j++)
1399 if (solv->decisionq.elements[j] == v)
1401 if (j == solv->decisionq.count)
1403 queuepush(&rulq, -(j + 1));
1405 continue; /* initial setting */
1409 num++; /* need to do this one as well */
1414 printf("PUSH %d ", v);
1415 printruleelement(solv, 0, v);
1422 printf("num = %d\n", num);
1428 v = solv->decisionq.elements[--idx];
1429 vv = v > 0 ? v : -v;
1430 if (MAPTST(&seen, vv))
1433 c = solv->rules + solv->decisionq_why.elements[idx];
1441 else if (r.count == 1 && r.elements[0] < 0)
1442 *dr = r.elements[0];
1444 *dr = pool_queuetowhatprovides(pool, &r);
1447 printf("learned rule for level %d (am %d)\n", rlevel, level);
1448 printruleelement(solv, 0, -v);
1449 for (i = 0; i < r.count; i++)
1452 printruleelement(solv, 0, v);
1456 queuepush(&solv->learnt_pool, 0);
1458 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1460 printf("learnt_why ");
1461 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1472 * reset the solver decisions to right after the rpm rules
1476 reset_solver(Solver *solv)
1481 /* delete all learnt rules */
1482 solv->nrules = solv->learntrules;
1483 QUEUEEMPTY(&solv->learnt_why);
1484 QUEUEEMPTY(&solv->learnt_pool);
1486 /* redo all direct rpm rule decisions */
1487 /* we break at the first decision with a why attached, this is
1488 * either a job/system rule decision of a propagated decision */
1489 for (i = 0; i < solv->decisionq.count; i++)
1491 v = solv->decisionq.elements[i];
1492 solv->decisionmap[v > 0 ? v : -v] = 0;
1494 for (i = 0; i < solv->decisionq_why.count; i++)
1495 if (solv->decisionq_why.elements[i])
1499 v = solv->decisionq.elements[i];
1500 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1503 if (solv->pool->verbose)
1504 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1506 solv->decisionq_why.count = i;
1507 solv->decisionq.count = i;
1508 solv->recommends_index = -1;
1509 solv->propagate_index = 0;
1511 /* redo all job/system decisions */
1512 makeruledecisions(solv);
1513 if (solv->pool->verbose)
1514 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1515 /* recreate watches */
1521 * analyze_unsolvable_rule
1525 analyze_unsolvable_rule(Solver *solv, Rule *r)
1528 Id why = r - solv->rules;
1530 if (why >= solv->jobrules && why < solv->systemrules)
1532 if (why >= solv->systemrules && why < solv->weakrules)
1533 printf("SYSTEM %d ", why - solv->systemrules);
1534 if (why >= solv->weakrules && why < solv->learntrules)
1536 if (solv->learntrules && why >= solv->learntrules)
1540 if (solv->learntrules && why >= solv->learntrules)
1542 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1543 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]);
1546 /* do not add rpm rules to problem */
1547 if (why < solv->jobrules)
1549 /* return if problem already countains the rule */
1550 if (solv->problems.count)
1552 for (i = solv->problems.count - 1; i >= 0; i--)
1553 if (solv->problems.elements[i] == 0)
1555 else if (solv->problems.elements[i] == why)
1558 queuepush(&solv->problems, why);
1563 * analyze_unsolvable
1565 * return: 1 - disabled some rules, try again
1570 analyze_unsolvable(Solver *solv, Rule *r, int disablerules)
1572 Pool *pool = solv->pool;
1573 Map seen; /* global? */
1576 Id *decisionmap = solv->decisionmap;
1577 int oldproblemcount;
1581 printf("ANALYZE UNSOLVABLE ----------------------\n");
1583 oldproblemcount = solv->problems.count;
1584 mapinit(&seen, pool->nsolvables);
1585 analyze_unsolvable_rule(solv, r);
1586 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1597 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1599 vv = v > 0 ? v : -v;
1600 l = solv->decisionmap[vv];
1605 idx = solv->decisionq.count;
1608 v = solv->decisionq.elements[--idx];
1609 vv = v > 0 ? v : -v;
1610 if (!MAPTST(&seen, vv))
1612 why = solv->decisionq_why.elements[idx];
1617 printruleelement(solv, 0, v);
1621 r = solv->rules + why;
1622 analyze_unsolvable_rule(solv, r);
1623 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1634 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1636 vv = v > 0 ? v : -v;
1637 l = solv->decisionmap[vv];
1644 queuepush(&solv->problems, 0); /* mark end of this problem */
1647 if (solv->weakrules != solv->learntrules)
1649 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1651 why = solv->problems.elements[i];
1652 if (why < solv->weakrules || why >= solv->learntrules)
1654 if (!lastweak || lastweak < why)
1660 /* disable last weak rule */
1661 solv->problems.count = oldproblemcount;
1662 r = solv->rules + lastweak;
1663 printf("disabling weak ");
1669 else if (disablerules)
1671 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1673 r = solv->rules + solv->problems.elements[i];
1683 /*-----------------------------------------------------------------*/
1684 /* Decision revert */
1688 * revert decision at level
1692 revert(Solver *solv, int level)
1695 while (solv->decisionq.count)
1697 v = solv->decisionq.elements[solv->decisionq.count - 1];
1698 vv = v > 0 ? v : -v;
1699 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1702 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1704 solv->decisionmap[vv] = 0;
1705 solv->decisionq.count--;
1706 solv->decisionq_why.count--;
1707 solv->propagate_index = solv->decisionq.count;
1709 solv->recommends_index = -1;
1714 * watch2onhighest - put watch2 on literal with highest level
1718 watch2onhighest(Solver *solv, Rule *r)
1724 return; /* binary rule, both watches are set */
1725 dp = solv->pool->whatprovidesdata + r->d;
1726 while ((v = *dp++) != 0)
1728 l = solv->decisionmap[v < 0 ? -v : v];
1745 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1755 solv->decisionmap[decision] = level;
1757 solv->decisionmap[-decision] = -level;
1758 queuepush(&solv->decisionq, decision);
1759 queuepush(&solv->decisionq_why, 0);
1763 r = propagate(solv, level);
1767 return analyze_unsolvable(solv, r, disablerules);
1768 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1769 l = analyze(solv, level, r, &p, &d, &why);
1770 if (l >= level || l <= 0)
1772 printf("reverting decisions (level %d -> %d)\n", level, l);
1774 revert(solv, level);
1775 r = addrule(solv, p, d); /* p requires d */
1778 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1780 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1783 queuepush(&solv->learnt_why, why);
1786 /* at least 2 literals, needs watches */
1787 watch2onhighest(solv, r);
1788 addwatches(solv, r);
1790 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1791 queuepush(&solv->decisionq, p);
1792 queuepush(&solv->decisionq_why, r - solv->rules);
1793 printf("decision: ");
1794 printruleelement(solv, 0, p);
1795 printf("new rule: ");
1801 /*-----------------------------------------------------------------*/
1802 /* Main solver interface */
1807 * create solver structure
1809 * pool: all available solvables
1810 * system: installed Solvables
1813 * Upon solving, rules are created to flag the Solvables
1814 * of the 'system' Source as installed.
1818 solver_create(Pool *pool, Source *system)
1821 solv = (Solver *)xcalloc(1, sizeof(Solver));
1823 solv->system = system;
1826 queueinit(&solv->decisionq);
1827 queueinit(&solv->decisionq_why);
1828 queueinit(&solv->problems);
1829 queueinit(&solv->suggestions);
1830 queueinit(&solv->learnt_why);
1831 queueinit(&solv->learnt_pool);
1833 mapinit(&solv->recommendsmap, pool->nsolvables);
1834 mapinit(&solv->suggestsmap, pool->nsolvables);
1835 solv->recommends_index = 0;
1837 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1838 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1839 memset(solv->rules, 0, sizeof(Rule));
1851 solver_free(Solver *solv)
1853 queuefree(&solv->decisionq);
1854 queuefree(&solv->decisionq_why);
1855 queuefree(&solv->learnt_why);
1856 queuefree(&solv->learnt_pool);
1857 queuefree(&solv->problems);
1858 queuefree(&solv->suggestions);
1860 mapfree(&solv->recommendsmap);
1861 mapfree(&solv->suggestsmap);
1862 xfree(solv->decisionmap);
1864 xfree(solv->watches);
1865 xfree(solv->weaksystemrules);
1866 xfree(solv->obsoletes);
1867 xfree(solv->obsoletes_data);
1872 /*-------------------------------------------------------*/
1877 * all rules have been set up, not actually run the solver
1882 run_solver(Solver *solv, int disablerules, int doweak)
1890 Pool *pool = solv->pool;
1894 printf("number of rules: %d\n", solv->nrules);
1897 for (i = 0; i < solv->nrules; i++)
1899 printrule(solv, solv->rules + i);
1904 /* all new rules are learnt after this point */
1905 solv->learntrules = solv->nrules;
1906 /* crate watches lists */
1909 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1911 /* start SAT algorithm */
1913 systemlevel = level + 1;
1914 if (pool->verbose) printf("solving...\n");
1925 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1926 if ((r = propagate(solv, level)) != 0)
1928 if (analyze_unsolvable(solv, r, disablerules))
1930 printf("UNSOLVABLE\n");
1940 if (level < systemlevel && solv->system->nsolvables)
1942 if (!solv->updatesystem)
1944 /* try to keep as many packages as possible */
1945 if (pool->verbose) printf("installing system packages\n");
1946 for (i = solv->system->start, n = 0; ; i++, n++)
1948 if (n == solv->system->nsolvables)
1950 if (i == solv->system->start + solv->system->nsolvables)
1951 i = solv->system->start;
1952 s = pool->solvables + i;
1953 if (solv->decisionmap[i] != 0)
1956 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1959 level = setpropagatelearn(solv, level, i, disablerules);
1962 printf("UNSOLVABLE\n");
1966 if (level <= olevel)
1970 if (solv->weaksystemrules)
1972 if (pool->verbose) printf("installing weak system packages\n");
1973 for (i = solv->system->start, n = 0; ; i++, n++)
1975 if (n == solv->system->nsolvables)
1977 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->system->start] == 0))
1980 if (solv->decisionmap[i] == 0)
1982 if (solv->weaksystemrules[i - solv->system->start])
1984 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1985 while ((p = *dp++) != 0)
1987 if (solv->decisionmap[p] > 0)
1989 if (solv->decisionmap[p] == 0)
1993 continue; /* rule is already true */
1999 prune_to_recommended(solv, &dq);
2001 prune_best_version_arch(pool, &dq);
2003 s = pool->solvables + dq.elements[0];
2004 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2007 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
2010 printf("UNSOLVABLE\n");
2014 if (level <= olevel)
2020 if (n != solv->system->nsolvables)
2023 systemlevel = level;
2030 if (pool->verbose) printf("deciding unresolved rules\n");
2031 for (i = 1, n = 1; ; i++, n++)
2033 if (n == solv->nrules)
2035 if (i == solv->nrules)
2037 r = solv->rules + i;
2043 /* binary or unary rule */
2044 /* need two positive undecided literals */
2045 if (r->p < 0 || r->w2 <= 0)
2047 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2049 queuepush(&dq, r->p);
2050 queuepush(&dq, r->w2);
2055 * all negative literals are installed
2056 * no positive literal is installed
2057 * i.e. the rule is not fulfilled and we
2058 * just need to decide on the positive literals
2062 if (solv->decisionmap[-r->p] <= 0)
2067 if (solv->decisionmap[r->p] > 0)
2069 if (solv->decisionmap[r->p] == 0)
2070 queuepush(&dq, r->p);
2072 dp = pool->whatprovidesdata + r->d;
2073 while ((p = *dp++) != 0)
2077 if (solv->decisionmap[-p] <= 0)
2082 if (solv->decisionmap[p] > 0)
2084 if (solv->decisionmap[p] == 0)
2093 /* cannot happen as this means that
2094 * the rule is unit */
2098 prune_to_recommended(solv, &dq);
2100 prune_best_version_arch(pool, &dq);
2101 p = dq.elements[dq.count - 1];
2102 s = pool->solvables + p;
2104 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2107 level = setpropagatelearn(solv, level, p, disablerules);
2110 printf("UNSOLVABLE\n");
2114 if (level < systemlevel)
2117 } /* for(), decide */
2119 if (n != solv->nrules) /* continue if level < systemlevel */
2122 if (doweak && !solv->problems.count)
2126 if (pool->verbose) printf("installing recommended packages\n");
2128 for (i = 1; i < pool->nsolvables; i++)
2130 if (solv->decisionmap[i] < 0)
2132 if (solv->decisionmap[i] > 0)
2134 Id *recp, rec, *pp, p;
2135 s = pool->solvables + i;
2136 /* installed, check for recommends */
2137 /* XXX need to special case AND ? */
2140 recp = s->source->idarraydata + s->recommends;
2141 while ((rec = *recp++) != 0)
2144 FOR_PROVIDES(p, pp, rec)
2146 if (solv->decisionmap[p] > 0)
2151 else if (solv->decisionmap[p] == 0)
2152 queuepushunique(&dq, p);
2160 s = pool->solvables + i;
2161 if (!s->supplements && !s->freshens)
2163 if (!pool_installable(pool, s))
2167 supp = s->source->idarraydata + s->supplements;
2168 while ((sup = *supp++) != 0)
2169 if (dep_fulfilled(solv, sup))
2176 supp = s->source->idarraydata + s->freshens;
2177 while ((sup = *supp++) != 0)
2178 if (dep_fulfilled(solv, sup))
2183 queuepushunique(&dq, i);
2188 prune_best_version_arch(pool, &dq);
2189 p = dq.elements[dq.count - 1];
2190 s = pool->solvables + p;
2192 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2194 level = setpropagatelearn(solv, level, p, 0);
2209 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2217 printf("refine_suggestion start\n");
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 r = solv->rules + problem[i];
2246 /* direct assertion */
2247 if (r->p == sugassert && sugseen)
2249 /* also leave this assertion disabled */
2252 v = r->p > 0 ? r->p : -r->p;
2253 if (solv->decisionmap[v])
2255 if ((solv->decisionmap[v] > 0 && r->p < 0) ||
2256 (solv->decisionmap[v] < 0 && r->p > 0))
2258 printf("direct assertion failure, no solution found!\n");
2261 r = solv->rules + problem[i];
2268 if (r->d == 0 || r->w2 != r->p)
2271 r->w1 = solv->pool->whatprovidesdata[r->d];
2275 /* re-enable as many weak rules as possible */
2276 for (i = solv->weakrules; i < solv->learntrules; i++)
2278 r = solv->rules + i;
2281 if (r->d == 0 || r->w2 != r->p)
2284 r->w1 = solv->pool->whatprovidesdata[r->d];
2287 QUEUEEMPTY(&solv->problems);
2288 revert(solv, 1); /* XXX move to reset_solver? */
2290 run_solver(solv, 0, 0);
2291 if (!solv->problems.count)
2293 printf("no more problems!\n");
2295 printdecisions(solv);
2297 break; /* great, no more problems */
2299 disabledcnt = disabled.count;
2300 for (i = 0; i < solv->problems.elements[i]; i++)
2302 /* ignore solutions in refined */
2303 v = solv->problems.elements[i];
2304 for (j = 0; problem[j]; j++)
2305 if (problem[j] != sug && problem[j] == v)
2309 queuepush(&disabled, v);
2310 queuepush(&disabled, 0); /* room for watch */
2312 if (disabled.count == disabledcnt)
2314 /* no solution found, this was an invalid suggestion! */
2315 printf("no solution found!\n");
2319 if (disabled.count == disabledcnt + 2)
2321 /* just one suggestion, add it to refined list */
2322 queuepush(refined, disabled.elements[disabledcnt]);
2326 printf("############################################## more than one solution found.\n");
2328 for (i = 0; i < solv->problems.elements[i]; i++)
2329 printrule(solv, solv->rules + solv->problems.elements[i]);
2330 printf("##############################################\n");
2332 /* more than one solution, keep all disabled */
2334 for (i = disabledcnt; i < disabled.count; i += 2)
2337 r = solv->rules + disabled.elements[i];
2338 disabled.elements[i + 1] = r->w1;
2346 /* enable refined rules again */
2347 for (i = 0; i < disabled.count; i += 2)
2349 r = solv->rules + disabled.elements[i];
2350 r->w1 = disabled.elements[i + 1];
2352 /* disable problem rules again so that we are in the same state as before */
2353 for (i = 0; problem[i]; i++)
2355 r = solv->rules + problem[i];
2358 printf("refine_suggestion end\n");
2367 id2rc(Solver *solv, Id id)
2370 if (solv->rc_output != 2)
2372 evr = id2str(solv->pool, id);
2373 if (*evr < '0' || *evr > '9')
2375 while (*evr >= '0' && *evr <= '9')
2383 printdecisions(Solver *solv)
2385 Pool *pool = solv->pool;
2386 Id p, *obsoletesmap;
2390 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2391 for (i = 0; i < solv->decisionq.count; i++)
2396 n = solv->decisionq.elements[i];
2399 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2401 s = pool->solvables + n;
2404 obsp = s->source->idarraydata + s->obsoletes;
2405 while ((obs = *obsp++) != 0)
2406 FOR_PROVIDES(p, pp, obs)
2408 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2410 obsoletesmap[p] = n;
2415 FOR_PROVIDES(p, pp, s->name)
2416 if (s->name == pool->solvables[p].name)
2418 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2420 obsoletesmap[p] = n;
2426 if (solv->rc_output)
2427 printf(">!> Solution #1:\n");
2429 int installs = 0, uninstalls = 0, upgrades = 0;
2431 /* print solvables to be erased */
2433 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2435 if (solv->decisionmap[i] > 0)
2437 if (obsoletesmap[i])
2439 s = pool->solvables + i;
2440 if (solv->rc_output == 2)
2441 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2442 else if (solv->rc_output)
2443 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2445 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2449 /* print solvables to be installed */
2451 for (i = 0; i < solv->decisionq.count; i++)
2454 p = solv->decisionq.elements[i];
2457 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2459 s = pool->solvables + p;
2461 if (!obsoletesmap[p])
2463 if (solv->rc_output)
2465 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2466 if (solv->rc_output != 2)
2467 printf(".%s", id2str(pool, s->arch));
2470 else if (!solv->rc_output)
2472 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2473 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2475 if (obsoletesmap[j] != p)
2477 s = pool->solvables + j;
2478 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2485 Solvable *f, *fn = 0;
2486 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2488 if (obsoletesmap[j] != p)
2490 f = pool->solvables + j;
2491 if (fn || f->name != s->name)
2493 if (solv->rc_output == 2)
2494 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2495 else if (solv->rc_output)
2496 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2504 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2505 if (solv->rc_output != 2)
2506 printf(".%s", id2str(pool, s->arch));
2511 if (solv->rc_output == 2)
2512 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));
2514 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));
2518 if (solv->rc_output)
2520 Source *source = s->source;
2521 if (source && strcmp(source_name(source), "locales"))
2522 printf("[%s]", source_name(source));
2527 if (solv->rc_output)
2528 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2530 xfree(obsoletesmap);
2534 create_obsolete_index(Solver *solv)
2536 Pool *pool = solv->pool;
2538 Source *system = solv->system;
2539 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
2542 /* create reverse obsoletes map for system solvables */
2543 solv->obsoletes = obsoletes = xcalloc(system->nsolvables, sizeof(Id));
2544 for (i = 1; i < pool->nsolvables; i++)
2546 s = pool->solvables + i;
2549 if (!pool_installable(pool, s))
2551 obsp = s->source->idarraydata + s->obsoletes;
2552 while ((obs = *obsp++) != 0)
2553 FOR_PROVIDES(p, pp, obs)
2555 if (p < system->start || p >= system->start + system->nsolvables)
2557 if (pool->solvables[p].name == s->name)
2559 obsoletes[p - system->start]++;
2563 for (i = 0; i < system->nsolvables; i++)
2566 n += obsoletes[i] + 1;
2569 solv->obsoletes_data = obsoletes_data = xcalloc(n + 1, sizeof(Id));
2570 if (pool->verbose) printf("obsoletes data: %d entries\n", n + 1);
2571 for (i = pool->nsolvables - 1; i > 0; i--)
2573 s = pool->solvables + i;
2576 if (!pool_installable(pool, s))
2578 obsp = s->source->idarraydata + s->obsoletes;
2579 while ((obs = *obsp++) != 0)
2580 FOR_PROVIDES(p, pp, obs)
2582 if (p < system->start || p >= system->start + system->nsolvables)
2584 if (pool->solvables[p].name == s->name)
2587 if (obsoletes_data[obsoletes[p]] != i)
2588 obsoletes_data[--obsoletes[p]] = i;
2593 /*-----------------------------------------------------------------*/
2603 solve(Solver *solv, Queue *job)
2605 Pool *pool = solv->pool;
2607 Map addedmap; /* '1' == have rule for solvable */
2608 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2609 Id how, what, p, *pp, d;
2615 * create basic rule set of all involved packages
2620 mapinit(&addedmap, pool->nsolvables);
2621 mapinit(&noupdaterule, pool->nsolvables);
2626 * create rules for installed solvables -> keep them installed
2627 * so called: rpm rules
2631 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2632 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2635 * create install rules
2637 * two passes, as we want to keep the rpm rules distinct from the job rules
2641 if (solv->noupdateprovide && solv->system->nsolvables)
2642 create_obsolete_index(solv);
2646 * process job rules for solvables
2649 for (i = 0; i < job->count; i += 2)
2651 how = job->elements[i];
2652 what = job->elements[i + 1];
2656 case SOLVER_INSTALL_SOLVABLE:
2657 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2659 case SOLVER_INSTALL_SOLVABLE_NAME:
2660 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2662 FOR_PROVIDES(p, pp, what)
2664 /* if by name, ensure that the name matches */
2665 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2667 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2670 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2671 /* dont allow downgrade */
2672 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2678 * if unstalls are disallowed, add update rules for every
2679 * installed solvables in the hope to circumvent uninstall
2685 if (!solv->allowuninstall)
2687 /* add update rule for every installed package */
2688 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2689 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2691 #else /* this is just to add the needed rpm rules to our set */
2692 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2693 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2696 addrulesforsupplements(solv, &addedmap);
2697 addrulesforenhances(solv, &addedmap); /* do this last */
2701 int possible = 0, installable = 0;
2702 for (i = 1; i < pool->nsolvables; i++)
2704 if (pool_installable(pool, pool->solvables + i))
2706 if (MAPTST(&addedmap, i))
2709 printf("%d of %d installable solvables used for solving\n", possible, installable);
2716 * unify existing rules before going over all job rules
2720 unifyrules(solv); /* remove duplicate rpm rules */
2723 * at this point the system is always solvable,
2724 * as an empty system (remove all packages) is a valid solution
2726 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2729 * now add all job rules
2732 solv->jobrules = solv->nrules;
2734 for (i = 0; i < job->count; i += 2)
2736 how = job->elements[i];
2737 what = job->elements[i + 1];
2740 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2741 if (solv->rc_output) {
2742 Solvable *s = pool->solvables + what;
2743 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(s->source));
2745 addrule(solv, what, 0); /* install by Id */
2747 case SOLVER_ERASE_SOLVABLE:
2748 addrule(solv, -what, 0); /* remove by Id */
2749 MAPSET(&noupdaterule, what);
2751 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2752 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2754 FOR_PROVIDES(p, pp, what) /* check all providers */
2756 /* if by name, ensure that the name matches */
2757 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2761 if (!q.count) { /* no provider found -> abort */
2762 fprintf(stderr, "Nothing provides '%s'\n", id2str(pool, what));
2763 /* XXX make this a problem! */
2768 p = queueshift(&q); /* get first provider */
2770 d = 0; /* single provider ? -> make assertion */
2772 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2773 addrule(solv, p, d); /* add 'requires' rule */
2775 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2776 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2777 FOR_PROVIDES(p, pp, what)
2779 /* if by name, ensure that the name matches */
2780 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2783 addrule(solv, -p, 0); /* add 'remove' rule */
2784 MAPSET(&noupdaterule, p);
2787 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2788 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2793 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2796 * now add policy rules
2800 solv->systemrules = solv->nrules;
2803 * create rules for updating installed solvables
2809 if (!solv->allowuninstall)
2810 { /* loop over all installed solvables */
2811 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2813 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2814 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2816 addrule(solv, 0, 0); /* place holder */
2818 /* consistency check: we added a rule for _every_ system solvable */
2819 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2823 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2825 /* create special weak system rules */
2826 if (solv->system->nsolvables)
2828 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2829 for (i = 0; i < solv->system->nsolvables; i++)
2831 if (MAPTST(&noupdaterule, solv->system->start + i))
2833 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2835 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2839 /* free unneeded memory */
2841 mapfree(&noupdaterule);
2844 solv->weakrules = solv->nrules;
2846 /* try real hard to keep packages installed */
2849 for (i = 0; i < solv->system->nsolvables; i++)
2851 d = solv->weaksystemrules[i];
2852 addrule(solv, solv->system->start + i, d);
2861 makeruledecisions(solv);
2862 run_solver(solv, 1, 1);
2864 /* find suggested packages */
2865 if (!solv->problems.count)
2867 Id sug, *sugp, enh, *enhp, req, *reqp, p, *pp;
2869 /* create map of all suggests that are still open */
2870 solv->recommends_index = -1;
2871 MAPZERO(&solv->suggestsmap);
2872 for (i = 0; i < solv->decisionq.count; i++)
2874 p = solv->decisionq.elements[i];
2877 s = pool->solvables + p;
2880 sugp = s->source->idarraydata + s->suggests;
2881 while ((sug = *sugp++) != 0)
2883 FOR_PROVIDES(p, pp, sug)
2884 if (solv->decisionmap[p] > 0)
2887 continue; /* already fulfilled */
2888 FOR_PROVIDES(p, pp, sug)
2889 MAPSET(&solv->suggestsmap, p);
2893 for (i = 1; i < pool->nsolvables; i++)
2895 if (solv->decisionmap[i] != 0)
2897 s = pool->solvables + i;
2898 if (!MAPTST(&solv->suggestsmap, i))
2902 if (!pool_installable(pool, s))
2904 enhp = s->source->idarraydata + s->enhances;
2905 while ((enh = *enhp++) != 0)
2906 if (dep_fulfilled(solv, enh))
2911 /* check if installation is possible at all */
2914 reqp = s->source->idarraydata + s->requires;
2915 while ((req = *reqp++) != 0)
2917 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
2919 FOR_PROVIDES(p, pp, req)
2920 if (solv->decisionmap[p] >= 0)
2922 if (!p && !strncmp(id2str(pool, req), "rpmlib(", 7))
2925 break; /* no provider installable! */
2930 queuepush(&solv->suggestions, i);
2932 prune_best_version_arch(pool, &solv->suggestions);
2937 * print solver result
2941 if (pool->verbose) printf("-------------------------------------------------------------\n");
2943 if (solv->problems.count)
2953 clonequeue(&problems, &solv->problems);
2954 queueinit(&solution);
2955 printf("Encountered problems! Here are the solutions:\n");
2956 problem = problems.elements;
2957 for (i = 0; i < problems.count; i++)
2959 Id v = problems.elements[i];
2962 printf("====================================\n");
2963 problem = problems.elements + i + 1;
2966 refine_suggestion(solv, problem, v, &solution);
2967 for (j = 0; j < solution.count; j++)
2969 r = solv->rules + solution.elements[j];
2970 why = solution.elements[j];
2974 if (why >= solv->jobrules && why < solv->systemrules)
2976 /* do a sloppy job of analyzing the job rule */
2979 s = pool->solvables + r->p;
2980 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2984 s = pool->solvables - r->p;
2985 printf("- do not erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2988 else if (why >= solv->systemrules && why < solv->weakrules)
2991 s = pool->solvables + solv->system->start + (why - solv->systemrules);
2992 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2994 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2997 if (*dp >= solv->system->start && *dp < solv->system->start + solv->system->nsolvables)
2999 if (solv->decisionmap[*dp] > 0)
3001 sd = pool->solvables + *dp;
3008 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));
3012 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));
3020 printf("------------------------------------\n");
3025 printdecisions(solv);
3026 if (solv->suggestions.count)
3028 printf("\nsuggested packages:\n");
3029 for (i = 0; i < solv->suggestions.count; i++)
3031 s = pool->solvables + solv->suggestions.elements[i];
3032 printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));