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, sug, *sugp, enh, *enhp;
122 if (solv->recommends_index < 0)
124 MAPZERO(&solv->recommends);
125 MAPZERO(&solv->suggests);
126 solv->recommends_index = 0;
128 while (solv->recommends_index < solv->decisionq.count)
130 p = solv->decisionq.elements[solv->recommends_index++];
133 s = pool->solvables + p;
134 if ((recp = s->recommends) != 0)
135 while ((rec = *recp++) != 0)
136 FOR_PROVIDES(p, pp, rec)
137 MAPSET(&solv->recommends, p);
138 if ((sugp = s->suggests) != 0)
139 while ((sug = *sugp++) != 0)
140 FOR_PROVIDES(p, pp, sug)
141 MAPSET(&solv->suggests, p);
143 /* prune to recommended/supplemented */
144 for (i = j = 0; i < plist->count; i++)
146 p = plist->elements[i];
147 if (MAPTST(&solv->recommends, p))
149 plist->elements[j++] = p;
152 s = pool->solvables + p;
153 if (!s->supplements && !s->freshens)
155 if ((supp = s->supplements) != 0)
157 while ((sup = *supp++) != 0)
158 if (dep_fulfilled(solv, sup))
163 if ((supp = s->freshens) != 0)
165 while ((sup = *supp++) != 0)
166 if (dep_fulfilled(solv, sup))
171 plist->elements[j++] = s - pool->solvables;
176 /* prune to suggested/enhanced*/
177 if (plist->count < 2)
179 for (i = j = 0; i < plist->count; i++)
181 p = plist->elements[i];
182 if (MAPTST(&solv->suggests, p))
184 plist->elements[j++] = p;
187 s = pool->solvables + p;
188 if (!(enhp = s->enhances))
190 while ((enh = *enhp++) != 0)
191 if (dep_fulfilled(solv, enh))
195 plist->elements[j++] = s - pool->solvables;
202 * prune_best_version_arch
204 * sort list of packages (given through plist) by name and evr
205 * return result through plist
209 /* FIXME: must also look at update packages */
212 prune_best_version_arch(Pool *pool, Queue *plist)
219 if (plist->count < 2) /* no need to prune for a single entry */
221 if (pool->verbose) printf("prune_best_version_arch %d\n", plist->count);
223 /* prune to best architecture */
227 for (i = 0; i < plist->count; i++)
229 s = pool->solvables + plist->elements[i];
231 if (a > pool->lastarch)
233 a = pool->id2arch[a];
234 if (!bestscore || (a & 0xffff0000) < bestscore)
235 bestscore = a & 0xffff0000;
237 for (i = j = 0; i < plist->count; i++)
239 s = pool->solvables + plist->elements[i];
241 if (a > pool->lastarch)
243 a = pool->id2arch[a];
244 /* a == 1 -> noarch */
245 if (a != 1 && (a & 0xffff0000) != bestscore)
247 plist->elements[j++] = plist->elements[i];
254 prune_best_version_arch_sortcmp_data = pool;
255 /* sort by name first */
256 qsort(plist->elements, plist->count, sizeof(Id), prune_best_version_arch_sortcmp);
258 /* now find best 'per name' */
259 for (i = j = 0; i < plist->count; i++)
261 s = pool->solvables + plist->elements[i];
262 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
265 if (pool->verbose) printf("- %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
267 if (!best) /* if no best yet, the current is best */
269 best = plist->elements[i];
273 /* name switch: re-init */
274 if (pool->solvables[best].name != s->name) /* new name */
276 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));
277 plist->elements[j++] = best; /* move old best to front */
278 best = plist->elements[i]; /* take current as new best */
282 if (pool->solvables[best].evr != s->evr) /* compare evr */
284 if (evrcmp(pool, pool->solvables[best].evr, s->evr) < 0)
285 best = plist->elements[i];
290 best = plist->elements[0];
292 /* XXX also check obsoletes! */
293 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));
295 plist->elements[j++] = best;
300 /*-----------------------------------------------------------------*/
307 printruleelement(Solver *solv, Rule *r, Id v)
309 Pool *pool = solv->pool;
313 s = pool->solvables + -v;
314 printf(" !%s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), -v);
318 s = pool->solvables + v;
319 printf(" %s-%s.%s [%d]", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch), v);
328 if (solv->decisionmap[s - pool->solvables] > 0)
329 printf(" I.%d", solv->decisionmap[s - pool->solvables]);
330 if (solv->decisionmap[s - pool->solvables] < 0)
331 printf(" C.%d", -solv->decisionmap[s - pool->solvables]);
341 printrule(Solver *solv, Rule *r)
346 if (r >= solv->rules && r < solv->rules + solv->nrules) /* r is a solver rule */
347 printf("Rule #%d:\n", (int)(r - solv->rules));
349 printf("Rule:\n"); /* r is any rule */
354 else if (r->d == ID_NULL)
361 v = solv->pool->whatprovidesdata[r->d + i - 1];
364 printruleelement(solv, r, v);
366 printf(" next: %d %d\n", r->n1, r->n2);
370 /*-----------------------------------------------------------------*/
376 static Pool *unifyrules_sortcmp_data;
379 * compare rules for unification sort
383 unifyrules_sortcmp(const void *ap, const void *bp)
385 Pool *pool = unifyrules_sortcmp_data;
386 Rule *a = (Rule *)ap;
387 Rule *b = (Rule *)bp;
393 return x; /* p differs */
396 if (a->d == 0 && b->d == 0)
397 return a->w2 - b->w2; /* assertion: return w2 diff */
399 if (a->d == 0) /* a is assertion, b not */
401 x = a->w2 - pool->whatprovidesdata[b->d];
405 if (b->d == 0) /* b is assertion, a not */
407 x = pool->whatprovidesdata[a->d] - b->w2;
411 /* compare whatprovidesdata */
412 ad = pool->whatprovidesdata + a->d;
413 bd = pool->whatprovidesdata + b->d;
414 for (; *ad && *ad == *bd; ad++, bd++)
425 unifyrules(Solver *solv)
430 if (solv->nrules <= 1) /* nothing to unify */
433 /* sort rules first */
434 unifyrules_sortcmp_data = solv->pool;
435 qsort(solv->rules + 1, solv->nrules - 1, sizeof(Rule), unifyrules_sortcmp);
442 for (i = j = 1, ir = solv->rules + 1; i < solv->nrules; i++, ir++)
444 if (jr && !unifyrules_sortcmp(ir, jr))
445 continue; /* prune! */
446 jr = solv->rules + j++; /* keep! */
451 /* reduced count from nrules to j rules */
452 if (solv->pool->verbose) printf("pruned rules from %d to %d\n", solv->nrules, j);
454 /* adapt rule buffer */
455 solv->rules = (Rule *)xrealloc(solv->rules, ((solv->nrules + RULES_BLOCK) & ~RULES_BLOCK) * sizeof(Rule));
464 for (i = 1; i < solv->nrules; i++)
467 if (r->d == 0) /* assertion */
472 dp = solv->pool->whatprovidesdata + r->d;
476 if (solv->pool->verbose)
478 printf(" binary: %d\n", binr);
479 printf(" normal: %d\n", solv->nrules - 1 - binr);
480 printf(" normal lits: %d\n", dc);
493 hashrule(Solver *solv, Id p, Id d, int n)
495 unsigned int x = (unsigned int)p;
499 return (x * 37) ^ (unsigned int)d;
500 dp = solv->pool->whatprovidesdata + d;
502 x = (x * 37) ^ (unsigned int)*dp++;
510 * p = direct literal; > 0 for learnt, < 0 for installed pkg (rpm)
511 * d, if < 0 direct literal, if > 0 offset into whatprovides, if == 0 rule is assertion (look at p only)
514 * A requires b, b provided by B1,B2,B3 => (-A|B1|B2|B3)
516 * p < 0 : rule from rpm (installed pkg)
517 * d > 0 : Offset in whatprovidesdata (list of providers)
519 * A conflicts b, b provided by B1,B2,B3 => (-A|-B1), (-A|-B2), (-A|-B3)
520 * d < 0: Id of solvable (e.g. B1)
522 * d == 0: unary rule, assertion => (A) or (-A)
524 * Install: p > 0, d = 0 (A) user requested install
525 * Remove: p < 0, d = 0 (-A) user requested remove
526 * Requires: p < 0, d > 0 (-A|B1|B2|...) d: <list of providers for requirement of p>
527 * Updates: p > 0, d > 0 (A|B1|B2|...) d: <list of updates for solvable p>
528 * Conflicts: p < 0, d < 0 (-A|-B) either p (conflict issuer) or d (conflict provider)
529 * ? p > 0, d < 0 (A|-B)
530 * No-op ?: p = 0, d = 0 (null) (used as policy rule placeholder)
534 addrule(Solver *solv, Id p, Id d)
539 int n = 0; /* number of literals in rule - 1
540 0 = direct assertion (single literal)
544 /* it often happenes that requires lead to adding the same rpm rule
545 * multiple times, so we prune those duplicates right away to make
546 * the work for unifyrules a bit easier */
548 if (solv->nrules && !solv->jobrules)
550 r = solv->rules + solv->nrules - 1; /* get the last added rule */
551 if (r->p == p && r->d == d && d != 0) /* identical and not user requested */
558 return NULL; /* ignore self conflict */
561 else if (d == 0) /* user requested */
565 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, n++)
567 return NULL; /* rule is self-fulfilling */
572 if (n == 0) /* direct assertion */
576 /* this is a rpm rule assertion, we do not have to allocate it */
577 /* we can identify it by looking at the decision level, it will be 1 */
580 if (solv->decisionmap[-p] > 0) /* */
582 if (solv->decisionmap[-p]) /* */
584 queuepush(&solv->decisionq, p);
585 queuepush(&solv->decisionq_why, 0);
586 solv->decisionmap[-p] = -1;
591 else if (n == 1 && p > d)
593 /* smallest literal first so we can find dups */
597 n = 1; /* re-set n, was used as temp var */
613 Id *dp2 = solv->pool->whatprovidesdata + r->d;
614 for (dp = solv->pool->whatprovidesdata + d; *dp; dp++, dp2++)
627 /* check and extend rule buffer */
628 if ((solv->nrules & RULES_BLOCK) == 0)
630 solv->rules = (Rule *)xrealloc(solv->rules, (solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
633 r = solv->rules + solv->nrules++; /* point to rule space */
638 /* direct assertion, no watch needed */
654 r->w2 = solv->pool->whatprovidesdata[d];
659 /* we don't add the decision for learnt rules, as the code does that
660 * right after calling addrule anyway */
663 && !solv->learntrules)
665 /* must be system or job rule, as there are only negative unary rpm rules */
666 Id vv = p > 0 ? p : -p;
667 if (solv->decisionmap[vv])
670 if (solv->decisionmap[vv] > 0 && p > 0)
672 if (solv->decisionmap[vv] < 0 && p < 0)
674 /* direct conflict! */
675 for (i = 0; i < solv->decisionq.count; i++)
676 if (solv->decisionq.elements[i] == -p)
678 if (i == solv->decisionq.count)
680 if (solv->decisionq_why.elements[i] == 0)
682 /* conflict with rpm rule */
683 queuepush(&solv->problems, r - solv->rules);
684 queuepush(&solv->problems, 0);
685 r->w1 = 0; /* disable */
688 /* conflict with other job or system rule */
689 queuepush(&solv->problems, solv->decisionq_why.elements[i]);
690 queuepush(&solv->problems, r - solv->rules);
691 queuepush(&solv->problems, 0);
692 r->w1 = 0; /* disable */
693 /* also disable conflicting rule */
694 solv->rules[solv->decisionq_why.elements[i]].w1 = 0;
695 /* XXX: remove from decisionq! */
696 printf("XXX remove from decisionq\n");
699 queuepush(&solv->decisionq, p);
700 queuepush(&solv->decisionq_why, r - solv->rules);
701 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? 1 : -1;
708 * add (install) rules for solvable
713 addrulesforsolvable(Solver *solv, Solvable *s, Map *m)
715 Pool *pool = solv->pool;
716 Source *system = solv->system;
729 queueinit_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
730 queuepush(&q, s - pool->solvables); /* push solvable Id */
736 * s: Pointer to solvable
740 if (MAPTST(m, n)) /* continue if already set in map */
744 s = pool->solvables + n; /* s = Solvable in question */
747 if (system /* have rpm */
749 && n >= system->start /* its an rpm rule */
750 && n < system->start + system->nsolvables)
752 dontfix = 1; /* dont care about broken rpm deps */
755 /*-----------------------------------------
756 * check requires of s
759 if ((reqp = s->requires) != ID_NULL)
761 while ((req = *reqp++) != ID_NULL)
763 if (req == SOLVABLE_PREREQMARKER) /* skip the marker */
766 dp = GET_PROVIDESP(req, p); /* get providers of req */
768 if (!*dp /* dont care if noone provides rpmlib() */
769 && !strncmp(id2str(pool, req), "rpmlib(", 7))
774 if (dontfix) /* rpm rule, dont care about breakage */
776 for (i = 0; dp[i]; i++)/* for all providers */
778 if (dp[i] >= system->start && dp[i] < system->start + system->nsolvables)
779 break; /* provider is installed */
781 if (!dp[i]) /* no provider found */
783 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));
790 /* nothing provides req! */
792 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));
794 addrule(solv, -n, 0); /* mark requestor as uninstallable */
796 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)));
800 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);
801 for (i = 0; dp[i]; i++)
802 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));
804 /* add 'requires' dependency */
805 addrule(solv, -n, dp - pool->whatprovidesdata); /* rule: (-requestor|provider1|provider2|...|providerN) */
807 /* descend the dependency tree */
808 for (; *dp != ID_NULL; dp++) /* loop through all providers */
814 } /* while, requirements of n */
816 } /* if, requirements */
819 /*-----------------------------------------
820 * check conflicts of s
823 if ((conp = s->conflicts) != ID_NULL)
825 while ((con = *conp++) != ID_NULL)
827 FOR_PROVIDES(p, pp, con) /* loop through all providers of this conflict */
829 /* dontfix: dont care about conflicts with already installed packs */
830 if (dontfix && p >= system->start && p < system->start + system->nsolvables)
832 addrule(solv, -n, -p); /* rule: -n|-p: either solvable _or_ provider of conflict */
837 /*-----------------------------------------
838 * check obsoletes if not installed
840 if (!system || n < system->start || n >= (system->start + system->nsolvables))
841 { /* not installed */
842 if ((obsp = s->obsoletes) != ID_NULL)
844 while ((obs = *obsp++) != ID_NULL)
846 FOR_PROVIDES(p, pp, obs)
847 addrule(solv, -n, -p);
850 FOR_PROVIDES(p, pp, s->name)
852 if (s->name == pool->solvables[p].name)
853 addrule(solv, -n, -p);
857 /*-----------------------------------------
858 * add recommends to the rule list
860 if ((recp = s->recommends) != ID_NULL)
861 while ((rec = *recp++) != ID_NULL)
863 FOR_PROVIDES(p, pp, rec)
872 addrulesforsupplements(Solver *solv, Map *m)
874 Pool *pool = solv->pool;
880 if (pool->verbose) printf("addrulesforsupplements... (%d)\n", solv->nrules);
881 for (i = n = 1; n < pool->nsolvables; i++, n++)
883 if (i == pool->nsolvables)
887 s = pool->solvables + i;
888 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
890 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
893 if ((supp = s->supplements) != 0)
895 while ((sup = *supp++) != ID_NULL)
897 FOR_PROVIDES(p, pp, sup)
904 if (!sup && (supp = s->freshens) != 0)
906 while ((sup = *supp++) != ID_NULL)
908 FOR_PROVIDES(p, pp, sup)
917 addrulesforsolvable(solv, s, m);
920 if (pool->verbose) printf("done. (%d)\n", solv->nrules);
925 archchanges(Pool *pool, Solvable *s1, Solvable *s2)
927 Id a1 = s1->arch, a2 = s2->arch;
929 /* we allow changes to/from noarch */
930 if (a1 == a2 || a1 == ARCH_NOARCH || a2 == ARCH_NOARCH)
934 a1 = a1 <= pool->lastarch ? pool->id2arch[a1] : 0;
935 a2 = a2 <= pool->lastarch ? pool->id2arch[a2] : 0;
936 if (((a1 ^ a2) & 0xffff0000) != 0)
943 findupdatepackages(Solver *solv, Solvable *s, Queue *qs, Map *m, int allowdowngrade, int allowarchchange)
945 /* system packages get a special upgrade allowed rule */
946 Pool *pool = solv->pool;
947 Id p, *pp, n, p2, *pp2;
955 n = s - pool->solvables;
956 if (m && !MAPTST(m, n)) /* add rule for s if not already done */
957 addrulesforsolvable(solv, s, m);
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 else if (!solv->noupdateprovide && (obsp = pool->solvables[p].obsoletes) != 0) /* provides/obsoletes combination ? */
978 while ((obs = *obsp++) != 0) /* for all obsoletes */
980 FOR_PROVIDES(p2, pp2, obs) /* and all matching providers of the obsoletes */
982 if (p2 == n) /* match ! */
988 if (!obs) /* continue if no match */
990 /* here we have 'p' with a matching provides/obsoletes combination
991 * thus flagging p as a valid update candidate for s
998 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
999 addrulesforsolvable(solv, pool->solvables + p, m);
1001 if (solv->noupdateprovide && solv->obsoletes && solv->obsoletes[n - solv->system->start])
1003 for (pp = solv->obsoletes_data + solv->obsoletes[n - solv->system->start]; (p = *pp++) != 0;)
1006 if (m && !MAPTST(m, p)) /* mark p for install if not already done */
1007 addrulesforsolvable(solv, pool->solvables + p, m);
1013 * add rule for update
1014 * (A|A1|A2|A3...) An = update candidates for A
1016 * s = (installed) solvable
1017 * m = 'addedmap', bit set if 'install' rule for solvable exists
1021 addupdaterule(Solver *solv, Solvable *s, Map *m, int allowdowngrade, int allowarchchange, int dontaddrule)
1023 /* system packages get a special upgrade allowed rule */
1024 Pool *pool = solv->pool;
1030 queueinit_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf));
1031 findupdatepackages(solv, s, &qs, m, allowdowngrade, allowarchchange);
1032 p = s - pool->solvables;
1033 if (dontaddrule) /* we consider update candidates but dont force them */
1039 if (qs.count == 0) /* no updates found */
1042 printf("new update rule: must keep %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1044 addrule(solv, p, 0); /* request 'install' of s */
1049 d = pool_queuetowhatprovides(pool, &qs); /* intern computed provider queue */
1051 r = addrule(solv, p, d); /* allow update of s */
1053 printf("new update rule ");
1060 /*-----------------------------------------------------------------*/
1067 * initial setup for all watches
1071 makewatches(Solver *solv)
1075 int nsolvables = solv->pool->nsolvables;
1077 xfree(solv->watches);
1078 /* lower half for removals, upper half for installs */
1079 solv->watches = (Id *)xcalloc(2 * nsolvables, sizeof(Id));
1081 /* do it reverse so rpm rules get triggered first */
1082 for (i = 1, r = solv->rules + solv->nrules - 1; i < solv->nrules; i++, r--)
1084 for (i = 1, r = solv->rules + 1; i < solv->nrules; i++, r++)
1087 if (!r->w1 /* rule is disabled */
1088 || !r->w2) /* rule is assertion */
1091 /* see addwatches(solv, r) */
1092 r->n1 = solv->watches[nsolvables + r->w1];
1093 solv->watches[nsolvables + r->w1] = r - solv->rules;
1095 r->n2 = solv->watches[nsolvables + r->w2];
1096 solv->watches[nsolvables + r->w2] = r - solv->rules;
1102 * add watches (for rule)
1106 addwatches(Solver *solv, Rule *r)
1108 int nsolvables = solv->pool->nsolvables;
1110 r->n1 = solv->watches[nsolvables + r->w1];
1111 solv->watches[nsolvables + r->w1] = r - solv->rules;
1113 r->n2 = solv->watches[nsolvables + r->w2];
1114 solv->watches[nsolvables + r->w2] = r - solv->rules;
1118 /*-----------------------------------------------------------------*/
1119 /* rule propagation */
1121 #define DECISIONMAP_TRUE(p) ((p) > 0 ? (decisionmap[p] > 0) : (decisionmap[-p] < 0))
1126 * propagate decision to all rules
1130 propagate(Solver *solv, int level)
1132 Pool *pool = solv->pool;
1137 Id *decisionmap = solv->decisionmap;
1138 Id *watches = solv->watches + pool->nsolvables;
1140 while (solv->propagate_index < solv->decisionq.count)
1142 /* negative because our watches trigger if literal goes FALSE */
1143 pkg = -solv->decisionq.elements[solv->propagate_index++];
1145 printf("popagate for decision %d level %d\n", -pkg, level);
1146 printruleelement(solv, 0, -pkg);
1148 for (rp = watches + pkg; *rp; rp = nrp)
1150 r = solv->rules + *rp;
1152 printf(" watch triggered ");
1165 /* if clause is TRUE, nothing to do */
1166 if (DECISIONMAP_TRUE(ow))
1171 /* not a binary clause, check if we need to move our watch */
1172 if (r->p && r->p != ow && !DECISIONMAP_TRUE(-r->p))
1175 for (dp = pool->whatprovidesdata + r->d; (p = *dp++) != 0;)
1176 if (p != ow && !DECISIONMAP_TRUE(-p))
1180 /* p is free to watch, move watch to p */
1183 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));
1185 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));
1199 watches[p] = r - solv->rules;
1203 /* unit clause found, set other watch to TRUE */
1204 if (DECISIONMAP_TRUE(-ow))
1205 return r; /* eek, a conflict! */
1211 decisionmap[ow] = level;
1213 decisionmap[-ow] = -level;
1214 queuepush(&solv->decisionq, ow);
1215 queuepush(&solv->decisionq_why, r - solv->rules);
1218 Solvable *s = pool->solvables + (ow > 0 ? ow : -ow);
1220 printf(" -> decided to install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1222 printf(" -> decided to conflict %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1227 return 0; /* all is well */
1231 /*-----------------------------------------------------------------*/
1240 analyze(Solver *solv, int level, Rule *c, int *pr, int *dr, int *why)
1242 Pool *pool = solv->pool;
1245 Map seen; /* global? */
1249 int learnt_why = solv->learnt_pool.count;
1250 Id *decisionmap = solv->decisionmap;
1254 if (pool->verbose) printf("ANALYZE at %d ----------------------\n", level);
1255 mapinit(&seen, pool->nsolvables);
1256 idx = solv->decisionq.count;
1260 queuepush(&solv->learnt_pool, c - solv->rules);
1261 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1272 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1274 vv = v > 0 ? v : -v;
1275 if (MAPTST(&seen, vv))
1277 l = solv->decisionmap[vv];
1284 for (j = 0; j < solv->decisionq.count; j++)
1285 if (solv->decisionq.elements[j] == v)
1287 if (j == solv->decisionq.count)
1289 queuepush(&rulq, -(j + 1));
1291 continue; /* initial setting */
1295 num++; /* need to do this one as well */
1300 printf("PUSH %d ", v);
1301 printruleelement(solv, 0, v);
1308 printf("num = %d\n", num);
1314 v = solv->decisionq.elements[--idx];
1315 vv = v > 0 ? v : -v;
1316 if (MAPTST(&seen, vv))
1319 c = solv->rules + solv->decisionq_why.elements[idx];
1327 else if (r.count == 1 && r.elements[0] < 0)
1328 *dr = r.elements[0];
1330 *dr = pool_queuetowhatprovides(pool, &r);
1333 printf("learned rule for level %d (am %d)\n", rlevel, level);
1334 printruleelement(solv, 0, -v);
1335 for (i = 0; i < r.count; i++)
1338 printruleelement(solv, 0, v);
1342 queuepush(&solv->learnt_pool, 0);
1344 for (i = learnt_why; solv->learnt_pool.elements[i]; i++)
1346 printf("learnt_why ");
1347 printrule(solv, solv->rules + solv->learnt_pool.elements[i]);
1358 * reset the solver decisions to right after the rpm rules
1362 reset_solver(Solver *solv)
1368 /* delete all learnt rules */
1369 solv->nrules = solv->learntrules;
1370 QUEUEEMPTY(&solv->learnt_why);
1371 QUEUEEMPTY(&solv->learnt_pool);
1373 /* redo all direct decision without the disabled rules */
1374 for (i = 0; i < solv->decisionq.count; i++)
1376 v = solv->decisionq.elements[i];
1377 solv->decisionmap[v > 0 ? v : -v] = 0;
1379 for (i = 0; i < solv->decisionq_why.count; i++)
1380 if (solv->decisionq_why.elements[i])
1384 v = solv->decisionq.elements[i];
1385 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1388 if (solv->pool->verbose)
1389 printf("decisions done reduced from %d to %d\n", solv->decisionq.count, i);
1391 solv->decisionq_why.count = i;
1392 solv->decisionq.count = i;
1393 solv->recommends_index = -1;
1394 if (i < solv->propagate_index)
1395 solv->propagate_index = i;
1396 /* make direct decisions from enabled unary rules */
1397 for (i = solv->jobrules, r = solv->rules + solv->jobrules; i < solv->nrules; i++, r++)
1399 if (!r->w1 || r->w2)
1405 queuepush(&solv->decisionq, v);
1406 queuepush(&solv->decisionq_why, r - solv->rules);
1407 solv->decisionmap[v > 0 ? v : -v] = v > 0 ? 1 : -1;
1409 if (solv->pool->verbose)
1410 printf("decisions after adding job and system rules: %d\n", solv->decisionq.count);
1411 /* recreate watches */
1417 * analyze_unsolvable_rule
1421 analyze_unsolvable_rule(Solver *solv, Rule *c, int disablerules)
1426 why = c - solv->rules;
1428 if (why >= solv->jobrules && why < solv->systemrules)
1430 if (why >= solv->systemrules && why < solv->learntrules)
1431 printf("SYSTEM %d ", why - solv->systemrules);
1432 if (solv->learntrules && why >= solv->learntrules)
1436 if (solv->learntrules && why >= solv->learntrules)
1438 for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++)
1439 analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], disablerules);
1442 if (why >= solv->jobrules && why < solv->learntrules)
1446 /* turn off rule for further analysis */
1450 if (solv->problems.count)
1452 for (i = solv->problems.count - 1; i >= 0; i--)
1453 if (solv->problems.elements[i] == 0)
1455 else if (solv->problems.elements[i] == why)
1458 queuepush(&solv->problems, why);
1464 * analyze_unsolvable
1468 analyze_unsolvable(Solver *solv, Rule *c, int disablerules)
1470 Pool *pool = solv->pool;
1471 Map seen; /* global? */
1474 Id *decisionmap = solv->decisionmap;
1477 printf("ANALYZE UNSOLVABLE ----------------------\n");
1479 mapinit(&seen, pool->nsolvables);
1480 analyze_unsolvable_rule(solv, c, disablerules);
1481 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1492 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1494 vv = v > 0 ? v : -v;
1495 l = solv->decisionmap[vv];
1500 idx = solv->decisionq.count;
1503 v = solv->decisionq.elements[--idx];
1504 vv = v > 0 ? v : -v;
1505 if (!MAPTST(&seen, vv))
1507 why = solv->decisionq_why.elements[idx];
1512 printruleelement(solv, 0, v);
1516 c = solv->rules + why;
1517 analyze_unsolvable_rule(solv, c, disablerules);
1518 dp = c->d ? pool->whatprovidesdata + c->d : 0;
1529 if (DECISIONMAP_TRUE(v)) /* the one true literal */
1531 vv = v > 0 ? v : -v;
1532 l = solv->decisionmap[vv];
1539 queuepush(&solv->problems, 0); /* mark end of this problem */
1543 printf("analyze_unsolvables done\n");
1548 /*-----------------------------------------------------------------*/
1549 /* Decision revert */
1553 * revert decision at level
1557 revert(Solver *solv, int level)
1560 while (solv->decisionq.count)
1562 v = solv->decisionq.elements[solv->decisionq.count - 1];
1563 vv = v > 0 ? v : -v;
1564 if (solv->decisionmap[vv] <= level && solv->decisionmap[vv] >= -level)
1567 printf("reverting decision %d at %d\n", v, solv->decisionmap[vv]);
1569 solv->decisionmap[vv] = 0;
1570 solv->decisionq.count--;
1571 solv->decisionq_why.count--;
1572 solv->propagate_index = solv->decisionq.count;
1574 solv->recommends_index = -1;
1583 watch2onhighest(Solver *solv, Rule *r)
1589 return; /* binary rule, both watches are set */
1590 dp = solv->pool->whatprovidesdata + r->d;
1591 while ((v = *dp++) != 0)
1593 l = solv->decisionmap[v < 0 ? -v : v];
1610 setpropagatelearn(Solver *solv, int level, Id decision, int disablerules)
1620 solv->decisionmap[decision] = level;
1622 solv->decisionmap[-decision] = -level;
1623 queuepush(&solv->decisionq, decision);
1624 queuepush(&solv->decisionq_why, 0);
1628 r = propagate(solv, level);
1633 analyze_unsolvable(solv, r, disablerules);
1638 printf("conflict with rule #%d\n", (int)(r - solv->rules));
1639 l = analyze(solv, level, r, &p, &d, &why);
1640 if (l >= level || l <= 0)
1642 printf("reverting decisions (level %d -> %d)\n", level, l);
1644 revert(solv, level);
1645 r = addrule(solv, p, d); /* p requires d */
1648 if (solv->learnt_why.count != (r - solv->rules) - solv->learntrules)
1650 printf("%d %d\n", solv->learnt_why.count, (int)(r - solv->rules) - solv->learntrules);
1653 queuepush(&solv->learnt_why, why);
1656 /* at least 2 literals, needs watches */
1657 watch2onhighest(solv, r);
1658 addwatches(solv, r);
1660 solv->decisionmap[p > 0 ? p : -p] = p > 0 ? level : -level;
1661 queuepush(&solv->decisionq, p);
1662 queuepush(&solv->decisionq_why, r - solv->rules);
1663 printf("decision: ");
1664 printruleelement(solv, 0, p);
1665 printf("new rule: ");
1671 /*-----------------------------------------------------------------*/
1672 /* Main solver interface */
1677 * create solver structure
1679 * pool: all available solvables
1680 * system: installed Solvables
1683 * Upon solving, rules are created to flag the Solvables
1684 * of the 'system' Source as installed.
1688 solver_create(Pool *pool, Source *system)
1691 solv = (Solver *)xcalloc(1, sizeof(Solver));
1693 solv->system = system;
1696 queueinit(&solv->decisionq);
1697 queueinit(&solv->decisionq_why);
1698 queueinit(&solv->problems);
1699 queueinit(&solv->learnt_why);
1700 queueinit(&solv->learnt_pool);
1702 mapinit(&solv->recommends, pool->nsolvables);
1703 mapinit(&solv->suggests, pool->nsolvables);
1704 solv->recommends_index = 0;
1706 solv->decisionmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
1707 solv->rules = (Rule *)xmalloc((solv->nrules + (RULES_BLOCK + 1)) * sizeof(Rule));
1708 memset(solv->rules, 0, sizeof(Rule));
1720 solver_free(Solver *solv)
1722 queuefree(&solv->decisionq);
1723 queuefree(&solv->decisionq_why);
1724 queuefree(&solv->learnt_why);
1725 queuefree(&solv->learnt_pool);
1726 mapfree(&solv->recommends);
1727 mapfree(&solv->suggests);
1728 xfree(solv->decisionmap);
1730 xfree(solv->watches);
1731 xfree(solv->weaksystemrules);
1732 xfree(solv->obsoletes);
1733 xfree(solv->obsoletes_data);
1741 * r->w1 was set to 0, now find proper value for w1
1745 reenablerule(Solver *solv, Rule *r)
1750 if (!r->w2) /* not a rule, but an assertion */
1760 r->w2 = r->d; /* mls: shouldn't this be r->w1 ? */
1764 /* put it on the first not-false literal */
1770 v = solv->pool->whatprovidesdata[r->d + i];
1778 l = solv->decisionmap[v > 0 ? v : -v];
1779 if (!l || (v < 0 && l < 0) || (v > 0 && l > 0))
1786 /*-------------------------------------------------------*/
1791 * all rules have been set up, not actually run the solver
1796 run_solver(Solver *solv, int disablerules, int doweak)
1804 Pool *pool = solv->pool;
1808 printf("number of rules: %d\n", solv->nrules);
1811 for (i = 0; i < solv->nrules; i++)
1813 printrule(solv, solv->rules + i);
1818 /* all new rules are learnt after this point */
1819 solv->learntrules = solv->nrules;
1820 /* crate watches lists */
1823 if (pool->verbose) printf("initial decisions: %d\n", solv->decisionq.count);
1825 /* start SAT algorithm */
1827 systemlevel = level + 1;
1828 if (pool->verbose) printf("solving...\n");
1839 if (pool->verbose) printf("propagating (%d %d)...\n", solv->propagate_index, solv->decisionq.count);
1840 if ((r = propagate(solv, level)) != 0)
1842 analyze_unsolvable(solv, r, disablerules);
1845 printf("UNSOLVABLE\n");
1855 if (level < systemlevel && solv->system->nsolvables)
1857 if (!solv->updatesystem)
1859 /* try to keep as many packages as possible */
1860 if (pool->verbose) printf("installing system packages\n");
1861 for (i = solv->system->start, n = 0; ; i++, n++)
1863 if (n == solv->system->nsolvables)
1865 if (i == solv->system->start + solv->system->nsolvables)
1866 i = solv->system->start;
1867 s = pool->solvables + i;
1868 if (solv->decisionmap[i] != 0)
1871 printf("system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1874 level = setpropagatelearn(solv, level, i, disablerules);
1877 printf("UNSOLVABLE\n");
1881 if (level <= olevel)
1885 if (solv->weaksystemrules)
1887 if (pool->verbose) printf("installing weak system packages\n");
1888 for (i = solv->system->start, n = 0; ; i++, n++)
1890 if (n == solv->system->nsolvables)
1892 if (solv->decisionmap[i] > 0 || (solv->decisionmap[i] < 0 && solv->weaksystemrules[i - solv->system->start] == 0))
1895 if (solv->decisionmap[i] == 0)
1897 if (solv->weaksystemrules[i - solv->system->start])
1899 dp = pool->whatprovidesdata + solv->weaksystemrules[i - solv->system->start];
1900 while ((p = *dp++) != 0)
1902 if (solv->decisionmap[p] > 0)
1904 if (solv->decisionmap[p] == 0)
1908 continue; /* rule is already true */
1914 prune_to_recommended(solv, &dq);
1916 prune_best_version_arch(pool, &dq);
1918 s = pool->solvables + dq.elements[0];
1919 printf("weak system installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
1922 level = setpropagatelearn(solv, level, dq.elements[0], disablerules);
1925 printf("UNSOLVABLE\n");
1929 if (level <= olevel)
1935 if (n != solv->system->nsolvables)
1938 systemlevel = level;
1945 if (pool->verbose) printf("deciding unresolved rules\n");
1946 for (i = 1, n = 1; ; i++, n++)
1948 if (n == solv->nrules)
1950 if (i == solv->nrules)
1952 r = solv->rules + i;
1958 /* binary or unary rule */
1959 /* need two positive undecided literals */
1960 if (r->p < 0 || r->w2 <= 0)
1962 if (solv->decisionmap[r->p] || solv->decisionmap[r->w2])
1964 queuepush(&dq, r->p);
1965 queuepush(&dq, r->w2);
1970 * all negative literals are installed
1971 * no positive literal is installed
1972 * i.e. the rule is not fulfilled and we
1973 * just need to decide on the positive literals
1977 if (solv->decisionmap[-r->p] <= 0)
1982 if (solv->decisionmap[r->p] > 0)
1984 if (solv->decisionmap[r->p] == 0)
1985 queuepush(&dq, r->p);
1987 dp = pool->whatprovidesdata + r->d;
1988 while ((p = *dp++) != 0)
1992 if (solv->decisionmap[-p] <= 0)
1997 if (solv->decisionmap[p] > 0)
1999 if (solv->decisionmap[p] == 0)
2008 /* cannot happen as this means that
2009 * the rule is unit */
2013 prune_to_recommended(solv, &dq);
2015 prune_best_version_arch(pool, &dq);
2016 p = dq.elements[dq.count - 1];
2017 s = pool->solvables + p;
2019 printf("installing %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2022 level = setpropagatelearn(solv, level, p, disablerules);
2025 printf("UNSOLVABLE\n");
2029 if (level < systemlevel)
2031 if (level <= olevel)
2033 } /* for(), decide */
2035 if (n != solv->nrules) /* continue if level < systemlevel */
2038 if (doweak && !solv->problems.count)
2042 if (pool->verbose) printf("installing recommended packages\n");
2044 for (i = 1; i < pool->nsolvables; i++)
2046 if (solv->decisionmap[i] < 0)
2048 if (solv->decisionmap[i] > 0)
2050 Id *recp, rec, *pp, p;
2051 s = pool->solvables + i;
2052 /* installed, check for recommends */
2053 /* XXX need to special case AND ? */
2054 if ((recp = s->recommends) != 0)
2056 while ((rec = *recp++) != 0)
2059 FOR_PROVIDES(p, pp, rec)
2061 if (solv->decisionmap[p] > 0)
2066 else if (solv->decisionmap[p] == 0)
2067 queuepushunique(&dq, p);
2075 s = pool->solvables + i;
2076 if (!s->supplements && !s->freshens)
2078 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
2080 if (pool->id2arch && (s->arch > pool->lastarch || !pool->id2arch[s->arch]))
2082 if ((supp = s->supplements) != 0)
2084 while ((sup = *supp++) != 0)
2085 if (dep_fulfilled(solv, sup))
2090 if ((supp = s->freshens) != 0)
2092 while ((sup = *supp++) != 0)
2093 if (dep_fulfilled(solv, sup))
2098 queuepushunique(&dq, i);
2103 prune_best_version_arch(pool, &dq);
2104 p = dq.elements[dq.count - 1];
2105 s = pool->solvables + p;
2107 printf("installing recommended %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2109 level = setpropagatelearn(solv, level, p, 0);
2124 refine_suggestion(Solver *solv, Id *problem, Id sug, Queue *refined)
2132 printf("refine_suggestion start\n");
2133 queueinit(&disabled);
2134 QUEUEEMPTY(refined);
2135 queuepush(refined, sug);
2137 /* re-enable all rules but rule "sug" of the problem */
2138 for (i = 0; problem[i]; i++)
2140 if (problem[i] == sug)
2142 r = solv->rules + problem[i];
2147 reenablerule(solv, r);
2151 revert(solv, 1); /* XXX move to reset_solver? */
2153 QUEUEEMPTY(&solv->problems);
2154 run_solver(solv, 0, 0);
2155 if (!solv->problems.count)
2157 printf("no more problems!\n");
2159 printdecisions(solv);
2161 break; /* great, no more problems */
2163 disabledcnt = disabled.count;
2164 for (i = 0; i < solv->problems.elements[i]; i++)
2166 /* ignore solutions in refined */
2167 v = solv->problems.elements[i];
2168 for (j = 0; problem[j]; j++)
2169 if (problem[j] != sug && problem[j] == v)
2173 queuepush(&disabled, v);
2175 if (disabled.count == disabledcnt)
2177 /* no solution found, this was an invalid suggestion! */
2178 printf("no solution found!\n");
2179 for (i = 0; i < refined->count; i++)
2180 reenablerule(solv, solv->rules + refined->elements[i]);
2184 if (disabled.count == disabledcnt + 1)
2186 /* just one solution, add it to refined list */
2187 queuepush(refined, disabled.elements[disabledcnt]);
2191 printf("############################################## more than one solution found.\n");
2193 for (i = 0; i < solv->problems.elements[i]; i++)
2195 printrule(solv, solv->rules + solv->problems.elements[i]);
2197 printf("##############################################\n");
2199 /* more than one solution */
2200 /* for now return */
2202 for (i = disabledcnt; i < disabled.count; i++)
2204 r = solv->rules + disabled.elements[i];;
2213 /* enable refined rules again */
2214 for (i = 0; i < disabled.count; i++)
2215 reenablerule(solv, solv->rules + disabled.elements[i]);
2216 /* disable problem rules again so that we are in the same state as before */
2217 for (i = 0; problem[i]; i++)
2219 r = solv->rules + problem[i];
2222 printf("refine_suggestion end\n");
2231 id2rc(Solver *solv, Id id)
2234 if (solv->rc_output != 2)
2236 evr = id2str(solv->pool, id);
2237 if (*evr < '0' || *evr > '9')
2239 while (*evr >= '0' && *evr <= '9')
2247 printdecisions(Solver *solv)
2249 Pool *pool = solv->pool;
2250 Id p, *obsoletesmap;
2254 obsoletesmap = (Id *)xcalloc(pool->nsolvables, sizeof(Id));
2255 for (i = 0; i < solv->decisionq.count; i++)
2260 n = solv->decisionq.elements[i];
2263 if (n >= solv->system->start && n < solv->system->start + solv->system->nsolvables)
2265 s = pool->solvables + n;
2266 if ((obsp = s->obsoletes) != 0)
2267 while ((obs = *obsp++) != 0)
2268 FOR_PROVIDES(p, pp, obs)
2270 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2272 obsoletesmap[p] = n;
2276 FOR_PROVIDES(p, pp, s->name)
2277 if (s->name == pool->solvables[p].name)
2279 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2281 obsoletesmap[p] = n;
2287 if (solv->rc_output)
2288 printf(">!> Solution #1:\n");
2290 int installs = 0, uninstalls = 0, upgrades = 0;
2292 /* print solvables to be erased */
2294 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2296 if (solv->decisionmap[i] > 0)
2298 if (obsoletesmap[i])
2300 s = pool->solvables + i;
2301 if (solv->rc_output == 2)
2302 printf(">!> remove %s-%s%s\n", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2303 else if (solv->rc_output)
2304 printf(">!> remove %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2306 printf("erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2310 /* print solvables to be installed */
2312 for (i = 0; i < solv->decisionq.count; i++)
2315 p = solv->decisionq.elements[i];
2318 if (p >= solv->system->start && p < solv->system->start + solv->system->nsolvables)
2320 s = pool->solvables + p;
2322 if (!obsoletesmap[p])
2324 if (solv->rc_output)
2326 printf("install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2327 if (solv->rc_output != 2)
2328 printf(".%s", id2str(pool, s->arch));
2331 else if (!solv->rc_output)
2333 printf("update %s-%s.%s (obsoletes", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2334 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2336 if (obsoletesmap[j] != p)
2338 s = pool->solvables + j;
2339 printf(" %s-%s.%s", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2346 Solvable *f, *fn = 0;
2347 for (j = solv->system->start; j < solv->system->start + solv->system->nsolvables; j++)
2349 if (obsoletesmap[j] != p)
2351 f = pool->solvables + j;
2352 if (fn || f->name != s->name)
2354 if (solv->rc_output == 2)
2355 printf(">!> remove %s-%s%s\n", id2str(pool, f->name), id2rc(solv, f->evr), id2str(pool, f->evr));
2356 else if (solv->rc_output)
2357 printf(">!> remove %s-%s.%s\n", id2str(pool, f->name), id2str(pool, f->evr), id2str(pool, f->arch));
2365 printf(">!> install %s-%s%s", id2str(pool, s->name), id2rc(solv, s->evr), id2str(pool, s->evr));
2366 if (solv->rc_output != 2)
2367 printf(".%s", id2str(pool, s->arch));
2372 if (solv->rc_output == 2)
2373 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));
2375 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));
2379 if (solv->rc_output)
2381 Source *source = pool_source(pool, s);
2382 if (source && strcmp(source_name(source), "locales"))
2383 printf("[%s]", source_name(source));
2388 if (solv->rc_output)
2389 printf(">!> installs=%d, upgrades=%d, uninstalls=%d\n", installs, upgrades, uninstalls);
2391 xfree(obsoletesmap);
2395 create_obsolete_index(Solver *solv)
2397 Pool *pool = solv->pool;
2399 Source *system = solv->system;
2400 Id p, *pp, obs, *obsp, *obsoletes, *obsoletes_data;
2403 /* create reverse obsoletes map for system solvables */
2404 solv->obsoletes = obsoletes = xcalloc(system->nsolvables, sizeof(Id));
2405 for (i = 1; i < pool->nsolvables; i++)
2407 s = pool->solvables + i;
2408 if ((obsp = s->obsoletes) == 0)
2410 while ((obs = *obsp++) != 0)
2411 FOR_PROVIDES(p, pp, obs)
2413 if (p < system->start || p >= system->start + system->nsolvables)
2415 if (pool->solvables[p].name == s->name)
2417 obsoletes[p - system->start]++;
2421 for (i = 0; i < system->nsolvables; i++)
2424 n += obsoletes[i] + 1;
2427 solv->obsoletes_data = obsoletes_data = xcalloc(n + 1, sizeof(Id));
2428 if (pool->verbose) printf("obsoletes data: %d entries\n", n + 1);
2429 for (i = pool->nsolvables - 1; i > 0; i--)
2431 s = pool->solvables + i;
2432 if ((obsp = s->obsoletes) == 0)
2434 while ((obs = *obsp++) != 0)
2435 FOR_PROVIDES(p, pp, obs)
2437 if (p < system->start || p >= system->start + system->nsolvables)
2439 if (pool->solvables[p].name == s->name)
2442 if (obsoletes_data[obsoletes[p]] != i)
2443 obsoletes_data[--obsoletes[p]] = i;
2448 /*-----------------------------------------------------------------*/
2458 solve(Solver *solv, Queue *job)
2460 Pool *pool = solv->pool;
2462 Map addedmap; /* '1' == have rule for solvable */
2463 Map noupdaterule; /* '1' == don't update (scheduled for removal) */
2464 Id how, what, p, *pp, d;
2470 * create basic rule set of all involved packages
2475 mapinit(&addedmap, pool->nsolvables);
2476 mapinit(&noupdaterule, pool->nsolvables);
2481 * create rules for installed solvables -> keep them installed
2482 * so called: rpm rules
2486 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2487 addrulesforsolvable(solv, pool->solvables + i, &addedmap);
2490 * create install rules
2492 * two passes, as we want to keep the rpm rules distinct from the job rules
2496 if (solv->noupdateprovide && solv->system->nsolvables)
2497 create_obsolete_index(solv);
2501 * process job rules for solvables
2504 for (i = 0; i < job->count; i += 2)
2506 how = job->elements[i];
2507 what = job->elements[i + 1];
2511 case SOLVER_INSTALL_SOLVABLE:
2512 addrulesforsolvable(solv, pool->solvables + what, &addedmap);
2514 case SOLVER_INSTALL_SOLVABLE_NAME:
2515 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2517 FOR_PROVIDES(p, pp, what)
2519 /* if by name, ensure that the name matches */
2520 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2522 addrulesforsolvable(solv, pool->solvables + p, &addedmap);
2525 case SOLVER_INSTALL_SOLVABLE_UPDATE:
2526 /* dont allow downgrade */
2527 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 1);
2533 * if unstalls are disallowed, add update rules for every
2534 * installed solvables in the hope to circumvent uninstall
2540 if (!solv->allowuninstall)
2542 /* add update rule for every installed package */
2543 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2544 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 1);
2546 #else /* this is just to add the needed rpm rules to our set */
2547 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2548 addupdaterule(solv, pool->solvables + i, &addedmap, 1, 1, 1);
2551 addrulesforsupplements(solv, &addedmap);
2556 * unify existing rules before going over all job rules
2560 unifyrules(solv); /* remove duplicate rpm rules */
2563 * at this point the system is always solvable,
2564 * as an empty system (remove all packages) is a valid solution
2566 if (pool->verbose) printf("decisions based on rpms: %d\n", solv->decisionq.count);
2569 * now add all job rules
2572 solv->jobrules = solv->nrules;
2574 for (i = 0; i < job->count; i += 2)
2576 how = job->elements[i];
2577 what = job->elements[i + 1];
2580 case SOLVER_INSTALL_SOLVABLE: /* install specific solvable */
2581 if (solv->rc_output) {
2582 Solvable *s = pool->solvables + what;
2583 printf(">!> Installing %s from channel %s\n", id2str(pool, s->name), source_name(pool_source(pool, s)));
2585 addrule(solv, what, 0); /* install by Id */
2587 case SOLVER_ERASE_SOLVABLE:
2588 addrule(solv, -what, 0); /* remove by Id */
2589 MAPSET(&noupdaterule, what);
2591 case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */
2592 case SOLVER_INSTALL_SOLVABLE_PROVIDES:
2594 FOR_PROVIDES(p, pp, what) /* check all providers */
2596 /* if by name, ensure that the name matches */
2597 if (how == SOLVER_INSTALL_SOLVABLE_NAME && pool->solvables[p].name != what)
2601 if (!q.count) { /* no provider found -> abort */
2602 fprintf(stderr, "Nothing provides '%s'\n", id2str(pool, what));
2603 /* XXX make this a problem! */
2608 p = queueshift(&q); /* get first provider */
2610 d = 0; /* single provider ? -> make assertion */
2612 d = pool_queuetowhatprovides(pool, &q); /* get all providers */
2613 addrule(solv, p, d); /* add 'requires' rule */
2615 case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */
2616 case SOLVER_ERASE_SOLVABLE_PROVIDES:
2617 FOR_PROVIDES(p, pp, what)
2619 /* if by name, ensure that the name matches */
2620 if (how == SOLVER_ERASE_SOLVABLE_NAME && pool->solvables[p].name != what)
2623 addrule(solv, -p, 0); /* add 'remove' rule */
2624 MAPSET(&noupdaterule, p);
2627 case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */
2628 addupdaterule(solv, pool->solvables + what, &addedmap, 0, 0, 0);
2633 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2636 * now add policy rules
2640 solv->systemrules = solv->nrules;
2643 * create rules for updating installed solvables
2649 if (!solv->allowuninstall)
2650 { /* loop over all installed solvables */
2651 for (i = solv->system->start; i < solv->system->start + solv->system->nsolvables; i++)
2653 if (!MAPTST(&noupdaterule, i)) /* if not marked as 'noupdate' */
2654 addupdaterule(solv, pool->solvables + i, &addedmap, solv->allowdowngrade, solv->allowarchchange, 0);
2656 addrule(solv, 0, 0); /* place holder */
2658 /* consistency check: we added a rule for _every_ system solvable */
2659 if (solv->nrules - solv->systemrules != solv->system->nsolvables)
2663 if (pool->verbose) printf("problems so far: %d\n", solv->problems.count);
2665 /* create special weak system rules */
2666 if (solv->system->nsolvables)
2668 solv->weaksystemrules = xcalloc(solv->system->nsolvables, sizeof(Id));
2669 for (i = 0; i < solv->system->nsolvables; i++)
2671 findupdatepackages(solv, pool->solvables + solv->system->start + i, &q, (Map *)0, 1, 1);
2673 solv->weaksystemrules[i] = pool_queuetowhatprovides(pool, &q);
2677 /* free unneeded memory */
2679 mapfree(&noupdaterule);
2687 run_solver(solv, 1, 1);
2691 * print solver result
2695 if (pool->verbose) printf("-------------------------------------------------------------\n");
2697 if (solv->problems.count)
2707 clonequeue(&problems, &solv->problems);
2708 queueinit(&solution);
2709 printf("Encountered problems! Here are the solutions:\n");
2710 problem = problems.elements;
2711 for (i = 0; i < problems.count; i++)
2713 Id v = problems.elements[i];
2716 printf("====================================\n");
2717 problem = problems.elements + i + 1;
2720 refine_suggestion(solv, problem, v, &solution);
2721 for (j = 0; j < solution.count; j++)
2723 r = solv->rules + solution.elements[j];
2724 why = solution.elements[j];
2728 if (why >= solv->jobrules && why < solv->systemrules)
2730 /* do a sloppy job of analyzing the job rule */
2733 s = pool->solvables + r->p;
2734 printf("- do not install %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2738 s = pool->solvables - r->p;
2739 printf("- do not erase %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2742 else if (why >= solv->systemrules && why < solv->learntrules)
2745 s = pool->solvables + solv->system->start + (why - solv->systemrules);
2746 if (solv->weaksystemrules && solv->weaksystemrules[why - solv->systemrules])
2748 Id *dp = pool->whatprovidesdata + solv->weaksystemrules[why - solv->systemrules];
2750 if (solv->decisionmap[*dp] > 0)
2752 sd = pool->solvables + *dp;
2758 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));
2762 printf("- allow deinstallation of %s-%s.%s\n", id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
2770 printf("------------------------------------\n");
2775 printdecisions(solv);