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 * prune_to_recommended
115 prune_to_recommended(Solver *solv, Queue *plist)
117 Pool *pool = solv->pool;
120 Id p, *pp, sup, *supp, rec, *recp;
122 if (solv->recommends_index < 0)
124 MAPZERO(&solv->recommends);
125 solv->recommends_index = 0;
127 while (solv->recommends_index < solv->decisionq.count)
129 p = solv->decisionq.elements[solv->recommends_index++];
132 s = pool->solvables + p;
133 if (!(recp = s->recommends))
135 while ((rec = *recp++) != 0)
136 FOR_PROVIDES(p, pp, rec)
137 MAPSET(&solv->recommends, p);
139 for (i = j = 0; i < plist->count; i++)
141 p = plist->elements[i];
142 if (MAPTST(&solv->recommends, p))
144 plist->elements[j++] = p;
147 s = pool->solvables + p;
148 if (!s->supplements && !s->freshens)
150 if ((supp = s->supplements) != 0)
152 while ((sup = *supp++) != 0)
153 if (dep_fulfilled(solv, sup))
158 if ((supp = s->freshens) != 0)
160 while ((sup = *supp++) != 0)
161 if (dep_fulfilled(solv, sup))
166 plist->elements[j++] = s - pool->solvables;
173 * prune_best_version_arch
175 * sort list of packages (given through plist) by name and evr
176 * return result through plist
180 /* FIXME: must also look at update packages */
183 prune_best_version_arch(Pool *pool, Queue *plist)
190 if (plist->count < 2) /* no need to prune for a single entry */
192 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
194 /* prune to best architecture */
198 for (i = 0; i < plist->count; i++)
200 s = pool->solvables + plist->elements[i];
202 if (a > pool->lastarch)
204 a = pool->id2arch[a];
205 if (!bestscore || (a & 0xffff0000) < bestscore)
206 bestscore = a & 0xffff0000;
208 for (i = j = 0; i < plist->count; i++)
210 s = pool->solvables + plist->elements[i];
212 if (a > pool->lastarch)
214 a = pool->id2arch[a];
215 /* a == 1 -> noarch */
216 if (a != 1 && (a & 0xffff0000) != bestscore)
218 plist->elements[j++] = plist->elements[i];
225 prune_best_version_arch_sortcmp_data = pool;
226 /* sort by name first */
227 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
229 /* now find best 'per name' */
230 for (i = j = 0; i < plist->count; i++)
232 s = pool->solvables + plist->elements[i];
233 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
236 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
238 if (!best) /* if no best yet, the current is best */
240 best = plist->elements[i];
244 /* name switch: re-init */
245 if (pool->solvables[best].name != s->name) /* new name */
247 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));
248 plist->elements[j++] = best; /* move old best to front */
249 best = plist->elements[i]; /* take current as new best */
253 if (pool->solvables[best].evr != s->evr) /* compare evr */
255 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
256 best = plist->elements[i];
261 best = plist->elements[0];
263 /* XXX also check obsoletes! */
264 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));
266 plist->elements[j++] = best;
271 /*-----------------------------------------------------------------*/
278 printruleelement(Solver *solv, Rule *r, Id v)
280 Pool *pool = solv->pool;
284 s = pool->solvables + -v;
285 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
289 s = pool->solvables + v;
290 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
299 if (solv->decisionmap[s - pool->solvables] > 0)
300 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
301 if (solv->decisionmap[s - pool->solvables] < 0)
302 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
312 printrule(Solver *solv, Rule *r)
317 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
318 printf("Rule #%d:\n", (int)(r - solv->rules));
320 printf("Rule:\n"); /* r is any rule */
325 else if (r->d == ID_NULL)
332 v = solv->pool->whatprovidesdata[r->d + i - 1];
335 printruleelement(solv, r, v);
337 printf(" next: %d %d\n", r->n1, r->n2);
341 /*-----------------------------------------------------------------*/
347 static Pool *unifyrules_sortcmp_data;
350 * compare rules for unification sort
354 unifyrules_sortcmp(const void *ap, const void *bp)
356 Pool *pool = unifyrules_sortcmp_data;
357 Rule *a = (Rule *)ap;
358 Rule *b = (Rule *)bp;
364 return x; /* p differs */
367 if (a->d == 0 && b->d == 0)
368 return a->w2 - b->w2; /* assertion: return w2 diff */
370 if (a->d == 0) /* a is assertion, b not */
372 x = a->w2 - pool->whatprovidesdata[b->d];
376 if (b->d == 0) /* b is assertion, a not */
378 x = pool->whatprovidesdata[a->d] - b->w2;
382 /* compare whatprovidesdata */
383 ad = pool->whatprovidesdata + a->d;
384 bd = pool->whatprovidesdata + b->d;
385 for (; *ad && *ad == *bd; ad++, bd++)
396 unifyrules(Solver *solv)
401 if (solv->nrules <= 1) /* nothing to unify */
404 /* sort rules first */
405 unifyrules_sortcmp_data = solv->pool;
406 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
413 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
415 if (jr && !unifyrules_sortcmp(ir, jr))
416 continue; /* prune! */
417 jr = solv->rules + j++; /* keep! */
422 /* reduced count from nrules to j rules */
423 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
425 /* adapt rule buffer */
426 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
435 for (i = 1; i < solv->nrules; i++)
438 if (r->d == 0) /* assertion */
443 dp = solv->pool->whatprovidesdata + r->d;
447 if (solv->pool->verbose)
449 printf(" binary: %d\n", binr);
450 printf(" normal: %d\n", solv->nrules - 1 - binr);
451 printf(" normal lits: %d\n", dc);
464 hashrule(Solver *solv, Id p, Id d, int n)
466 unsigned int x = (unsigned int)p;
470 return (x * 37) ^ (unsigned int)d;
471 dp = solv->pool->whatprovidesdata + d;
473 x = (x * 37) ^ (unsigned int)*dp++;
481 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
482 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
485 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
487 * p < 0 : rule from rpm (installed pkg)
488 * d > 0 : Offset in whatprovidesdata (list of providers)
490 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
491 * d < 0: Id of solvable (e.g. B1)
493 * d == 0: unary rule, assertion => (A) or (-A)
495 * Install: p > 0, d = 0 (A) user requested install
496 * Remove: p < 0, d = 0 (-A) user requested remove
497 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
498 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
499 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
500 * ? p > 0, d < 0 (A|-B)
501 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
505 addrule(Solver *solv, Id p, Id d)
510 int n = 0; /* number of literals in rule - 1
511 0 = direct assertion (single literal)
515 /* it often happenes that requires lead to adding the same rpm rule
516 * multiple times, so we prune those duplicates right away to make
517 * the work for unifyrules a bit easier */
519 if (solv->nrules && !solv->jobrules)
521 r = solv->rules + solv->nrules - 1; /* get the last added rule */
522 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
529 return NULL; /* ignore self conflict */
532 else if (d == 0) /* user requested */
536 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
538 return NULL; /* rule is self-fulfilling */
543 if (n == 0) /* direct assertion */
547 /* this is a rpm rule assertion, we do not have to allocate it */
548 /* we can identify it by looking at the decision level, it will be 1 */
551 if (solv->decisionmap[-p] > 0) /* */
553 if (solv->decisionmap[-p]) /* */
555 queuepush(&solv->decisionq, p);
556 queuepush(&solv->decisionq_why, 0);
557 solv->decisionmap[-p] = -1;
562 else if (n == 1 && p > d)
564 /* smallest literal first so we can find dups */
568 n = 1; /* re-set n, was used as temp var */
584 Id *dp2 = solv->pool->whatprovidesdata + r->d;
585 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
598 /* check and extend rule buffer */
599 if ((solv->nrules & RULES_BLOCK) == 0)
601 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
604 r = solv->rules + solv->nrules++; /* point to rule space */
609 /* direct assertion, no watch needed */
625 r->w2 = solv->pool->whatprovidesdata[d];
630 /* we don't add the decision for learnt rules, as the code does that
631 * right after calling addrule anyway */
634 && !solv->learntrules)
636 /* must be system or job rule, as there are only negative unary rpm rules */
637 Id vv = p > 0 ? p : -p;
638 if (solv->decisionmap[vv])
641 if (solv->decisionmap[vv] > 0 && p > 0)
643 if (solv->decisionmap[vv] < 0 && p < 0)
645 /* direct conflict! */
646 for (i = 0; i < solv->decisionq.count; i++)
647 if (solv->decisionq.elements[i] == -p)
649 if (i == solv->decisionq.count)
651 if (solv->decisionq_why.elements[i] == 0)
653 /* conflict with rpm rule */
654 queuepush(&solv->problems, r - solv->rules);
655 queuepush(&solv->problems, 0);
656 r->w1 = 0; /* disable */
659 /* conflict with other job or system rule */
660 queuepush(&solv->problems, solv->decisionq_why.elements[i]);
661 queuepush(&solv->problems, r - solv->rules);
662 queuepush(&solv->problems, 0);
663 r->w1 = 0; /* disable */
664 /* also disable conflicting rule */
665 solv->rules[solv->decisionq_why.elements[i]].w1 = 0;
666 /* XXX: remove from decisionq! */
667 printf("XXX remove from decisionq\n");
670 queuepush(&solv->decisionq, p);
671 queuepush(&solv->decisionq_why, r - solv->rules);
672 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? 1 : -1;
679 * add (install) rules for solvable
684 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
686 Pool *pool = solv->pool;
687 Source *system = solv->system;
700 queueinit_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
701 queuepush(&q, s - pool->solvables); /* push solvable Id */
707 * s: Pointer to solvable
711 if (MAPTST(m, n)) /* continue if already set in map */
715 s = pool->solvables + n; /* s = Solvable in question */
718 if (system /* have rpm */
720 && n >= system->start /* its an rpm rule */
721 && n < system->start + system->nsolvables)
723 dontfix = 1; /* dont care about broken rpm deps */
726 /*-----------------------------------------
727 * check requires of s
730 if ((reqp = s->requires) != ID_NULL)
732 while ((req = *reqp++) != ID_NULL)
734 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
737 dp = GET_PROVIDESP(req, p); /* get providers of req */
739 if (!*dp /* dont care if noone provides rpmlib() */
740 && !strncmp(id2str(pool, req), "rpmlib(", 7))
745 if (dontfix) /* rpm rule, dont care about breakage */
747 for (i = 0; dp[i]; i++)/* for all providers */
749 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
750 break; /* provider is installed */
752 if (!dp[i]) /* no provider found */
754 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));
761 /* nothing provides req! */
763 if (pool->verbose) printf("package %s-%s.%s is not installable (%s)\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), dep2str(pool, req));
765 addrule(solv, -n, 0); /* mark requestor as uninstallable */
767 printf(">!> !unflag %s-%s.%s[%s]\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), source_name(pool_source(pool, s)));
771 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);
772 for (i = 0; dp[i]; i++)
773 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));
775 /* add 'requires' dependency */
776 addrule(solv, -n, dp - pool->whatprovidesdata); /* rule: (-requestor|provider1|provider2|...|providerN) */
778 /* descend the dependency tree */
779 for (; *dp != ID_NULL; dp++) /* loop through all providers */
785 } /* while, requirements of n */
787 } /* if, requirements */
790 /*-----------------------------------------
791 * check conflicts of s
794 if ((conp = s->conflicts) != ID_NULL)
796 while ((con = *conp++) != ID_NULL)
798 FOR_PROVIDES(p, pp, con) /* loop through all providers of this conflict */
800 /* dontfix: dont care about conflicts with already installed packs */
801 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
803 addrule(solv, -n, -p); /* rule: -n|-p: either solvable _or_ provider of conflict */
808 /*-----------------------------------------
809 * check obsoletes if not installed
811 if (!system || n < system->start || n >= (system->start + system->nsolvables))
812 { /* not installed */
813 if ((obsp = s->obsoletes) != ID_NULL)
815 while ((obs = *obsp++) != ID_NULL)
817 FOR_PROVIDES(p, pp, obs)
818 addrule(solv, -n, -p);
821 FOR_PROVIDES(p, pp, s->name)
823 if (s->name == pool->solvables[p].name)
824 addrule(solv, -n, -p);
828 /*-----------------------------------------
829 * add recommends to the rule list
831 if ((recp = s->recommends) != ID_NULL)
832 while ((rec = *recp++) != ID_NULL)
834 FOR_PROVIDES(p, pp, rec)
843 addrulesforsupplements(Solver *solv, Map *m)
845 Pool *pool = solv->pool;
851 if (pool->verbose) printf("addrulesforsupplements... (%d)\n", solv->nrules);
852 for (i = n = 1; n < pool->nsolvables; i++, n++)
854 if (i == pool->nsolvables)
858 s = pool->solvables + i;
859 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
861 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
864 if ((supp = s->supplements) != 0)
866 while ((sup = *supp++) != ID_NULL)
868 FOR_PROVIDES(p, pp, sup)
875 if (!sup && (supp = s->freshens) != 0)
877 while ((sup = *supp++) != ID_NULL)
879 FOR_PROVIDES(p, pp, sup)
888 addrulesforsolvable(solv, s, m);
891 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
896 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
898 Id a1 = s1->arch, a2 = s2->arch;
900 /* we allow changes to/from noarch */
901 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
905 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
906 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
907 if (((a1 ^ a2) & 0xffff0000) != 0)
914 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
916 /* system packages get a special upgrade allowed rule */
917 Pool *pool = solv->pool;
918 Id p, *pp, n, p2, *pp2;
926 n = s - pool->solvables;
927 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
928 addrulesforsolvable(solv, s, m);
930 #if defined(GNADENLOS)
931 for (p = 1; p < pool->nsolvables; ++p)
936 if (s->name == pool->solvables[p].name)
939 if ((obsp = pool->solvables[p].obsoletes) != 0) /* provides/obsoletes combination ? */
941 while ((obs = *obsp++) != 0) /* for all obsoletes */
943 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
945 if (p2 == n) /* match ! */
951 if (!obs) /* continue if no match */
960 * look for updates for s
962 FOR_PROVIDES(p, pp, s->name) /* every provider of s' name */
964 if (p == n) /* skip itself */
967 if (s->name == pool->solvables[p].name) /* name match */
969 if (!allowdowngrade /* consider downgrades ? */
970 && evrcmp(pool, s->evr, pool->solvables[p].evr) > 0)
973 if (!allowarchchange && archchanges(pool, s, pool->solvables + p))
976 #if !defined(GNADENLOS)
977 else if ((obsp = pool->solvables[p].obsoletes) != 0) /* provides/obsoletes combination ? */
979 while ((obs = *obsp++) != 0) /* for all obsoletes */
981 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
983 if (p2 == n) /* match ! */
989 if (!obs) /* continue if no match */
991 /* here we have 'p' with a matching provides/obsoletes combination
992 * thus flagging p as a valid update candidate for s
1000 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1001 addrulesforsolvable(solv, pool->solvables + p, m);
1006 * add rule for update
1007 * (A|A1|A2|A3...) An = update candidates for A
1009 * s = (installed) solvable
1010 * m = 'addedmap', bit set if 'install' rule for solvable exists
1014 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
1016 /* system packages get a special upgrade allowed rule */
1017 Pool *pool = solv->pool;
1023 queueinit_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1024 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
1025 p = s - pool->solvables;
1026 if (dontaddrule) /* we consider update candidates but dont force them */
1032 if (qs.count == 0) /* no updates found */
1035 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1037 addrule(solv, p, 0); /* request 'install' of s */
1042 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1044 r = addrule(solv, p, d); /* allow update of s */
1046 printf("new update rule ");
1053 /*-----------------------------------------------------------------*/
1060 * initial setup for all watches
1064 makewatches(Solver *solv)
1068 int nsolvables = solv->pool->nsolvables;
1070 xfree(solv->watches);
1071 /* lower half for removals, upper half for installs */
1072 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1074 /* do it reverse so rpm rules get triggered first */
1075 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1077 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1080 if (!r->w1 /* rule is disabled */
1081 || !r->w2) /* rule is assertion */
1084 /* see addwatches(solv, r) */
1085 r->n1 = solv->watches[nsolvables + r->w1];
1086 solv->watches[nsolvables + r->w1] = r - solv->rules;
1088 r->n2 = solv->watches[nsolvables + r->w2];
1089 solv->watches[nsolvables + r->w2] = r - solv->rules;
1095 * add watches (for rule)
1099 addwatches(Solver *solv, Rule *r)
1101 int nsolvables = solv->pool->nsolvables;
1103 r->n1 = solv->watches[nsolvables + r->w1];
1104 solv->watches[nsolvables + r->w1] = r - solv->rules;
1106 r->n2 = solv->watches[nsolvables + r->w2];
1107 solv->watches[nsolvables + r->w2] = r - solv->rules;
1111 /*-----------------------------------------------------------------*/
1112 /* rule propagation */
1114 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1119 * propagate decision to all rules
1123 propagate(Solver *solv, int level)
1125 Pool *pool = solv->pool;
1130 Id *decisionmap = solv->decisionmap;
1131 Id *watches = solv->watches + pool->nsolvables;
1133 while (solv->propagate_index < solv->decisionq.count)
1135 /* negative because our watches trigger if literal goes FALSE */
1136 pkg = -solv->decisionq.elements[solv->propagate_index++];
1138 printf("popagate for decision %d level %d\n", -pkg, level);
1139 printruleelement(solv, 0, -pkg);
1141 for (rp = watches + pkg; *rp; rp = nrp)
1143 r = solv->rules + *rp;
1145 printf(" watch triggered ");
1158 /* if clause is TRUE, nothing to do */
1159 if (DECISIONMAP_TRUE(ow))
1164 /* not a binary clause, check if we need to move our watch */
1165 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1168 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1169 if (p != ow && !DECISIONMAP_TRUE(-p))
1173 /* p is free to watch, move watch to p */
1176 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));
1178 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));
1192 watches[p] = r - solv->rules;
1196 /* unit clause found, set other watch to TRUE */
1197 if (DECISIONMAP_TRUE(-ow))
1198 return r; /* eek, a conflict! */
1204 decisionmap[ow] = level;
1206 decisionmap[-ow] = -level;
1207 queuepush(&solv->decisionq, ow);
1208 queuepush(&solv->decisionq_why, r - solv->rules);
1211 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1213 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1215 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1220 return 0; /* all is well */
1224 /*-----------------------------------------------------------------*/
1233 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1235 Pool *pool = solv->pool;
1238 Map seen; /* global? */
1242 int learnt_why = solv->learnt_pool.count;
1243 Id *decisionmap = solv->decisionmap;
1247 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1248 mapinit(&seen, pool->nsolvables);
1249 idx = solv->decisionq.count;
1253 queuepush(&solv->learnt_pool, c - solv->rules);
1254 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1265 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1267 vv = v > 0 ? v : -v;
1268 if (MAPTST(&seen, vv))
1270 l = solv->decisionmap[vv];
1277 for (j = 0; j < solv->decisionq.count; j++)
1278 if (solv->decisionq.elements[j] == v)
1280 if (j == solv->decisionq.count)
1282 queuepush(&rulq, -(j + 1));
1284 continue; /* initial setting */
1288 num++; /* need to do this one as well */
1293 printf("PUSH %d ", v);
1294 printruleelement(solv, 0, v);
1301 printf("num = %d\n", num);
1307 v = solv->decisionq.elements[--idx];
1308 vv = v > 0 ? v : -v;
1309 if (MAPTST(&seen, vv))
1312 c = solv->rules + solv->decisionq_why.elements[idx];
1320 else if (r.count == 1 && r.elements[0] < 0)
1321 *dr = r.elements[0];
1323 *dr = pool_queuetowhatprovides(pool, &r);
1326 printf("learned rule for level %d (am %d)\n", rlevel, level);
1327 printruleelement(solv, 0, -v);
1328 for (i = 0; i < r.count; i++)
1331 printruleelement(solv, 0, v);
1335 queuepush(&solv->learnt_pool, 0);
1337 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1339 printf("learnt_why ");
1340 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1351 * reset the solver decisions to right after the rpm rules
1355 reset_solver(Solver *solv)
1361 /* delete all learnt rules */
1362 solv->nrules = solv->learntrules;
1363 QUEUEEMPTY(&solv->learnt_why);
1364 QUEUEEMPTY(&solv->learnt_pool);
1366 /* redo all direct decision without the disabled rules */
1367 for (i = 0; i < solv->decisionq.count; i++)
1369 v = solv->decisionq.elements[i];
1370 solv->decisionmap[v > 0 ? v : -v] = 0;
1372 for (i = 0; i < solv->decisionq_why.count; i++)
1373 if (solv->decisionq_why.elements[i])
1377 v = solv->decisionq.elements[i];
1378 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1381 if (solv->pool->verbose)
1382 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1384 solv->decisionq_why.count = i;
1385 solv->decisionq.count = i;
1386 solv->recommends_index = -1;
1387 if (i < solv->propagate_index)
1388 solv->propagate_index = i;
1389 /* make direct decisions from enabled unary rules */
1390 for (i = solv->jobrules, r = solv->rules + solv->jobrules; i < solv->nrules; i++, r++)
1392 if (!r->w1 || r->w2)
1398 queuepush(&solv->decisionq, v);
1399 queuepush(&solv->decisionq_why, r - solv->rules);
1400 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1402 if (solv->pool->verbose)
1403 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1404 /* recreate watches */
1410 * analyze_unsolvable_rule
1414 analyze_unsolvable_rule(Solver *solv, Rule *c, int disablerules)
1419 why = c - solv->rules;
1421 if (why >= solv->jobrules && why < solv->systemrules)
1423 if (why >= solv->systemrules && why < solv->learntrules)
1424 printf("SYSTEM %d ", why - solv->systemrules);
1425 if (solv->learntrules && why >= solv->learntrules)
1429 if (solv->learntrules && why >= solv->learntrules)
1431 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1432 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], disablerules);
1435 if (why >= solv->jobrules && why < solv->learntrules)
1439 /* turn off rule for further analysis */
1443 if (solv->problems.count)
1445 for (i = solv->problems.count - 1; i >= 0; i--)
1446 if (solv->problems.elements[i] == 0)
1448 else if (solv->problems.elements[i] == why)
1451 queuepush(&solv->problems, why);
1457 * analyze_unsolvable
1461 analyze_unsolvable(Solver *solv, Rule *c, int disablerules)
1463 Pool *pool = solv->pool;
1464 Map seen; /* global? */
1467 Id *decisionmap = solv->decisionmap;
1470 printf("ANALYZE UNSOLVABLE ----------------------\n");
1472 mapinit(&seen, pool->nsolvables);
1473 analyze_unsolvable_rule(solv, c, disablerules);
1474 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1485 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1487 vv = v > 0 ? v : -v;
1488 l = solv->decisionmap[vv];
1493 idx = solv->decisionq.count;
1496 v = solv->decisionq.elements[--idx];
1497 vv = v > 0 ? v : -v;
1498 if (!MAPTST(&seen, vv))
1500 why = solv->decisionq_why.elements[idx];
1505 printruleelement(solv, 0, v);
1509 c = solv->rules + why;
1510 analyze_unsolvable_rule(solv, c, disablerules);
1511 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1522 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1524 vv = v > 0 ? v : -v;
1525 l = solv->decisionmap[vv];
1532 queuepush(&solv->problems, 0); /* mark end of this problem */
1536 printf("analyze_unsolvables done\n");
1541 /*-----------------------------------------------------------------*/
1542 /* Decision revert */
1546 * revert decision at level
1550 revert(Solver *solv, int level)
1553 while (solv->decisionq.count)
1555 v = solv->decisionq.elements[solv->decisionq.count - 1];
1556 vv = v > 0 ? v : -v;
1557 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1560 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1562 solv->decisionmap[vv] = 0;
1563 solv->decisionq.count--;
1564 solv->decisionq_why.count--;
1565 solv->propagate_index = solv->decisionq.count;
1567 solv->recommends_index = -1;
1576 watch2onhighest(Solver *solv, Rule *r)
1582 return; /* binary rule, both watches are set */
1583 dp = solv->pool->whatprovidesdata + r->d;
1584 while ((v = *dp++) != 0)
1586 l = solv->decisionmap[v < 0 ? -v : v];
1603 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1613 solv->decisionmap[decision] = level;
1615 solv->decisionmap[-decision] = -level;
1616 queuepush(&solv->decisionq, decision);
1617 queuepush(&solv->decisionq_why, 0);
1621 r = propagate(solv, level);
1626 analyze_unsolvable(solv, r, disablerules);
1631 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1632 l = analyze(solv, level, r, &p, &d, &why);
1633 if (l >= level || l <= 0)
1635 printf("reverting decisions (level %d -> %d)\n", level, l);
1637 revert(solv, level);
1638 r = addrule(solv, p, d); /* p requires d */
1641 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1643 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1646 queuepush(&solv->learnt_why, why);
1649 /* at least 2 literals, needs watches */
1650 watch2onhighest(solv, r);
1651 addwatches(solv, r);
1653 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1654 queuepush(&solv->decisionq, p);
1655 queuepush(&solv->decisionq_why, r - solv->rules);
1656 printf("decision: ");
1657 printruleelement(solv, 0, p);
1658 printf("new rule: ");
1664 /*-----------------------------------------------------------------*/
1665 /* Main solver interface */
1670 * create solver structure
1672 * pool: all available solvables
1673 * system: installed Solvables
1676 * Upon solving, rules are created to flag the Solvables
1677 * of the 'system' Source as installed.
1681 solver_create(Pool *pool, Source *system)
1684 solv = (Solver *)xcalloc(1, sizeof(Solver));
1686 solv->system = system;
1689 queueinit(&solv->decisionq);
1690 queueinit(&solv->decisionq_why);
1691 queueinit(&solv->problems);
1692 queueinit(&solv->learnt_why);
1693 queueinit(&solv->learnt_pool);
1695 mapinit(&solv->recommends, pool->nsolvables);
1696 solv->recommends_index = 0;
1698 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1699 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1700 memset(solv->rules, 0, sizeof(Rule));
1712 solver_free(Solver *solv)
1714 queuefree(&solv->decisionq);
1715 queuefree(&solv->decisionq_why);
1716 queuefree(&solv->learnt_why);
1717 queuefree(&solv->learnt_pool);
1718 mapfree(&solv->recommends);
1719 xfree(solv->decisionmap);
1721 xfree(solv->watches);
1722 xfree(solv->weaksystemrules);
1730 * r->w1 was set to 0, now find proper value for w1
1734 reenablerule(Solver *solv, Rule *r)
1739 if (!r->w2) /* not a rule, but an assertion */
1749 r->w2 = r->d; /* mls: shouldn't this be r->w1 ? */
1753 /* put it on the first not-false literal */
1759 v = solv->pool->whatprovidesdata[r->d + i];
1767 l = solv->decisionmap[v > 0 ? v : -v];
1768 if (!l || (v < 0 && l < 0) || (v > 0 && l > 0))
1775 /*-------------------------------------------------------*/
1780 * all rules have been set up, not actually run the solver
1785 run_solver(Solver *solv, int disablerules, int doweak)
1793 Pool *pool = solv->pool;
1797 printf("number of rules: %d\n", solv->nrules);
1800 for (i = 0; i < solv->nrules; i++)
1802 printrule(solv, solv->rules + i);
1807 /* all new rules are learnt after this point */
1808 solv->learntrules = solv->nrules;
1809 /* crate watches lists */
1812 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1814 /* start SAT algorithm */
1816 systemlevel = level + 1;
1817 if (pool->verbose) printf("solving...\n");
1828 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1829 if ((r = propagate(solv, level)) != 0)
1831 analyze_unsolvable(solv, r, disablerules);
1834 printf("UNSOLVABLE\n");
1844 if (level < systemlevel && solv->system->nsolvables)
1846 if (!solv->updatesystem)
1848 /* try to keep as many packages as possible */
1849 if (pool->verbose) printf("installing system packages\n");
1850 for (i = solv->system->start, n = 0; ; i++, n++)
1852 if (n == solv->system->nsolvables)
1854 if (i == solv->system->start + solv->system->nsolvables)
1855 i = solv->system->start;
1856 s = pool->solvables + i;
1857 if (solv->decisionmap[i] != 0)
1860 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1863 level = setpropagatelearn(solv, level, i, disablerules);
1866 printf("UNSOLVABLE\n");
1870 if (level <= olevel)
1874 if (solv->weaksystemrules)
1876 if (pool->verbose) printf("installing weak system packages\n");
1877 for (i = solv->system->start, n = 0; ; i++, n++)
1879 if (n == solv->system->nsolvables)
1881 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->system->start] == 0))
1884 if (solv->decisionmap[i] == 0)
1886 if (solv->weaksystemrules[i - solv->system->start])
1888 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1889 while ((p = *dp++) != 0)
1891 if (solv->decisionmap[p] > 0)
1893 if (solv->decisionmap[p] == 0)
1897 continue; /* rule is already true */
1903 prune_to_recommended(solv, &dq);
1905 prune_best_version_arch(pool, &dq);
1907 s = pool->solvables + dq.elements[0];
1908 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1911 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
1914 printf("UNSOLVABLE\n");
1918 if (level <= olevel)
1924 if (n != solv->system->nsolvables)
1927 systemlevel = level;
1934 if (pool->verbose) printf("deciding unresolved rules\n");
1935 for (i = 1, n = 1; ; i++, n++)
1937 if (n == solv->nrules)
1939 if (i == solv->nrules)
1941 r = solv->rules + i;
1947 /* binary or unary rule */
1948 /* need two positive undecided literals */
1949 if (r->p < 0 || r->w2 <= 0)
1951 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
1953 queuepush(&dq, r->p);
1954 queuepush(&dq, r->w2);
1959 * all negative literals are installed
1960 * no positive literal is installed
1961 * i.e. the rule is not fulfilled and we
1962 * just need to decide on the positive literals
1966 if (solv->decisionmap[-r->p] <= 0)
1971 if (solv->decisionmap[r->p] > 0)
1973 if (solv->decisionmap[r->p] == 0)
1974 queuepush(&dq, r->p);
1976 dp = pool->whatprovidesdata + r->d;
1977 while ((p = *dp++) != 0)
1981 if (solv->decisionmap[-p] <= 0)
1986 if (solv->decisionmap[p] > 0)
1988 if (solv->decisionmap[p] == 0)
1997 /* cannot happen as this means that
1998 * the rule is unit */
2002 prune_to_recommended(solv, &dq);
2004 prune_best_version_arch(pool, &dq);
2005 p = dq.elements[dq.count - 1];
2006 s = pool->solvables + p;
2008 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2011 level = setpropagatelearn(solv, level, p, disablerules);
2014 printf("UNSOLVABLE\n");
2018 if (level < systemlevel)
2020 if (level <= olevel)
2022 } /* for(), decide */
2024 if (n != solv->nrules) /* continue if level < systemlevel */
2027 if (doweak && !solv->problems.count)
2031 if (pool->verbose) printf("installing recommended packages\n");
2033 for (i = 1; i < pool->nsolvables; i++)
2035 if (solv->decisionmap[i] < 0)
2037 if (solv->decisionmap[i] > 0)
2039 Id *recp, rec, *pp, p;
2040 s = pool->solvables + i;
2041 /* installed, check for recommends */
2042 /* XXX need to special case AND ? */
2043 if ((recp = s->recommends) != 0)
2045 while ((rec = *recp++) != 0)
2048 FOR_PROVIDES(p, pp, rec)
2050 if (solv->decisionmap[p] > 0)
2055 else if (solv->decisionmap[p] == 0)
2056 queuepushunique(&dq, p);
2064 s = pool->solvables + i;
2065 if (!s->supplements && !s->freshens)
2067 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
2069 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
2071 if ((supp = s->supplements) != 0)
2073 while ((sup = *supp++) != 0)
2074 if (dep_fulfilled(solv, sup))
2079 if ((supp = s->freshens) != 0)
2081 while ((sup = *supp++) != 0)
2082 if (dep_fulfilled(solv, sup))
2087 queuepushunique(&dq, i);
2092 prune_best_version_arch(pool, &dq);
2093 p = dq.elements[dq.count - 1];
2094 s = pool->solvables + p;
2096 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2098 level = setpropagatelearn(solv, level, p, 0);
2113 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2121 printf("refine_suggestion start\n");
2122 queueinit(&disabled);
2123 QUEUEEMPTY(refined);
2124 queuepush(refined, sug);
2126 /* re-enable all rules but rule "sug" of the problem */
2127 for (i = 0; problem[i]; i++)
2129 if (problem[i] == sug)
2131 r = solv->rules + problem[i];
2136 reenablerule(solv, r);
2140 revert(solv, 1); /* XXX move to reset_solver? */
2142 QUEUEEMPTY(&solv->problems);
2143 run_solver(solv, 0, 0);
2144 if (!solv->problems.count)
2146 printf("no more problems!\n");
2148 printdecisions(solv);
2150 break; /* great, no more problems */
2152 disabledcnt = disabled.count;
2153 for (i = 0; i < solv->problems.elements[i]; i++)
2155 /* ignore solutions in refined */
2156 v = solv->problems.elements[i];
2157 for (j = 0; problem[j]; j++)
2158 if (problem[j] != sug && problem[j] == v)
2162 queuepush(&disabled, v);
2164 if (disabled.count == disabledcnt)
2166 /* no solution found, this was an invalid suggestion! */
2167 printf("no solution found!\n");
2168 for (i = 0; i < refined->count; i++)
2169 reenablerule(solv, solv->rules + refined->elements[i]);
2173 if (disabled.count == disabledcnt + 1)
2175 /* just one solution, add it to refined list */
2176 queuepush(refined, disabled.elements[disabledcnt]);
2180 printf("############################################## more than one solution found.\n");
2182 for (i = 0; i < solv->problems.elements[i]; i++)
2184 printrule(solv, solv->rules + solv->problems.elements[i]);
2186 printf("##############################################\n");
2188 /* more than one solution */
2189 /* for now return */
2191 for (i = disabledcnt; i < disabled.count; i++)
2193 r = solv->rules + disabled.elements[i];;
2202 /* enable refined rules again */
2203 for (i = 0; i < disabled.count; i++)
2204 reenablerule(solv, solv->rules + disabled.elements[i]);
2205 /* disable problem rules again so that we are in the same state as before */
2206 for (i = 0; problem[i]; i++)
2208 r = solv->rules + problem[i];
2211 printf("refine_suggestion end\n");
2220 id2rc(Solver *solv, Id id)
2223 if (solv->rc_output != 2)
2225 evr = id2str(solv->pool, id);
2226 if (*evr < '0' || *evr > '9')
2228 while (*evr >= '0' && *evr <= '9')
2236 printdecisions(Solver *solv)
2238 Pool *pool = solv->pool;
2239 Id p, *obsoletesmap;
2243 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2244 for (i = 0; i < solv->decisionq.count; i++)
2249 n = solv->decisionq.elements[i];
2252 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2254 s = pool->solvables + n;
2255 if ((obsp = s->obsoletes) != 0)
2256 while ((obs = *obsp++) != 0)
2257 FOR_PROVIDES(p, pp, obs)
2259 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2261 obsoletesmap[p] = n;
2265 FOR_PROVIDES(p, pp, s->name)
2266 if (s->name == pool->solvables[p].name)
2268 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2270 obsoletesmap[p] = n;
2276 if (solv->rc_output)
2277 printf(">!> Solution #1:\n");
2279 int installs = 0, uninstalls = 0, upgrades = 0;
2281 /* print solvables to be erased */
2283 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2285 if (solv->decisionmap[i] > 0)
2287 if (obsoletesmap[i])
2289 s = pool->solvables + i;
2290 if (solv->rc_output == 2)
2291 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2292 else if (solv->rc_output)
2293 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2295 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2299 /* print solvables to be installed */
2301 for (i = 0; i < solv->decisionq.count; i++)
2304 p = solv->decisionq.elements[i];
2307 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2309 s = pool->solvables + p;
2311 if (!obsoletesmap[p])
2313 if (solv->rc_output)
2315 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2316 if (solv->rc_output != 2)
2317 printf(".%s", id2str(pool, s->arch));
2320 else if (!solv->rc_output)
2322 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2323 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2325 if (obsoletesmap[j] != p)
2327 s = pool->solvables + j;
2328 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2335 Solvable *f, *fn = 0;
2336 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2338 if (obsoletesmap[j] != p)
2340 f = pool->solvables + j;
2341 if (fn || f->name != s->name)
2343 if (solv->rc_output == 2)
2344 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2345 else if (solv->rc_output)
2346 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2354 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2355 if (solv->rc_output != 2)
2356 printf(".%s", id2str(pool, s->arch));
2361 if (solv->rc_output == 2)
2362 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));
2364 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));
2368 if (solv->rc_output)
2370 Source *source = pool_source(pool, s);
2371 if (source && strcmp(source_name(source), "locales"))
2372 printf("[%s]", source_name(source));
2377 if (solv->rc_output)
2378 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2380 xfree(obsoletesmap);
2384 /*-----------------------------------------------------------------*/
2394 solve(Solver *solv, Queue *job)
2396 Pool *pool = solv->pool;
2398 Map addedmap; /* '1' == have rule for solvable */
2399 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2400 Id how, what, p, *pp, d;
2406 * create basic rule set of all involved packages
2411 mapinit(&addedmap, pool->nsolvables);
2412 mapinit(&noupdaterule, pool->nsolvables);
2417 * create rules for installed solvables -> keep them installed
2418 * so called: rpm rules
2422 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2423 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2426 * create install rules
2428 * two passes, as we want to keep the rpm rules distinct from the job rules
2434 * process job rules for solvables
2437 for (i = 0; i < job->count; i += 2)
2439 how = job->elements[i];
2440 what = job->elements[i + 1];
2444 case SOLVER_INSTALL_SOLVABLE:
2445 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2447 case SOLVER_INSTALL_SOLVABLE_NAME:
2448 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2450 FOR_PROVIDES(p, pp, what)
2452 /* if by name, ensure that the name matches */
2453 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2455 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2458 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2459 /* dont allow downgrade */
2460 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2466 * if unstalls are disallowed, add update rules for every
2467 * installed solvables in the hope to circumvent uninstall
2473 if (!solv->allowuninstall)
2475 /* add update rule for every installed package */
2476 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2477 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2479 #else /* this is just to add the needed rpm rules to our set */
2480 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2481 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2484 addrulesforsupplements(solv, &addedmap);
2489 * unify existing rules before going over all job rules
2493 unifyrules(solv); /* remove duplicate rpm rules */
2496 * at this point the system is always solvable,
2497 * as an empty system (remove all packages) is a valid solution
2499 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2502 * now add all job rules
2505 solv->jobrules = solv->nrules;
2507 for (i = 0; i < job->count; i += 2)
2509 how = job->elements[i];
2510 what = job->elements[i + 1];
2513 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2514 if (solv->rc_output) {
2515 Solvable *s = pool->solvables + what;
2516 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(pool_source(pool, s)));
2518 addrule(solv, what, 0); /* install by Id */
2520 case SOLVER_ERASE_SOLVABLE:
2521 addrule(solv, -what, 0); /* remove by Id */
2522 MAPSET(&noupdaterule, what);
2524 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2525 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2527 FOR_PROVIDES(p, pp, what) /* check all providers */
2529 /* if by name, ensure that the name matches */
2530 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2534 if (!q.count) { /* no provider found -> abort */
2535 fprintf(stderr, "Nothing provides '%s'\n", id2str(pool, what));
2536 /* XXX make this a problem! */
2541 p = queueshift(&q); /* get first provider */
2543 d = 0; /* single provider ? -> make assertion */
2545 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2546 addrule(solv, p, d); /* add 'requires' rule */
2548 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2549 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2550 FOR_PROVIDES(p, pp, what)
2552 /* if by name, ensure that the name matches */
2553 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2556 addrule(solv, -p, 0); /* add 'remove' rule */
2557 MAPSET(&noupdaterule, p);
2560 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2561 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2566 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2569 * now add policy rules
2573 solv->systemrules = solv->nrules;
2576 * create rules for updating installed solvables
2582 if (!solv->allowuninstall)
2583 { /* loop over all installed solvables */
2584 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2586 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2587 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2589 addrule(solv, 0, 0); /* place holder */
2591 /* consistency check: we added a rule for _every_ system solvable */
2592 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2596 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2598 /* create special weak system rules */
2599 if (solv->system->nsolvables)
2601 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2602 for (i = 0; i < solv->system->nsolvables; i++)
2604 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2606 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2610 /* free unneeded memory */
2612 mapfree(&noupdaterule);
2620 run_solver(solv, 1, 1);
2624 * print solver result
2628 if (pool->verbose) printf("-------------------------------------------------------------\n");
2630 if (solv->problems.count)
2640 clonequeue(&problems, &solv->problems);
2641 queueinit(&solution);
2642 printf("Encountered problems! Here are the solutions:\n");
2643 problem = problems.elements;
2644 for (i = 0; i < problems.count; i++)
2646 Id v = problems.elements[i];
2649 printf("====================================\n");
2650 problem = problems.elements + i + 1;
2653 refine_suggestion(solv, problem, v, &solution);
2654 for (j = 0; j < solution.count; j++)
2656 r = solv->rules + solution.elements[j];
2657 why = solution.elements[j];
2661 if (why >= solv->jobrules && why < solv->systemrules)
2663 /* do a sloppy job of analyzing the job rule */
2666 s = pool->solvables + r->p;
2667 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2671 s = pool->solvables - r->p;
2672 printf("- do not erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2675 else if (why >= solv->systemrules && why < solv->learntrules)
2678 s = pool->solvables + solv->system->start + (why - solv->systemrules);
2679 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2681 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2683 if (solv->decisionmap[*dp] > 0)
2685 sd = pool->solvables + *dp;
2691 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));
2695 printf("- allow deinstallation of %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2703 printf("------------------------------------\n");
2708 printdecisions(solv);