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;
162 if ((recp = s->recommends) != 0)
163 while ((rec = *recp++) != 0)
164 FOR_PROVIDES(p, pp, rec)
165 MAPSET(&solv->recommendsmap, p);
166 if ((sugp = s->suggests) != 0)
167 while ((sug = *sugp++) != 0)
168 FOR_PROVIDES(p, pp, sug)
169 MAPSET(&solv->suggestsmap, p);
171 /* prune to recommended/supplemented */
172 for (i = j = 0; i < plist->count; i++)
174 p = plist->elements[i];
175 if (MAPTST(&solv->recommendsmap, p))
177 plist->elements[j++] = p;
180 s = pool->solvables + p;
181 if (!s->supplements && !s->freshens)
183 if ((supp = s->supplements) != 0)
185 while ((sup = *supp++) != 0)
186 if (dep_fulfilled(solv, sup))
191 if ((supp = s->freshens) != 0)
193 while ((sup = *supp++) != 0)
194 if (dep_fulfilled(solv, sup))
199 plist->elements[j++] = s - pool->solvables;
204 /* prune to suggested/enhanced*/
205 if (plist->count < 2)
207 for (i = j = 0; i < plist->count; i++)
209 p = plist->elements[i];
210 if (MAPTST(&solv->suggestsmap, p))
212 plist->elements[j++] = p;
215 s = pool->solvables + p;
216 if (!(enhp = s->enhances))
218 while ((enh = *enhp++) != 0)
219 if (dep_fulfilled(solv, enh))
223 plist->elements[j++] = s - pool->solvables;
230 * prune_best_version_arch
232 * sort list of packages (given through plist) by name and evr
233 * return result through plist
237 /* FIXME: must also look at update packages */
240 prune_best_version_arch(Pool *pool, Queue *plist)
247 if (plist->count < 2) /* no need to prune for a single entry */
249 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
251 /* prune to best architecture */
255 for (i = 0; i < plist->count; i++)
257 s = pool->solvables + plist->elements[i];
259 if (a > pool->lastarch)
261 a = pool->id2arch[a];
262 if (!bestscore || (a & 0xffff0000) < bestscore)
263 bestscore = a & 0xffff0000;
265 for (i = j = 0; i < plist->count; i++)
267 s = pool->solvables + plist->elements[i];
269 if (a > pool->lastarch)
271 a = pool->id2arch[a];
272 /* a == 1 -> noarch */
273 if (a != 1 && (a & 0xffff0000) != bestscore)
275 plist->elements[j++] = plist->elements[i];
282 prune_best_version_arch_sortcmp_data = pool;
283 /* sort by name first */
284 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
286 /* now find best 'per name' */
287 for (i = j = 0; i < plist->count; i++)
289 s = pool->solvables + plist->elements[i];
291 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
293 if (!best) /* if no best yet, the current is best */
295 best = plist->elements[i];
299 /* name switch: re-init */
300 if (pool->solvables[best].name != s->name) /* new name */
302 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));
303 plist->elements[j++] = best; /* move old best to front */
304 best = plist->elements[i]; /* take current as new best */
308 if (pool->solvables[best].evr != s->evr) /* compare evr */
310 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
311 best = plist->elements[i];
316 best = plist->elements[0];
318 /* XXX also check obsoletes! */
319 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));
321 plist->elements[j++] = best;
326 /*-----------------------------------------------------------------*/
333 printruleelement(Solver *solv, Rule *r, Id v)
335 Pool *pool = solv->pool;
339 s = pool->solvables + -v;
340 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
344 s = pool->solvables + v;
345 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
354 if (solv->decisionmap[s - pool->solvables] > 0)
355 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
356 if (solv->decisionmap[s - pool->solvables] < 0)
357 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
367 printrule(Solver *solv, Rule *r)
372 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
373 printf("Rule #%d:\n", (int)(r - solv->rules));
375 printf("Rule:\n"); /* r is any rule */
380 else if (r->d == ID_NULL)
387 v = solv->pool->whatprovidesdata[r->d + i - 1];
390 printruleelement(solv, r, v);
392 printf(" next: %d %d\n", r->n1, r->n2);
396 /*-----------------------------------------------------------------*/
402 static Pool *unifyrules_sortcmp_data;
405 * compare rules for unification sort
409 unifyrules_sortcmp(const void *ap, const void *bp)
411 Pool *pool = unifyrules_sortcmp_data;
412 Rule *a = (Rule *)ap;
413 Rule *b = (Rule *)bp;
419 return x; /* p differs */
422 if (a->d == 0 && b->d == 0)
423 return a->w2 - b->w2; /* assertion: return w2 diff */
425 if (a->d == 0) /* a is assertion, b not */
427 x = a->w2 - pool->whatprovidesdata[b->d];
431 if (b->d == 0) /* b is assertion, a not */
433 x = pool->whatprovidesdata[a->d] - b->w2;
437 /* compare whatprovidesdata */
438 ad = pool->whatprovidesdata + a->d;
439 bd = pool->whatprovidesdata + b->d;
441 if ((x = *ad++ - *bd++) != 0)
452 unifyrules(Solver *solv)
457 if (solv->nrules <= 1) /* nothing to unify */
460 /* sort rules first */
461 unifyrules_sortcmp_data = solv->pool;
462 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
469 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
471 if (jr && !unifyrules_sortcmp(ir, jr))
472 continue; /* prune! */
473 jr = solv->rules + j++; /* keep! */
478 /* reduced count from nrules to j rules */
479 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
481 /* adapt rule buffer */
482 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
491 for (i = 1; i < solv->nrules; i++)
494 if (r->d == 0) /* assertion */
499 dp = solv->pool->whatprovidesdata + r->d;
503 if (solv->pool->verbose)
505 printf(" binary: %d\n", binr);
506 printf(" normal: %d\n", solv->nrules - 1 - binr);
507 printf(" normal lits: %d\n", dc);
520 hashrule(Solver *solv, Id p, Id d, int n)
522 unsigned int x = (unsigned int)p;
526 return (x * 37) ^ (unsigned int)d;
527 dp = solv->pool->whatprovidesdata + d;
529 x = (x * 37) ^ (unsigned int)*dp++;
537 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
538 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
541 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
543 * p < 0 : rule from rpm (installed pkg)
544 * d > 0 : Offset in whatprovidesdata (list of providers)
546 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
547 * d < 0: Id of solvable (e.g. B1)
549 * d == 0: unary rule, assertion => (A) or (-A)
551 * Install: p > 0, d = 0 (A) user requested install
552 * Remove: p < 0, d = 0 (-A) user requested remove
553 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
554 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
555 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
556 * ? p > 0, d < 0 (A|-B)
557 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
561 addrule(Solver *solv, Id p, Id d)
566 int n = 0; /* number of literals in rule - 1
567 0 = direct assertion (single literal)
571 /* it often happenes that requires lead to adding the same rpm rule
572 * multiple times, so we prune those duplicates right away to make
573 * the work for unifyrules a bit easier */
575 if (solv->nrules && !solv->jobrules)
577 r = solv->rules + solv->nrules - 1; /* get the last added rule */
578 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
585 return 0; /* ignore self conflict */
588 else if (d == 0) /* user requested */
592 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
594 return 0; /* rule is self-fulfilling */
599 if (n == 0) /* direct assertion */
603 /* this is a rpm rule assertion, we do not have to allocate it */
604 /* it can be identified by a level of 1 and a zero reason */
607 if (solv->decisionmap[-p] > 0 || solv->decisionmap[-p] < -1)
609 if (solv->decisionmap[-p])
611 queuepush(&solv->decisionq, p);
612 queuepush(&solv->decisionq_why, 0);
613 solv->decisionmap[-p] = -1;
617 else if (n == 1 && p > d)
619 /* smallest literal first so we can find dups */
623 n = 1; /* re-set n, was used as temp var */
626 /* check if the last added rule is exactly the same as what we're looking for. */
627 if (r && n == 1 && !r->d && r->p == p && r->w2 == d)
630 if (r && n > 1 && r->d && r->p == p)
635 dp2 = solv->pool->whatprovidesdata + r->d;
636 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
647 /* check and extend rule buffer */
648 if ((solv->nrules & RULES_BLOCK) == 0)
650 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
653 r = solv->rules + solv->nrules++; /* point to rule space */
658 /* direct assertion, no watch needed */
674 r->w2 = solv->pool->whatprovidesdata[d];
682 /* go through system and job rules and add direct assertions
683 * to the decisionqueue. If we find a conflict, disable rules and
684 * add them to problem queue.
687 makeruledecisions(Solver *solv)
693 /* no learnt rules for now */
694 if (solv->learntrules && solv->learntrules != solv->nrules)
697 for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++)
703 if (solv->decisionmap[vv] == 0)
705 queuepush(&solv->decisionq, v);
706 queuepush(&solv->decisionq_why, r - solv->rules);
707 solv->decisionmap[vv] = v > 0 ? 1 : -1;
710 if (v > 0 && solv->decisionmap[vv] > 0)
712 if (v < 0 && solv->decisionmap[vv] < 0)
714 /* found a conflict! */
715 /* if we are weak, just disable ourself */
716 if (ri >= solv->weakrules)
718 printf("conflict, but I am weak, disabling ");
723 for (i = 0; i < solv->decisionq.count; i++)
724 if (solv->decisionq.elements[i] == -v)
726 if (i == solv->decisionq.count)
728 if (solv->decisionq_why.elements[i] == 0)
730 /* conflict with rpm rule, need only disable our rule */
731 printf("conflict with rpm rule, disabling rule #%d\n", ri);
732 queuepush(&solv->problems, r - solv->rules);
733 queuepush(&solv->problems, 0);
734 r->w1 = 0; /* disable */
737 /* conflict with another job or system rule */
738 /* remove old decision */
739 printf("conflicting system/job rules over literal %d\n", vv);
740 solv->decisionmap[vv] = 0;
741 for (; i + 1 < solv->decisionq.count; i++)
743 solv->decisionq.elements[i] = solv->decisionq.elements[i + 1];
744 solv->decisionq_why.elements[i] = solv->decisionq_why.elements[i + 1];
746 solv->decisionq.count--;
747 solv->decisionq_why.count--;
748 /* push all of our rules asserting this literal on the problem stack */
749 for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++)
751 if (!rr->w1 || rr->w2)
753 if (rr->p != v && rr->p != -v)
755 printf(" - disabling rule #%d\n", i);
756 queuepush(&solv->problems, i);
757 rr->w1 = 0; /* disable */
759 queuepush(&solv->problems, 0);
765 * add (install) rules for solvable
770 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
772 Pool *pool = solv->pool;
773 Source *system = solv->system;
786 queueinit_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
787 queuepush(&q, s - pool->solvables); /* push solvable Id */
793 * s: Pointer to solvable
797 if (MAPTST(m, n)) /* continue if already done */
801 s = pool->solvables + n; /* s = Solvable in question */
806 && n >= system->start /* is it installed? */
807 && n < system->start + system->nsolvables)
809 dontfix = 1; /* dont care about broken rpm deps */
812 /*-----------------------------------------
813 * check requires of s
816 if ((reqp = s->requires) != ID_NULL)
818 while ((req = *reqp++) != ID_NULL)
820 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
823 dp = GET_PROVIDESP(req, p); /* get providers of req */
825 if (!*dp /* dont care if noone provides rpmlib() */
826 && !strncmp(id2str(pool, req), "rpmlib(", 7))
831 if (dontfix) /* dont care about breakage */
833 /* the strategy here is to not insist on dependencies
834 * that are already broken. so if we find one provider
835 * that was already installed, we know that the
836 * dependency was not broken before so we enforce it */
837 for (i = 0; dp[i]; i++) /* for all providers */
839 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
840 break; /* provider is installed */
842 if (!dp[i]) /* previously broken dependency */
844 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));
851 /* nothing provides req! */
853 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));
855 addrule(solv, -n, 0); /* mark requestor as uninstallable */
857 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), source_name(s->source));
861 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);
862 for (i = 0; dp[i]; i++)
863 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));
865 /* add 'requires' dependency */
866 /* rule: (-requestor|provider1|provider2|...|providerN) */
867 addrule(solv, -n, dp - pool->whatprovidesdata);
869 /* descend the dependency tree */
870 for (; *dp; dp++) /* loop through all providers */
876 } /* while, requirements of n */
878 } /* if, requirements */
881 /*-----------------------------------------
882 * check conflicts of s
885 if ((conp = s->conflicts) != 0)
887 while ((con = *conp++) != 0)
889 FOR_PROVIDES(p, pp, con)
891 /* dontfix: dont care about conflicts with already installed packs */
892 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
894 /* rule: -n|-p: either solvable _or_ provider of conflict */
895 addrule(solv, -n, -p);
900 /*-----------------------------------------
901 * check obsoletes if not installed
903 if (!system || n < system->start || n >= (system->start + system->nsolvables))
904 { /* not installed */
905 if ((obsp = s->obsoletes) != 0)
907 while ((obs = *obsp++) != 0)
909 FOR_PROVIDES(p, pp, obs)
910 addrule(solv, -n, -p);
913 FOR_PROVIDES(p, pp, s->name)
915 if (s->name == pool->solvables[p].name)
916 addrule(solv, -n, -p);
920 /*-----------------------------------------
921 * add recommends to the rule list
923 if ((recp = s->recommends) != 0)
924 while ((rec = *recp++) != 0)
926 FOR_PROVIDES(p, pp, rec)
935 addrulesforsupplements(Solver *solv, Map *m)
937 Pool *pool = solv->pool;
942 if (pool->verbose) printf("addrulesforsupplements... (%d)\n", solv->nrules);
943 for (i = n = 1; n < pool->nsolvables; i++, n++)
945 if (i == pool->nsolvables)
949 s = pool->solvables + i;
950 if (!pool_installable(pool, s))
953 if ((supp = s->supplements) != 0)
954 while ((sup = *supp++) != ID_NULL)
955 if (dep_possible(solv, sup, m))
957 if (!sup && (supp = s->freshens) != 0)
958 while ((sup = *supp++) != ID_NULL)
959 if (dep_possible(solv, sup, m))
963 addrulesforsolvable(solv, s, m);
966 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
970 addrulesforenhances(Solver *solv, Map *m)
972 Pool *pool = solv->pool;
975 Id p, *pp, enh, *enhp, obs, *obsp, con, *conp;
977 if (pool->verbose) printf("addrulesforenhances... (%d)\n", solv->nrules);
978 for (i = 1; i < pool->nsolvables; i++)
982 s = pool->solvables + i;
983 if ((enhp = s->enhances) == 0)
985 if (!pool_installable(pool, s))
987 while ((enh = *enhp++) != ID_NULL)
988 if (dep_possible(solv, enh, m))
992 if ((conp = s->conflicts) != 0)
993 while ((con = *conp++) != 0)
994 FOR_PROVIDES(p, pp, con)
995 addrule(solv, -i, -p);
996 if ((obsp = s->obsoletes) != 0)
997 while ((obs = *obsp++) != ID_NULL)
998 FOR_PROVIDES(p, pp, obs)
999 addrule(solv, -i, -p);
1000 FOR_PROVIDES(p, pp, s->name)
1001 if (s->name == pool->solvables[p].name)
1002 addrule(solv, -i, -p);
1008 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
1010 Id a1 = s1->arch, a2 = s2->arch;
1012 /* we allow changes to/from noarch */
1013 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
1017 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
1018 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
1019 if (((a1 ^ a2) & 0xffff0000) != 0)
1026 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
1028 /* system packages get a special upgrade allowed rule */
1029 Pool *pool = solv->pool;
1030 Id p, *pp, n, p2, *pp2;
1038 n = s - pool->solvables;
1039 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
1040 addrulesforsolvable(solv, s, m);
1043 * look for updates for s
1045 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
1047 if (p == n) /* skip itself */
1050 if (s->name == pool->solvables[p].name) /* name match */
1052 if (!allowdowngrade /* consider downgrades ? */
1053 && evrcmp(pool, s->evr, pool->solvables[p].evr) > 0)
1056 if (!allowarchchange && archchanges(pool, s, pool->solvables + p))
1059 else if (!solv->noupdateprovide && (obsp = pool->solvables[p].obsoletes) != 0) /* provides/obsoletes combination ? */
1061 while ((obs = *obsp++) != 0) /* for all obsoletes */
1063 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
1065 if (p2 == n) /* match ! */
1068 if (p2) /* match! */
1071 if (!obs) /* continue if no match */
1073 /* here we have 'p' with a matching provides/obsoletes combination
1074 * thus flagging p as a valid update candidate for s
1081 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1082 addrulesforsolvable(solv, pool->solvables + p, m);
1084 if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->system->start])
1086 for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->system->start]; (p = *pp++) != 0;)
1089 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1090 addrulesforsolvable(solv, pool->solvables + p, m);
1096 * add rule for update
1097 * (A|A1|A2|A3...) An = update candidates for A
1099 * s = (installed) solvable
1100 * m = 'addedmap', bit set if 'install' rule for solvable exists
1104 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
1106 /* system packages get a special upgrade allowed rule */
1107 Pool *pool = solv->pool;
1113 queueinit_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1114 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
1115 p = s - pool->solvables;
1116 if (dontaddrule) /* we consider update candidates but dont force them */
1122 if (qs.count == 0) /* no updates found */
1125 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1127 addrule(solv, p, 0); /* request 'install' of s */
1132 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1134 r = addrule(solv, p, d); /* allow update of s */
1136 printf("new update rule ");
1143 /*-----------------------------------------------------------------*/
1150 * initial setup for all watches
1154 makewatches(Solver *solv)
1158 int nsolvables = solv->pool->nsolvables;
1160 xfree(solv->watches);
1161 /* lower half for removals, upper half for installs */
1162 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1164 /* do it reverse so rpm rules get triggered first */
1165 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1167 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1170 if (!r->w1 /* rule is disabled */
1171 || !r->w2) /* rule is assertion */
1174 /* see addwatches(solv, r) */
1175 r->n1 = solv->watches[nsolvables + r->w1];
1176 solv->watches[nsolvables + r->w1] = r - solv->rules;
1178 r->n2 = solv->watches[nsolvables + r->w2];
1179 solv->watches[nsolvables + r->w2] = r - solv->rules;
1185 * add watches (for rule)
1189 addwatches(Solver *solv, Rule *r)
1191 int nsolvables = solv->pool->nsolvables;
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;
1201 /*-----------------------------------------------------------------*/
1202 /* rule propagation */
1204 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1209 * propagate decision to all rules
1213 propagate(Solver *solv, int level)
1215 Pool *pool = solv->pool;
1220 Id *decisionmap = solv->decisionmap;
1221 Id *watches = solv->watches + pool->nsolvables;
1223 while (solv->propagate_index < solv->decisionq.count)
1225 /* negative because our watches trigger if literal goes FALSE */
1226 pkg = -solv->decisionq.elements[solv->propagate_index++];
1228 printf("popagate for decision %d level %d\n", -pkg, level);
1229 printruleelement(solv, 0, -pkg);
1231 for (rp = watches + pkg; *rp; rp = nrp)
1233 r = solv->rules + *rp;
1235 printf(" watch triggered ");
1248 /* if clause is TRUE, nothing to do */
1249 if (DECISIONMAP_TRUE(ow))
1254 /* not a binary clause, check if we need to move our watch */
1255 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1258 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1259 if (p != ow && !DECISIONMAP_TRUE(-p))
1263 /* p is free to watch, move watch to p */
1266 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));
1268 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));
1282 watches[p] = r - solv->rules;
1286 /* unit clause found, set other watch to TRUE */
1287 if (DECISIONMAP_TRUE(-ow))
1288 return r; /* eek, a conflict! */
1294 decisionmap[ow] = level;
1296 decisionmap[-ow] = -level;
1297 queuepush(&solv->decisionq, ow);
1298 queuepush(&solv->decisionq_why, r - solv->rules);
1301 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1303 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1305 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1310 return 0; /* all is well */
1314 /*-----------------------------------------------------------------*/
1323 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1325 Pool *pool = solv->pool;
1328 Map seen; /* global? */
1332 int learnt_why = solv->learnt_pool.count;
1333 Id *decisionmap = solv->decisionmap;
1337 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1338 mapinit(&seen, pool->nsolvables);
1339 idx = solv->decisionq.count;
1343 queuepush(&solv->learnt_pool, c - solv->rules);
1344 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1355 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1357 vv = v > 0 ? v : -v;
1358 if (MAPTST(&seen, vv))
1360 l = solv->decisionmap[vv];
1367 for (j = 0; j < solv->decisionq.count; j++)
1368 if (solv->decisionq.elements[j] == v)
1370 if (j == solv->decisionq.count)
1372 queuepush(&rulq, -(j + 1));
1374 continue; /* initial setting */
1378 num++; /* need to do this one as well */
1383 printf("PUSH %d ", v);
1384 printruleelement(solv, 0, v);
1391 printf("num = %d\n", num);
1397 v = solv->decisionq.elements[--idx];
1398 vv = v > 0 ? v : -v;
1399 if (MAPTST(&seen, vv))
1402 c = solv->rules + solv->decisionq_why.elements[idx];
1410 else if (r.count == 1 && r.elements[0] < 0)
1411 *dr = r.elements[0];
1413 *dr = pool_queuetowhatprovides(pool, &r);
1416 printf("learned rule for level %d (am %d)\n", rlevel, level);
1417 printruleelement(solv, 0, -v);
1418 for (i = 0; i < r.count; i++)
1421 printruleelement(solv, 0, v);
1425 queuepush(&solv->learnt_pool, 0);
1427 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1429 printf("learnt_why ");
1430 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1441 * reset the solver decisions to right after the rpm rules
1445 reset_solver(Solver *solv)
1450 /* delete all learnt rules */
1451 solv->nrules = solv->learntrules;
1452 QUEUEEMPTY(&solv->learnt_why);
1453 QUEUEEMPTY(&solv->learnt_pool);
1455 /* redo all direct rpm rule decisions */
1456 /* we break at the first decision with a why attached, this is
1457 * either a job/system rule decision of a propagated decision */
1458 for (i = 0; i < solv->decisionq.count; i++)
1460 v = solv->decisionq.elements[i];
1461 solv->decisionmap[v > 0 ? v : -v] = 0;
1463 for (i = 0; i < solv->decisionq_why.count; i++)
1464 if (solv->decisionq_why.elements[i])
1468 v = solv->decisionq.elements[i];
1469 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1472 if (solv->pool->verbose)
1473 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1475 solv->decisionq_why.count = i;
1476 solv->decisionq.count = i;
1477 solv->recommends_index = -1;
1478 solv->propagate_index = 0;
1480 /* redo all job/system decisions */
1481 makeruledecisions(solv);
1482 if (solv->pool->verbose)
1483 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1484 /* recreate watches */
1490 * analyze_unsolvable_rule
1494 analyze_unsolvable_rule(Solver *solv, Rule *r)
1497 Id why = r - solv->rules;
1499 if (why >= solv->jobrules && why < solv->systemrules)
1501 if (why >= solv->systemrules && why < solv->weakrules)
1502 printf("SYSTEM %d ", why - solv->systemrules);
1503 if (why >= solv->weakrules && why < solv->learntrules)
1505 if (solv->learntrules && why >= solv->learntrules)
1509 if (solv->learntrules && why >= solv->learntrules)
1511 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1512 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]);
1515 /* do not add rpm rules to problem */
1516 if (why < solv->jobrules)
1518 /* return if problem already countains the rule */
1519 if (solv->problems.count)
1521 for (i = solv->problems.count - 1; i >= 0; i--)
1522 if (solv->problems.elements[i] == 0)
1524 else if (solv->problems.elements[i] == why)
1527 queuepush(&solv->problems, why);
1532 * analyze_unsolvable
1534 * return: 1 - disabled some rules, try again
1539 analyze_unsolvable(Solver *solv, Rule *r, int disablerules)
1541 Pool *pool = solv->pool;
1542 Map seen; /* global? */
1545 Id *decisionmap = solv->decisionmap;
1546 int oldproblemcount;
1550 printf("ANALYZE UNSOLVABLE ----------------------\n");
1552 oldproblemcount = solv->problems.count;
1553 mapinit(&seen, pool->nsolvables);
1554 analyze_unsolvable_rule(solv, r);
1555 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1566 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1568 vv = v > 0 ? v : -v;
1569 l = solv->decisionmap[vv];
1574 idx = solv->decisionq.count;
1577 v = solv->decisionq.elements[--idx];
1578 vv = v > 0 ? v : -v;
1579 if (!MAPTST(&seen, vv))
1581 why = solv->decisionq_why.elements[idx];
1586 printruleelement(solv, 0, v);
1590 r = solv->rules + why;
1591 analyze_unsolvable_rule(solv, r);
1592 dp = r->d ? pool->whatprovidesdata + r->d : 0;
1603 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1605 vv = v > 0 ? v : -v;
1606 l = solv->decisionmap[vv];
1613 queuepush(&solv->problems, 0); /* mark end of this problem */
1616 if (solv->weakrules != solv->learntrules)
1618 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1620 why = solv->problems.elements[i];
1621 if (why < solv->weakrules || why >= solv->learntrules)
1623 if (!lastweak || lastweak < why)
1629 /* disable last weak rule */
1630 solv->problems.count = oldproblemcount;
1631 r = solv->rules + lastweak;
1632 printf("disabling weak ");
1638 else if (disablerules)
1640 for (i = oldproblemcount; i < solv->problems.count - 1; i++)
1642 r = solv->rules + solv->problems.elements[i];
1652 /*-----------------------------------------------------------------*/
1653 /* Decision revert */
1657 * revert decision at level
1661 revert(Solver *solv, int level)
1664 while (solv->decisionq.count)
1666 v = solv->decisionq.elements[solv->decisionq.count - 1];
1667 vv = v > 0 ? v : -v;
1668 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1671 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1673 solv->decisionmap[vv] = 0;
1674 solv->decisionq.count--;
1675 solv->decisionq_why.count--;
1676 solv->propagate_index = solv->decisionq.count;
1678 solv->recommends_index = -1;
1683 * watch2onhighest - put watch2 on literal with highest level
1687 watch2onhighest(Solver *solv, Rule *r)
1693 return; /* binary rule, both watches are set */
1694 dp = solv->pool->whatprovidesdata + r->d;
1695 while ((v = *dp++) != 0)
1697 l = solv->decisionmap[v < 0 ? -v : v];
1714 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1724 solv->decisionmap[decision] = level;
1726 solv->decisionmap[-decision] = -level;
1727 queuepush(&solv->decisionq, decision);
1728 queuepush(&solv->decisionq_why, 0);
1732 r = propagate(solv, level);
1736 return analyze_unsolvable(solv, r, disablerules);
1737 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1738 l = analyze(solv, level, r, &p, &d, &why);
1739 if (l >= level || l <= 0)
1741 printf("reverting decisions (level %d -> %d)\n", level, l);
1743 revert(solv, level);
1744 r = addrule(solv, p, d); /* p requires d */
1747 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1749 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1752 queuepush(&solv->learnt_why, why);
1755 /* at least 2 literals, needs watches */
1756 watch2onhighest(solv, r);
1757 addwatches(solv, r);
1759 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1760 queuepush(&solv->decisionq, p);
1761 queuepush(&solv->decisionq_why, r - solv->rules);
1762 printf("decision: ");
1763 printruleelement(solv, 0, p);
1764 printf("new rule: ");
1770 /*-----------------------------------------------------------------*/
1771 /* Main solver interface */
1776 * create solver structure
1778 * pool: all available solvables
1779 * system: installed Solvables
1782 * Upon solving, rules are created to flag the Solvables
1783 * of the 'system' Source as installed.
1787 solver_create(Pool *pool, Source *system)
1790 solv = (Solver *)xcalloc(1, sizeof(Solver));
1792 solv->system = system;
1795 queueinit(&solv->decisionq);
1796 queueinit(&solv->decisionq_why);
1797 queueinit(&solv->problems);
1798 queueinit(&solv->suggestions);
1799 queueinit(&solv->learnt_why);
1800 queueinit(&solv->learnt_pool);
1802 mapinit(&solv->recommendsmap, pool->nsolvables);
1803 mapinit(&solv->suggestsmap, pool->nsolvables);
1804 solv->recommends_index = 0;
1806 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1807 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1808 memset(solv->rules, 0, sizeof(Rule));
1820 solver_free(Solver *solv)
1822 queuefree(&solv->decisionq);
1823 queuefree(&solv->decisionq_why);
1824 queuefree(&solv->learnt_why);
1825 queuefree(&solv->learnt_pool);
1826 queuefree(&solv->problems);
1827 queuefree(&solv->suggestions);
1829 mapfree(&solv->recommendsmap);
1830 mapfree(&solv->suggestsmap);
1831 xfree(solv->decisionmap);
1833 xfree(solv->watches);
1834 xfree(solv->weaksystemrules);
1835 xfree(solv->obsoletes);
1836 xfree(solv->obsoletes_data);
1841 /*-------------------------------------------------------*/
1846 * all rules have been set up, not actually run the solver
1851 run_solver(Solver *solv, int disablerules, int doweak)
1859 Pool *pool = solv->pool;
1863 printf("number of rules: %d\n", solv->nrules);
1866 for (i = 0; i < solv->nrules; i++)
1868 printrule(solv, solv->rules + i);
1873 /* all new rules are learnt after this point */
1874 solv->learntrules = solv->nrules;
1875 /* crate watches lists */
1878 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1880 /* start SAT algorithm */
1882 systemlevel = level + 1;
1883 if (pool->verbose) printf("solving...\n");
1894 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1895 if ((r = propagate(solv, level)) != 0)
1897 if (analyze_unsolvable(solv, r, disablerules))
1899 printf("UNSOLVABLE\n");
1909 if (level < systemlevel && solv->system->nsolvables)
1911 if (!solv->updatesystem)
1913 /* try to keep as many packages as possible */
1914 if (pool->verbose) printf("installing system packages\n");
1915 for (i = solv->system->start, n = 0; ; i++, n++)
1917 if (n == solv->system->nsolvables)
1919 if (i == solv->system->start + solv->system->nsolvables)
1920 i = solv->system->start;
1921 s = pool->solvables + i;
1922 if (solv->decisionmap[i] != 0)
1925 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1928 level = setpropagatelearn(solv, level, i, disablerules);
1931 printf("UNSOLVABLE\n");
1935 if (level <= olevel)
1939 if (solv->weaksystemrules)
1941 if (pool->verbose) printf("installing weak system packages\n");
1942 for (i = solv->system->start, n = 0; ; i++, n++)
1944 if (n == solv->system->nsolvables)
1946 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->system->start] == 0))
1949 if (solv->decisionmap[i] == 0)
1951 if (solv->weaksystemrules[i - solv->system->start])
1953 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1954 while ((p = *dp++) != 0)
1956 if (solv->decisionmap[p] > 0)
1958 if (solv->decisionmap[p] == 0)
1962 continue; /* rule is already true */
1968 prune_to_recommended(solv, &dq);
1970 prune_best_version_arch(pool, &dq);
1972 s = pool->solvables + dq.elements[0];
1973 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1976 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
1979 printf("UNSOLVABLE\n");
1983 if (level <= olevel)
1989 if (n != solv->system->nsolvables)
1992 systemlevel = level;
1999 if (pool->verbose) printf("deciding unresolved rules\n");
2000 for (i = 1, n = 1; ; i++, n++)
2002 if (n == solv->nrules)
2004 if (i == solv->nrules)
2006 r = solv->rules + i;
2012 /* binary or unary rule */
2013 /* need two positive undecided literals */
2014 if (r->p < 0 || r->w2 <= 0)
2016 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
2018 queuepush(&dq, r->p);
2019 queuepush(&dq, r->w2);
2024 * all negative literals are installed
2025 * no positive literal is installed
2026 * i.e. the rule is not fulfilled and we
2027 * just need to decide on the positive literals
2031 if (solv->decisionmap[-r->p] <= 0)
2036 if (solv->decisionmap[r->p] > 0)
2038 if (solv->decisionmap[r->p] == 0)
2039 queuepush(&dq, r->p);
2041 dp = pool->whatprovidesdata + r->d;
2042 while ((p = *dp++) != 0)
2046 if (solv->decisionmap[-p] <= 0)
2051 if (solv->decisionmap[p] > 0)
2053 if (solv->decisionmap[p] == 0)
2062 /* cannot happen as this means that
2063 * the rule is unit */
2067 prune_to_recommended(solv, &dq);
2069 prune_best_version_arch(pool, &dq);
2070 p = dq.elements[dq.count - 1];
2071 s = pool->solvables + p;
2073 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2076 level = setpropagatelearn(solv, level, p, disablerules);
2079 printf("UNSOLVABLE\n");
2083 if (level < systemlevel)
2086 } /* for(), decide */
2088 if (n != solv->nrules) /* continue if level < systemlevel */
2091 if (doweak && !solv->problems.count)
2095 if (pool->verbose) printf("installing recommended packages\n");
2097 for (i = 1; i < pool->nsolvables; i++)
2099 if (solv->decisionmap[i] < 0)
2101 if (solv->decisionmap[i] > 0)
2103 Id *recp, rec, *pp, p;
2104 s = pool->solvables + i;
2105 /* installed, check for recommends */
2106 /* XXX need to special case AND ? */
2107 if ((recp = s->recommends) != 0)
2109 while ((rec = *recp++) != 0)
2112 FOR_PROVIDES(p, pp, rec)
2114 if (solv->decisionmap[p] > 0)
2119 else if (solv->decisionmap[p] == 0)
2120 queuepushunique(&dq, p);
2128 s = pool->solvables + i;
2129 if (!s->supplements && !s->freshens)
2131 if (!pool_installable(pool, s))
2133 if ((supp = s->supplements) != 0)
2135 while ((sup = *supp++) != 0)
2136 if (dep_fulfilled(solv, sup))
2141 if ((supp = s->freshens) != 0)
2143 while ((sup = *supp++) != 0)
2144 if (dep_fulfilled(solv, sup))
2149 queuepushunique(&dq, i);
2154 prune_best_version_arch(pool, &dq);
2155 p = dq.elements[dq.count - 1];
2156 s = pool->solvables + p;
2158 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2160 level = setpropagatelearn(solv, level, p, 0);
2175 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2183 printf("refine_suggestion start\n");
2184 queueinit(&disabled);
2185 QUEUEEMPTY(refined);
2186 queuepush(refined, sug);
2188 /* re-enable all rules but rule "sug" of the problem */
2194 r = solv->rules + sug;
2198 for (i = 0; problem[i]; i++)
2200 if (problem[i] == sug)
2205 r = solv->rules + problem[i];
2212 /* direct assertion */
2213 if (r->p == sugassert && sugseen)
2215 /* also leave this assertion disabled */
2218 v = r->p > 0 ? r->p : -r->p;
2219 if (solv->decisionmap[v])
2221 if ((solv->decisionmap[v] > 0 && r->p < 0) ||
2222 (solv->decisionmap[v] < 0 && r->p > 0))
2224 printf("direct assertion failure, no solution found!\n");
2227 r = solv->rules + problem[i];
2234 if (r->d == 0 || r->w2 != r->p)
2237 r->w1 = solv->pool->whatprovidesdata[r->d];
2241 /* re-enable as many weak rules as possible */
2242 for (i = solv->weakrules; i < solv->learntrules; i++)
2244 r = solv->rules + i;
2247 if (r->d == 0 || r->w2 != r->p)
2250 r->w1 = solv->pool->whatprovidesdata[r->d];
2253 QUEUEEMPTY(&solv->problems);
2254 revert(solv, 1); /* XXX move to reset_solver? */
2256 run_solver(solv, 0, 0);
2257 if (!solv->problems.count)
2259 printf("no more problems!\n");
2261 printdecisions(solv);
2263 break; /* great, no more problems */
2265 disabledcnt = disabled.count;
2266 for (i = 0; i < solv->problems.elements[i]; i++)
2268 /* ignore solutions in refined */
2269 v = solv->problems.elements[i];
2270 for (j = 0; problem[j]; j++)
2271 if (problem[j] != sug && problem[j] == v)
2275 queuepush(&disabled, v);
2276 queuepush(&disabled, 0); /* room for watch */
2278 if (disabled.count == disabledcnt)
2280 /* no solution found, this was an invalid suggestion! */
2281 printf("no solution found!\n");
2285 if (disabled.count == disabledcnt + 2)
2287 /* just one suggestion, add it to refined list */
2288 queuepush(refined, disabled.elements[disabledcnt]);
2292 printf("############################################## more than one solution found.\n");
2294 for (i = 0; i < solv->problems.elements[i]; i++)
2295 printrule(solv, solv->rules + solv->problems.elements[i]);
2296 printf("##############################################\n");
2298 /* more than one solution, keep all disabled */
2300 for (i = disabledcnt; i < disabled.count; i += 2)
2303 r = solv->rules + disabled.elements[i];
2304 disabled.elements[i + 1] = r->w1;
2312 /* enable refined rules again */
2313 for (i = 0; i < disabled.count; i += 2)
2315 r = solv->rules + disabled.elements[i];
2316 r->w1 = disabled.elements[i + 1];
2318 /* disable problem rules again so that we are in the same state as before */
2319 for (i = 0; problem[i]; i++)
2321 r = solv->rules + problem[i];
2324 printf("refine_suggestion end\n");
2333 id2rc(Solver *solv, Id id)
2336 if (solv->rc_output != 2)
2338 evr = id2str(solv->pool, id);
2339 if (*evr < '0' || *evr > '9')
2341 while (*evr >= '0' && *evr <= '9')
2349 printdecisions(Solver *solv)
2351 Pool *pool = solv->pool;
2352 Id p, *obsoletesmap;
2356 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2357 for (i = 0; i < solv->decisionq.count; i++)
2362 n = solv->decisionq.elements[i];
2365 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2367 s = pool->solvables + n;
2368 if ((obsp = s->obsoletes) != 0)
2369 while ((obs = *obsp++) != 0)
2370 FOR_PROVIDES(p, pp, obs)
2372 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2374 obsoletesmap[p] = n;
2378 FOR_PROVIDES(p, pp, s->name)
2379 if (s->name == pool->solvables[p].name)
2381 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2383 obsoletesmap[p] = n;
2389 if (solv->rc_output)
2390 printf(">!> Solution #1:\n");
2392 int installs = 0, uninstalls = 0, upgrades = 0;
2394 /* print solvables to be erased */
2396 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2398 if (solv->decisionmap[i] > 0)
2400 if (obsoletesmap[i])
2402 s = pool->solvables + i;
2403 if (solv->rc_output == 2)
2404 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2405 else if (solv->rc_output)
2406 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2408 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2412 /* print solvables to be installed */
2414 for (i = 0; i < solv->decisionq.count; i++)
2417 p = solv->decisionq.elements[i];
2420 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2422 s = pool->solvables + p;
2424 if (!obsoletesmap[p])
2426 if (solv->rc_output)
2428 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2429 if (solv->rc_output != 2)
2430 printf(".%s", id2str(pool, s->arch));
2433 else if (!solv->rc_output)
2435 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2436 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2438 if (obsoletesmap[j] != p)
2440 s = pool->solvables + j;
2441 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2448 Solvable *f, *fn = 0;
2449 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2451 if (obsoletesmap[j] != p)
2453 f = pool->solvables + j;
2454 if (fn || f->name != s->name)
2456 if (solv->rc_output == 2)
2457 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2458 else if (solv->rc_output)
2459 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2467 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2468 if (solv->rc_output != 2)
2469 printf(".%s", id2str(pool, s->arch));
2474 if (solv->rc_output == 2)
2475 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));
2477 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));
2481 if (solv->rc_output)
2483 Source *source = s->source;
2484 if (source && strcmp(source_name(source), "locales"))
2485 printf("[%s]", source_name(source));
2490 if (solv->rc_output)
2491 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2493 xfree(obsoletesmap);
2497 create_obsolete_index(Solver *solv)
2499 Pool *pool = solv->pool;
2501 Source *system = solv->system;
2502 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
2505 /* create reverse obsoletes map for system solvables */
2506 solv->obsoletes = obsoletes = xcalloc(system->nsolvables, sizeof(Id));
2507 for (i = 1; i < pool->nsolvables; i++)
2509 s = pool->solvables + i;
2510 if ((obsp = s->obsoletes) == 0)
2512 if (!pool_installable(pool, s))
2514 while ((obs = *obsp++) != 0)
2515 FOR_PROVIDES(p, pp, obs)
2517 if (p < system->start || p >= system->start + system->nsolvables)
2519 if (pool->solvables[p].name == s->name)
2521 obsoletes[p - system->start]++;
2525 for (i = 0; i < system->nsolvables; i++)
2528 n += obsoletes[i] + 1;
2531 solv->obsoletes_data = obsoletes_data = xcalloc(n + 1, sizeof(Id));
2532 if (pool->verbose) printf("obsoletes data: %d entries\n", n + 1);
2533 for (i = pool->nsolvables - 1; i > 0; i--)
2535 s = pool->solvables + i;
2536 if ((obsp = s->obsoletes) == 0)
2538 if (!pool_installable(pool, s))
2540 while ((obs = *obsp++) != 0)
2541 FOR_PROVIDES(p, pp, obs)
2543 if (p < system->start || p >= system->start + system->nsolvables)
2545 if (pool->solvables[p].name == s->name)
2548 if (obsoletes_data[obsoletes[p]] != i)
2549 obsoletes_data[--obsoletes[p]] = i;
2554 /*-----------------------------------------------------------------*/
2564 solve(Solver *solv, Queue *job)
2566 Pool *pool = solv->pool;
2568 Map addedmap; /* '1' == have rule for solvable */
2569 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2570 Id how, what, p, *pp, d;
2576 * create basic rule set of all involved packages
2581 mapinit(&addedmap, pool->nsolvables);
2582 mapinit(&noupdaterule, pool->nsolvables);
2587 * create rules for installed solvables -> keep them installed
2588 * so called: rpm rules
2592 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2593 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2596 * create install rules
2598 * two passes, as we want to keep the rpm rules distinct from the job rules
2602 if (solv->noupdateprovide && solv->system->nsolvables)
2603 create_obsolete_index(solv);
2607 * process job rules for solvables
2610 for (i = 0; i < job->count; i += 2)
2612 how = job->elements[i];
2613 what = job->elements[i + 1];
2617 case SOLVER_INSTALL_SOLVABLE:
2618 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2620 case SOLVER_INSTALL_SOLVABLE_NAME:
2621 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2623 FOR_PROVIDES(p, pp, what)
2625 /* if by name, ensure that the name matches */
2626 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2628 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2631 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2632 /* dont allow downgrade */
2633 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2639 * if unstalls are disallowed, add update rules for every
2640 * installed solvables in the hope to circumvent uninstall
2646 if (!solv->allowuninstall)
2648 /* add update rule for every installed package */
2649 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2650 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2652 #else /* this is just to add the needed rpm rules to our set */
2653 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2654 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2657 addrulesforsupplements(solv, &addedmap);
2658 addrulesforenhances(solv, &addedmap); /* do this last */
2662 int possible = 0, installable = 0;
2663 for (i = 1; i < pool->nsolvables; i++)
2665 if (pool_installable(pool, pool->solvables + i))
2667 if (MAPTST(&addedmap, i))
2670 printf("%d of %d installable solvables used for solving\n", possible, installable);
2677 * unify existing rules before going over all job rules
2681 unifyrules(solv); /* remove duplicate rpm rules */
2684 * at this point the system is always solvable,
2685 * as an empty system (remove all packages) is a valid solution
2687 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2690 * now add all job rules
2693 solv->jobrules = solv->nrules;
2695 for (i = 0; i < job->count; i += 2)
2697 how = job->elements[i];
2698 what = job->elements[i + 1];
2701 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2702 if (solv->rc_output) {
2703 Solvable *s = pool->solvables + what;
2704 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(s->source));
2706 addrule(solv, what, 0); /* install by Id */
2708 case SOLVER_ERASE_SOLVABLE:
2709 addrule(solv, -what, 0); /* remove by Id */
2710 MAPSET(&noupdaterule, what);
2712 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2713 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2715 FOR_PROVIDES(p, pp, what) /* check all providers */
2717 /* if by name, ensure that the name matches */
2718 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2722 if (!q.count) { /* no provider found -> abort */
2723 fprintf(stderr, "Nothing provides '%s'\n", id2str(pool, what));
2724 /* XXX make this a problem! */
2729 p = queueshift(&q); /* get first provider */
2731 d = 0; /* single provider ? -> make assertion */
2733 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2734 addrule(solv, p, d); /* add 'requires' rule */
2736 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2737 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2738 FOR_PROVIDES(p, pp, what)
2740 /* if by name, ensure that the name matches */
2741 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2744 addrule(solv, -p, 0); /* add 'remove' rule */
2745 MAPSET(&noupdaterule, p);
2748 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2749 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2754 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2757 * now add policy rules
2761 solv->systemrules = solv->nrules;
2764 * create rules for updating installed solvables
2770 if (!solv->allowuninstall)
2771 { /* loop over all installed solvables */
2772 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2774 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2775 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2777 addrule(solv, 0, 0); /* place holder */
2779 /* consistency check: we added a rule for _every_ system solvable */
2780 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2784 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2786 /* create special weak system rules */
2787 if (solv->system->nsolvables)
2789 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2790 for (i = 0; i < solv->system->nsolvables; i++)
2792 if (MAPTST(&noupdaterule, solv->system->start + i))
2794 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2796 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2800 /* free unneeded memory */
2802 mapfree(&noupdaterule);
2805 solv->weakrules = solv->nrules;
2807 /* try real hard to keep packages installed */
2810 for (i = 0; i < solv->system->nsolvables; i++)
2812 d = solv->weaksystemrules[i];
2813 addrule(solv, solv->system->start + i, d);
2822 makeruledecisions(solv);
2823 run_solver(solv, 1, 1);
2825 /* find suggested packages */
2826 if (!solv->problems.count)
2828 Id sug, *sugp, enh, *enhp, req, *reqp, p, *pp;
2830 /* create map of all suggests that are still open */
2831 solv->recommends_index = -1;
2832 MAPZERO(&solv->suggestsmap);
2833 for (i = 0; i < solv->decisionq.count; i++)
2835 p = solv->decisionq.elements[i];
2838 s = pool->solvables + p;
2839 if ((sugp = s->suggests) != 0)
2840 while ((sug = *sugp++) != 0)
2842 FOR_PROVIDES(p, pp, sug)
2843 if (solv->decisionmap[p] > 0)
2846 continue; /* already fulfilled */
2847 FOR_PROVIDES(p, pp, sug)
2848 MAPSET(&solv->suggestsmap, p);
2851 for (i = 1; i < pool->nsolvables; i++)
2853 if (solv->decisionmap[i] != 0)
2855 s = pool->solvables + i;
2856 if (!MAPTST(&solv->suggestsmap, i))
2858 if ((enhp = s->enhances) == 0)
2860 if (!pool_installable(pool, s))
2862 while ((enh = *enhp++) != 0)
2863 if (dep_fulfilled(solv, enh))
2868 /* check if installation is possible at all */
2869 if ((reqp = s->requires) != 0)
2871 while ((req = *reqp++) != 0)
2873 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
2875 FOR_PROVIDES(p, pp, req)
2876 if (solv->decisionmap[p] >= 0)
2878 if (!p && !strncmp(id2str(pool, req), "rpmlib(", 7))
2881 break; /* no provider installable! */
2886 queuepush(&solv->suggestions, i);
2888 prune_best_version_arch(pool, &solv->suggestions);
2893 * print solver result
2897 if (pool->verbose) printf("-------------------------------------------------------------\n");
2899 if (solv->problems.count)
2909 clonequeue(&problems, &solv->problems);
2910 queueinit(&solution);
2911 printf("Encountered problems! Here are the solutions:\n");
2912 problem = problems.elements;
2913 for (i = 0; i < problems.count; i++)
2915 Id v = problems.elements[i];
2918 printf("====================================\n");
2919 problem = problems.elements + i + 1;
2922 refine_suggestion(solv, problem, v, &solution);
2923 for (j = 0; j < solution.count; j++)
2925 r = solv->rules + solution.elements[j];
2926 why = solution.elements[j];
2930 if (why >= solv->jobrules && why < solv->systemrules)
2932 /* do a sloppy job of analyzing the job rule */
2935 s = pool->solvables + r->p;
2936 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2940 s = pool->solvables - r->p;
2941 printf("- do not erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2944 else if (why >= solv->systemrules && why < solv->weakrules)
2947 s = pool->solvables + solv->system->start + (why - solv->systemrules);
2948 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2950 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2953 if (*dp >= solv->system->start && *dp < solv->system->start + solv->system->nsolvables)
2955 if (solv->decisionmap[*dp] > 0)
2957 sd = pool->solvables + *dp;
2964 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));
2968 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));
2976 printf("------------------------------------\n");
2981 printdecisions(solv);
2982 if (solv->suggestions.count)
2984 printf("\nsuggested packages:\n");
2985 for (i = 0; i < solv->suggestions.count; i++)
2987 s = pool->solvables + solv->suggestions.elements[i];
2988 printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));