diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cleandeps.c | 7 | ||||
-rw-r--r-- | src/dirpool.c | 2 | ||||
-rw-r--r-- | src/order.c | 1 | ||||
-rw-r--r-- | src/policy.c | 120 | ||||
-rw-r--r-- | src/policy.h | 1 | ||||
-rw-r--r-- | src/pool.c | 1 | ||||
-rw-r--r-- | src/problems.c | 18 | ||||
-rw-r--r-- | src/repopage.c | 1 | ||||
-rw-r--r-- | src/rules.c | 161 | ||||
-rw-r--r-- | src/rules.h | 6 | ||||
-rw-r--r-- | src/solver.c | 178 | ||||
-rw-r--r-- | src/solver.h | 12 | ||||
-rw-r--r-- | src/solverdebug.c | 2 |
13 files changed, 292 insertions, 218 deletions
diff --git a/src/cleandeps.c b/src/cleandeps.c index 1da28f6..8ef6fd3 100644 --- a/src/cleandeps.c +++ b/src/cleandeps.c @@ -748,7 +748,6 @@ solver_createcleandepsmap(Solver *solv, Map *cleandepsmap, int unneeded) continue; if (strncmp(pool_id2str(pool, s->name), "pattern:", 8) != 0) continue; - dp = s->repo->idarraydata + s->requires; for (dp = s->repo->idarraydata + s->requires; *dp; dp++) FOR_PROVIDES(p, pp, *dp) if (pool->solvables[p].repo == installed) @@ -1368,11 +1367,11 @@ solver_check_cleandeps_mistakes(Solver *solv) if (!r->p || r == fr || cleandeps_rule_is_true(solv, r)) { /* update rule is true, check best rules */ - if (!solv->bestrules_pkg) + if (!solv->bestrules_info) continue; nj = solv->bestrules_end - solv->bestrules; - for (j = 0; j < nj; j++) - if (solv->bestrules_pkg[j] == i) + for (j = solv->bestrules_up - solv->bestrules; j < nj; j++) + if (solv->bestrules_info[j] == i) { r = solv->rules + solv->bestrules + j; if (!cleandeps_rule_is_true(solv, r)) diff --git a/src/dirpool.c b/src/dirpool.c index afb26ea..bed9435 100644 --- a/src/dirpool.c +++ b/src/dirpool.c @@ -85,7 +85,7 @@ dirpool_make_dirtraverse(Dirpool *dp) return; dp->dirs = solv_extend_resize(dp->dirs, dp->ndirs, sizeof(Id), DIR_BLOCK); dirtraverse = solv_calloc_block(dp->ndirs, sizeof(Id), DIR_BLOCK); - for (parent = 0, i = 0; i < dp->ndirs; i++) + for (i = 0; i < dp->ndirs; i++) { if (dp->dirs[i] > 0) continue; diff --git a/src/order.c b/src/order.c index c0cc07f..c45a9a2 100644 --- a/src/order.c +++ b/src/order.c @@ -1066,7 +1066,6 @@ transaction_order(Transaction *trans, int flags) #if 0 printf("do %s [%d]\n", pool_solvid2str(pool, te->p), temedianr[i]); #endif - s = pool->solvables + te->p; for (j = te->edges; od.invedgedata[j]; j++) { struct s_TransactionElement *te2 = od.tes + od.invedgedata[j]; diff --git a/src/policy.c b/src/policy.c index 191327a..45c7357 100644 --- a/src/policy.c +++ b/src/policy.c @@ -454,86 +454,18 @@ prefer_suggested(Solver *solv, Queue *plist) } static int -sort_by_favorq_cmp(const void *ap, const void *bp, void *dp) +sort_by_favor_cmp(const void *ap, const void *bp, void *dp) { const Id *a = ap, *b = bp, *d = dp; return d[b[0]] - d[a[0]]; } -static void -sort_by_favorq(Queue *favorq, Id *el, int cnt) -{ - int i; - /* map to offsets into favorq */ - for (i = 0; i < cnt; i++) - { - Id p = el[i]; - /* lookup p in sorted favorq */ - int med = 0, low = 0; - int high = favorq->count / 2; - while (low != high) - { - med = (low + high) / 2; - Id pp = favorq->elements[2 * med]; - if (pp < p) - low = med; - else if (pp > p) - high = med; - else - break; - } - while(med && favorq->elements[2 * med - 2] == p) - med--; - if (favorq->elements[2 * med] == p) - el[i] = 2 * med + 1; - else - el[i] = 0; /* hmm */ - } - /* sort by position */ - solv_sort(el, cnt, sizeof(Id), sort_by_favorq_cmp, favorq->elements); - /* map back */ - for (i = 0; i < cnt; i++) - if (el[i]) - el[i] = favorq->elements[el[i] - 1]; -} - /* bring favored packages to front and disfavored packages to back */ void policy_prefer_favored(Solver *solv, Queue *plist) { - int i, fav, disfav, count; - if (!solv->favormap.size) - return; - for (i = fav = disfav = 0, count = plist->count; i < count; i++) - { - Id p = plist->elements[i]; - if (!MAPTST(&solv->favormap, p)) - continue; - if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p)) - { - /* disfavored package. bring to back */ - if (i < plist->count - 1) - { - memmove(plist->elements + i, plist->elements + i + 1, (plist->count - 1 - i) * sizeof(Id)); - plist->elements[plist->count - 1] = p; - } - i--; - count--; - disfav++; - } - else - { - /* favored package. bring to front */ - if (i > fav) - memmove(plist->elements + fav + 1, plist->elements + fav, (i - fav) * sizeof(Id)); - plist->elements[fav++] = p; - } - } - /* if we have multiple favored/disfavored packages, sort by favorq index */ - if (fav > 1) - sort_by_favorq(solv->favorq, plist->elements, fav); - if (disfav > 1) - sort_by_favorq(solv->favorq, plist->elements + plist->count - disfav, disfav); + if (solv->favormap && plist->count > 1) + solv_sort(plist->elements, plist->count, sizeof(Id), sort_by_favor_cmp, solv->favormap); } /* @@ -1300,6 +1232,37 @@ urpm_reorder(Solver *solv, Queue *plist) queue_truncate(plist, count); } +/* support multiple favor groups by calling policy_filter_unwanted on + * each of them and combining the result */ +static void +policy_filter_unwanted_favored(Solver *solv, Queue *plist, int mode) +{ + int i, j, f; + Queue qin, qprune; + queue_init_clone(&qin, plist); + queue_empty(plist); + /* sort by favor group */ + solv_sort(qin.elements, qin.count, sizeof(Id), sort_by_favor_cmp, solv->favormap); + /* go over groups */ + queue_init(&qprune); + for (i = 0; i < qin.count; i = j) + { + /* find end of group */ + f = solv->favormap[qin.elements[i]]; + for (j = i + 1; j < qin.count; j++) + if (solv->favormap[qin.elements[j]] != f) + break; + /* prune this group */ + queue_empty(&qprune); + queue_insertn(&qprune, 0, j, qin.elements); + policy_filter_unwanted(solv, &qprune, mode | POLICY_MODE_FAVOR_REC); + for (i = 0; i < qprune.count; i++) + if (solv->favormap[qprune.elements[i]] == f) + queue_push(plist, qprune.elements[i]); + } + queue_free(&qprune); + queue_free(&qin); +} /* * POLICY_MODE_CHOOSE: default, do all pruning steps @@ -1321,6 +1284,21 @@ policy_filter_unwanted(Solver *solv, Queue *plist, int mode) policy_prefer_favored(solv, plist); return; } + if (mode & POLICY_MODE_FAVOR_REC) + mode ^= POLICY_MODE_FAVOR_REC; + else if (solv->favormap && plist->count > 1) + { + /* check if we have multiple favor groups */ + int i, f = solv->favormap[plist->elements[0]]; + for (i = 1; i < plist->count; i++) + if (solv->favormap[plist->elements[i]] != f) + break; + if (i < plist->count) + { + policy_filter_unwanted_favored(solv, plist, mode); + return; + } + } if (plist->count > 1) { if (mode != POLICY_MODE_SUGGEST) diff --git a/src/policy.h b/src/policy.h index 68f4db9..3ae1005 100644 --- a/src/policy.h +++ b/src/policy.h @@ -21,6 +21,7 @@ extern "C" { #define POLICY_MODE_SUGGEST 2 #define POLICY_MODE_CHOOSE_NOREORDER 3 /* internal, do not use */ #define POLICY_MODE_SUPPLEMENT 4 /* internal, do not use */ +#define POLICY_MODE_FAVOR_REC (1 << 30) /* internal, do not use */ #define POLICY_ILLEGAL_DOWNGRADE 1 @@ -1536,6 +1536,7 @@ pool_debug(Pool *pool, int type, const char *format, ...) vprintf(format, args); else vfprintf(stderr, format, args); + va_end(args); return; } vsnprintf(buf, sizeof(buf), format, args); diff --git a/src/problems.c b/src/problems.c index 2b5cefd..6f2ad4b 100644 --- a/src/problems.c +++ b/src/problems.c @@ -64,12 +64,12 @@ solver_disableproblem(Solver *solv, Id v) } v = -(v + 1); jp = solv->ruletojob.elements; - if (solv->bestrules_pkg) + if (solv->bestrules_info) { int ni = solv->bestrules_up - solv->bestrules; for (i = 0; i < ni; i++) { - int j = solv->bestrules_pkg[i]; + int j = solv->bestrules_info[i]; if (j < 0 && jp[-j - solv->jobrules] == v) solver_disablerule(solv, solv->rules + solv->bestrules + i); } @@ -131,12 +131,12 @@ solver_enableproblem(Solver *solv, Id v) } v = -(v + 1); jp = solv->ruletojob.elements; - if (solv->bestrules_pkg) + if (solv->bestrules_info) { int ni = solv->bestrules_up - solv->bestrules; for (i = 0; i < ni; i++) { - int j = solv->bestrules_pkg[i]; + int j = solv->bestrules_info[i]; if (j < 0 && jp[-j - solv->jobrules] == v) solver_enablerule(solv, solv->rules + solv->bestrules + i); } @@ -155,8 +155,8 @@ solver_ruletoproblem(Solver *solv, Id rid) { if (rid >= solv->jobrules && rid < solv->jobrules_end) rid = -(solv->ruletojob.elements[rid - solv->jobrules] + 1); - else if (rid >= solv->bestrules && rid < solv->bestrules_up && solv->bestrules_pkg[rid - solv->bestrules] < 0) - rid = -(solv->ruletojob.elements[-solv->bestrules_pkg[rid - solv->bestrules] - solv->jobrules] + 1); + else if (rid >= solv->bestrules && rid < solv->bestrules_up && solv->bestrules_info[rid - solv->bestrules] < 0) + rid = -(solv->ruletojob.elements[-solv->bestrules_info[rid - solv->bestrules] - solv->jobrules] + 1); else if (rid > solv->infarchrules && rid < solv->infarchrules_end) { Pool *pool = solv->pool; @@ -252,13 +252,13 @@ solver_autouninstall(Solver *solv, int start) continue; if (pool->considered && !MAPTST(pool->considered, p)) continue; /* do not uninstalled disabled packages */ - if (solv->bestrules_pkg && solv->bestrules_end > solv->bestrules) + if (solv->bestrules_info && solv->bestrules_end > solv->bestrules) { int j; for (j = start + 1; j < solv->problems.count - 1; j++) { Id vv = solv->problems.elements[j]; - if (vv >= solv->bestrules && vv < solv->bestrules_end && solv->bestrules_pkg[vv - solv->bestrules] == p) + if (vv >= solv->bestrules && vv < solv->bestrules_end && solv->bestrules_info[vv - solv->bestrules] == p) break; } if (j < solv->problems.count - 1) @@ -678,7 +678,7 @@ convertsolution(Solver *solv, Id why, Queue *solutionq) if (p > 0 && solv->decisionmap[p] > 0) return; /* false alarm */ /* check update/feature rule */ - p = solv->bestrules_pkg[why - solv->bestrules]; + p = solv->bestrules_info[why - solv->bestrules]; if (p < 0) { /* install job */ diff --git a/src/repopage.c b/src/repopage.c index 2b7a863..85d53eb 100644 --- a/src/repopage.c +++ b/src/repopage.c @@ -399,7 +399,6 @@ match_done: litlen -= 32; } } - litofs = 0; } return oo; } diff --git a/src/rules.c b/src/rules.c index df32341..b6cd582 100644 --- a/src/rules.c +++ b/src/rules.c @@ -1463,12 +1463,12 @@ disableupdaterule(Solver *solv, Id p) r = solv->rules + solv->featurerules + (p - solv->installed->start); if (r->p && r->d >= 0) solver_disablerule(solv, r); - if (solv->bestrules_pkg) + if (solv->bestrules_info) { int i, ni; ni = solv->bestrules_end - solv->bestrules; for (i = solv->bestrules_up - solv->bestrules; i < ni; i++) - if (solv->bestrules_pkg[i] == p) + if (solv->bestrules_info[i] == p) solver_disablerule(solv, solv->rules + solv->bestrules + i); } } @@ -1506,12 +1506,12 @@ reenableupdaterule(Solver *solv, Id p) } } } - if (solv->bestrules_pkg) + if (solv->bestrules_info) { int i, ni; ni = solv->bestrules_end - solv->bestrules; for (i = solv->bestrules_up - solv->bestrules; i < ni; i++) - if (solv->bestrules_pkg[i] == p) + if (solv->bestrules_info[i] == p) solver_enablerule(solv, solv->rules + solv->bestrules + i); } } @@ -1674,11 +1674,15 @@ solver_addinfarchrules(Solver *solv, Map *addedmap) } if (installed && pool->solvables[p].repo == installed && !haveinstalled) continue; /* installed package not in lock-step */ + if (lsq.count < 2) + solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0); + else + solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, &lsq)); } - if (lsq.count < 2) - solver_addrule(solv, -p, lsq.count ? lsq.elements[0] : 0, 0); else - solver_addrule(solv, -p, 0, pool_queuetowhatprovides(pool, &lsq)); + { + solver_addrule(solv, -p, 0, 0); + } } } queue_free(&lsq); @@ -2126,7 +2130,13 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) if ((set & SOLVER_SETARCH) != 0 && solv->infarchrules != solv->infarchrules_end) { if (select == SOLVER_SOLVABLE) - queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name); + { + for (i = solv->infarchrules; i < solv->infarchrules_end; i++) + if (solv->rules[i].p == -what) + break; + if (i < solv->infarchrules_end) + queue_push2(q, DISABLE_INFARCH, pool->solvables[what].name); + } else { int qcnt = q->count; @@ -2140,8 +2150,12 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) if (q->elements[i + 1] == s->name) break; if (i < q->count) - continue; - queue_push2(q, DISABLE_INFARCH, s->name); + continue; /* already have that DISABLE_INFARCH element */ + for (i = solv->infarchrules; i < solv->infarchrules_end; i++) + if (solv->rules[i].p == -p) + break; + if (i < solv->infarchrules_end) + queue_push2(q, DISABLE_INFARCH, s->name); } } } @@ -2719,8 +2733,8 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) } if (rid >= solv->bestrules && rid < solv->bestrules_end) { - if (fromp && solv->bestrules_pkg[rid - solv->bestrules] > 0) - *fromp = solv->bestrules_pkg[rid - solv->bestrules]; + if (fromp && solv->bestrules_info[rid - solv->bestrules] > 0) + *fromp = solv->bestrules_info[rid - solv->bestrules]; return SOLVER_RULE_BEST; } if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end) @@ -2740,13 +2754,11 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) return SOLVER_RULE_YUMOBS; } if (rid >= solv->choicerules && rid < solv->choicerules_end) - { - return SOLVER_RULE_CHOICE; - } + return SOLVER_RULE_CHOICE; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return SOLVER_RULE_RECOMMENDS; if (rid >= solv->learntrules) - { - return SOLVER_RULE_LEARNT; - } + return SOLVER_RULE_LEARNT; return SOLVER_RULE_UNKNOWN; } @@ -2773,6 +2785,8 @@ solver_ruleclass(Solver *solv, Id rid) return SOLVER_RULE_YUMOBS; if (rid >= solv->choicerules && rid < solv->choicerules_end) return SOLVER_RULE_CHOICE; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return SOLVER_RULE_RECOMMENDS; if (rid >= solv->learntrules && rid < solv->nrules) return SOLVER_RULE_LEARNT; return SOLVER_RULE_UNKNOWN; @@ -2834,7 +2848,9 @@ Id solver_rule2pkgrule(Solver *solv, Id rid) { if (rid >= solv->choicerules && rid < solv->choicerules_end) - return solv->choicerules_ref[rid - solv->choicerules]; + return solv->choicerules_info[rid - solv->choicerules]; + if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end) + return solv->recommendsrules_info[rid - solv->recommendsrules]; return 0; } @@ -2950,7 +2966,7 @@ solver_addchoicerules(Solver *solv) Pool *pool = solv->pool; Map m, mneg; Rule *r; - Queue q, qi, qcheck; + Queue q, qi, qcheck, infoq; int i, j, rid, havechoice; Id p, d, pp; Id p2, pp2; @@ -2966,10 +2982,11 @@ solver_addchoicerules(Solver *solv) return; } now = solv_timems(0); - solv->choicerules_ref = solv_calloc(solv->pkgrules_end, sizeof(Id)); + solv->choicerules_info = solv_calloc(solv->pkgrules_end, sizeof(Id)); queue_init(&q); queue_init(&qi); queue_init(&qcheck); + queue_init(&infoq); map_init(&m, pool->nsolvables); map_init(&mneg, pool->nsolvables); /* set up negative assertion map from infarch and dup rules */ @@ -3158,7 +3175,7 @@ solver_addchoicerules(Solver *solv) solver_addrule(solv, r->p, 0, d); queue_push(&solv->weakruleq, solv->nrules - 1); - solv->choicerules_ref[solv->nrules - 1 - solv->choicerules] = rid; + queue_push(&infoq, rid); #if 0 printf("OLD "); solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + rid); @@ -3166,20 +3183,21 @@ solver_addchoicerules(Solver *solv) solver_printrule(solv, SOLV_DEBUG_RESULT, solv->rules + solv->nrules - 1); #endif } + if (infoq.count) + solv->choicerules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); queue_free(&q); queue_free(&qi); queue_free(&qcheck); + queue_free(&infoq); map_free(&m); map_free(&mneg); solv->choicerules_end = solv->nrules; - /* shrink choicerules_ref */ - solv->choicerules_ref = solv_realloc2(solv->choicerules_ref, solv->choicerules_end - solv->choicerules, sizeof(Id)); POOL_DEBUG(SOLV_DEBUG_STATS, "choice rule creation took %d ms\n", solv_timems(now)); } -/* called when a choice rule is disabled by analyze_unsolvable. We also - * have to disable all other choice rules so that the best packages get - * picked */ +/* called when a choice rule needs to be disabled by analyze_unsolvable. + * We also have to disable all other choice rules so that the best packages + * get picked */ void solver_disablechoicerules(Solver *solv, Rule *r) { @@ -3188,7 +3206,8 @@ solver_disablechoicerules(Solver *solv, Rule *r) Map m; Rule *or; - or = solv->rules + solv->choicerules_ref[(r - solv->rules) - solv->choicerules]; + solver_disablerule(solv, r); + or = solv->rules + solv->choicerules_info[(r - solv->rules) - solv->choicerules]; map_init(&m, pool->nsolvables); FOR_RULELITERALS(p, pp, or) if (p > 0) @@ -3201,7 +3220,7 @@ solver_disablechoicerules(Solver *solv, Rule *r) r = solv->rules + rid; if (r->d < 0) continue; - or = solv->rules + solv->choicerules_ref[(r - solv->rules) - solv->choicerules]; + or = solv->rules + solv->choicerules_info[rid - solv->choicerules]; FOR_RULELITERALS(p, pp, or) if (p > 0 && MAPTST(&m, p)) break; @@ -3250,13 +3269,13 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) Repo *installed = solv->installed; Queue q, q2; Rule *r; - Queue r2pkg; + Queue infoq; int i, oldcnt; solv->bestrules = solv->nrules; queue_init(&q); queue_init(&q2); - queue_init(&r2pkg); + queue_init(&infoq); if (havebestinstalljobs) { @@ -3297,7 +3316,7 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q)); if ((how & SOLVER_WEAK) != 0) queue_push(&solv->weakruleq, solv->nrules - 1); - queue_push(&r2pkg, -(solv->jobrules + j)); + queue_push(&infoq, -(solv->jobrules + j)); } } } @@ -3387,7 +3406,7 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) solver_addrule(solv, -p2, d, 0); else solver_addrule(solv, -p2, 0, -d); - queue_push(&r2pkg, p); + queue_push(&infoq, p); } for (i = 0; i < q.count; i++) MAPCLR(&m, q.elements[i]); @@ -3398,16 +3417,16 @@ solver_addbestrules(Solver *solv, int havebestinstalljobs) solver_addrule(solv, p2, q.count ? q.elements[0] : 0, 0); else solver_addrule(solv, p2, 0, pool_queuetowhatprovides(pool, &q)); - queue_push(&r2pkg, p); + queue_push(&infoq, p); } map_free(&m); } - if (r2pkg.count) - solv->bestrules_pkg = solv_memdup2(r2pkg.elements, r2pkg.count, sizeof(Id)); + if (infoq.count) + solv->bestrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); solv->bestrules_end = solv->nrules; queue_free(&q); queue_free(&q2); - queue_free(&r2pkg); + queue_free(&infoq); } @@ -3442,7 +3461,7 @@ find_obsolete_group(Solver *solv, Id obs, Queue *q) continue; if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s2, os)) continue; - obsp2 = os->repo->idarraydata + os->obsoletes; + obsp2 = os->repo->idarraydata + os->obsoletes; while ((obs2 = *obsp2++) != 0) if (obs2 == obs) break; @@ -3460,7 +3479,7 @@ find_obsolete_group(Solver *solv, Id obs, Queue *q) continue; if ((pool->obsoleteusescolors || pool->implicitobsoleteusescolors) && !pool_colormatch(pool, s2, os)) continue; - obsp2 = os->repo->idarraydata + os->obsoletes; + obsp2 = os->repo->idarraydata + os->obsoletes; while ((obs2 = *obsp2++) != 0) if (obs2 == obs) break; @@ -3524,7 +3543,7 @@ solver_addyumobsrules(Solver *solv) Repo *installed = solv->installed; Id p, op, *opp; Solvable *s; - Queue qo, qq, yumobsinfoq; + Queue qo, qq, infoq; int i, j, k; unsigned int now; @@ -3570,7 +3589,7 @@ printf("checking yumobs for %s\n", pool_solvable2str(pool, s)); queue_free(&qo); return; } - queue_init(&yumobsinfoq); + queue_init(&infoq); queue_init(&qq); for (i = 0; i < qo.count; i++) { @@ -3588,7 +3607,7 @@ for (j = 0; j < qq.count; j++) else printf("%s\n", pool_solvid2str(pool, qq.elements[j])); #endif - + if (!qq.count) continue; /* at least two goups, build rules */ @@ -3617,22 +3636,70 @@ for (j = 0; j < qq.count; j++) solver_addrule(solv, -p, qq.elements[groupstart], 0); else solver_addrule(solv, -p, 0, pool_ids2whatprovides(pool, qq.elements + groupstart, k - groupstart)); - queue_push(&yumobsinfoq, qo.elements[i]); + queue_push(&infoq, qo.elements[i]); } groupstart = k + 1; groupk++; } } } - if (yumobsinfoq.count) - solv->yumobsrules_info = solv_memdup2(yumobsinfoq.elements, yumobsinfoq.count, sizeof(Id)); - queue_free(&yumobsinfoq); + if (infoq.count) + solv->yumobsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); + queue_free(&infoq); queue_free(&qq); queue_free(&qo); solv->yumobsrules_end = solv->nrules; POOL_DEBUG(SOLV_DEBUG_STATS, "yumobs rule creation took %d ms\n", solv_timems(now)); } +/* recommendsrules are a copy of some recommends package rule but + * with some disfavored literals removed */ +void +solver_addrecommendsrules(Solver *solv) +{ + Pool *pool = solv->pool; + int i, havedis, havepos; + Id p, pp; + Queue q, infoq; + + solv->recommendsrules = solv->nrules; + queue_init(&q); + queue_init(&infoq); + for (i = 0; i < solv->recommendsruleq->count; i++) + { + int rid = solv->recommendsruleq->elements[i]; + Rule *r = solv->rules + rid; + queue_empty(&q); + havedis = havepos = 0; + FOR_RULELITERALS(p, pp, r) + { + if (p > 0 && solv->favormap[p] < 0) + havedis = 1; + else + { + if (p > 0) + havepos = 1; + queue_push(&q, p); + } + } + if (!havedis) + continue; + solver_disablerule(solv, r); + if (!havepos || q.count < 2) + continue; + if (q.count == 2) + solver_addrule(solv, q.elements[0], q.elements[1], 0); + else + solver_addrule(solv, q.elements[0], 0, pool_ids2whatprovides(pool, q.elements + 1, q.count - 1)); + queue_push(&infoq, rid); + } + if (infoq.count) + solv->recommendsrules_info = solv_memdup2(infoq.elements, infoq.count, sizeof(Id)); + queue_free(&infoq); + queue_free(&q); + solv->recommendsrules_end = solv->nrules; +} + void solver_breakorphans(Solver *solv) { @@ -3696,7 +3763,7 @@ solver_check_brokenorphanrules(Solver *solv, Queue *dq) Pool *pool = solv->pool; int i; Id l, pp; - + queue_empty(dq); if (!solv->brokenorphanrules) return; diff --git a/src/rules.h b/src/rules.h index a3c0135..1db0551 100644 --- a/src/rules.h +++ b/src/rules.h @@ -71,7 +71,8 @@ typedef enum { SOLVER_RULE_CHOICE = 0x700, SOLVER_RULE_LEARNT = 0x800, SOLVER_RULE_BEST = 0x900, - SOLVER_RULE_YUMOBS = 0xa00 + SOLVER_RULE_YUMOBS = 0xa00, + SOLVER_RULE_RECOMMENDS = 0xb00 } SolverRuleinfo; #define SOLVER_RULE_TYPEMASK 0xff00 @@ -133,6 +134,9 @@ extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs); /* yumobs rules */ extern void solver_addyumobsrules(struct s_Solver *solv); +/* recommends rules */ +extern void solver_addrecommendsrules(struct s_Solver *solv); + /* policy rule disabling/reenabling */ extern void solver_disablepolicyrules(struct s_Solver *solv); extern void solver_reenablepolicyrules(struct s_Solver *solv, int jobidx); diff --git a/src/solver.c b/src/solver.c index 57fa3e4..a80090d 100644 --- a/src/solver.c +++ b/src/solver.c @@ -243,7 +243,7 @@ makeruledecisions(Solver *solv, int disablerules) continue; if (solv->weakrulemap.size && MAPTST(&solv->weakrulemap, i)) /* weak: silently ignore */ continue; - + POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i); solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + i); solver_recordproblem(solv, i); @@ -845,18 +845,19 @@ static void disable_recommendsrules(Solver *solv, Queue *weakq) { Pool *pool = solv->pool; - int i; + int i, rid; for (i = 0; i < weakq->count; i++) { - Rule *r; - if (!queue_contains(solv->recommendsruleq, weakq->elements[i])) - continue; - r = solv->rules + weakq->elements[i]; - if (r->d >= 0) + rid = weakq->elements[i]; + if ((rid >= solv->recommendsrules && rid < solv->recommendsrules_end) || queue_contains(solv->recommendsruleq, rid)) { - POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); - solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r); - solver_disablerule(solv, r); + Rule *r = solv->rules + rid; + if (r->d >= 0) + { + POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); + solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, r); + solver_disablerule(solv, r); + } } } } @@ -894,6 +895,41 @@ analyze_unsolvable_rule(Solver *solv, Rule *r, Queue *weakq, Map *rseen) solver_recordproblem(solv, why); } +/* fix a problem by disabling one or more weak rules */ +static void +disable_weakrules(Solver *solv, Queue *weakq) +{ + Pool *pool = solv->pool; + int i; + Id lastweak = 0; + for (i = 0; i < weakq->count; i++) + if (weakq->elements[i] > lastweak) + lastweak = weakq->elements[i]; + if (lastweak >= solv->recommendsrules && lastweak < solv->recommendsrules_end) + { + lastweak = 0; + for (i = 0; i < weakq->count; i++) + if (weakq->elements[i] < solv->recommendsrules && weakq->elements[i] > lastweak) + lastweak = weakq->elements[i]; + if (lastweak < solv->pkgrules_end) + { + disable_recommendsrules(solv, weakq); + return; + } + } + if (lastweak < solv->pkgrules_end && solv->strongrecommends && solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak)) + { + disable_recommendsrules(solv, weakq); + return; + } + POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); + solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + lastweak); + /* choice rules need special handling */ + if (lastweak >= solv->choicerules && lastweak < solv->choicerules_end) + solver_disablechoicerules(solv, solv->rules + lastweak); + else + solver_fixproblem(solv, lastweak); +} /*------------------------------------------------------------------- * @@ -924,7 +960,7 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) Map rseen; Queue weakq; Id pp, v, vv, why; - int i, idx; + int idx; Id *decisionmap = solv->decisionmap; int oldproblemcount; int oldlearntpoolcount; @@ -981,28 +1017,12 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) if (weakq.count) { - Id lastweak; /* revert problems */ solv->problems.count = oldproblemcount; solv->learnt_pool.count = oldlearntpoolcount; - /* find last weak */ - lastweak = 0; - for (i = 0; i < weakq.count; i++) - if (weakq.elements[i] > lastweak) - lastweak = weakq.elements[i]; - if (lastweak < solv->pkgrules_end && solv->strongrecommends && solv->recommendsruleq && queue_contains(solv->recommendsruleq, lastweak)) - { - disable_recommendsrules(solv, &weakq); - queue_free(&weakq); - solver_reset(solv); - return 0; - } + /* disable some weak rules */ + disable_weakrules(solv, &weakq); queue_free(&weakq); - POOL_DEBUG(SOLV_DEBUG_UNSOLVABLE, "disabling "); - solver_printruleclass(solv, SOLV_DEBUG_UNSOLVABLE, solv->rules + lastweak); - if (lastweak >= solv->choicerules && lastweak < solv->choicerules_end) - solver_disablechoicerules(solv, solv->rules + lastweak); - solver_fixproblem(solv, lastweak); solver_reset(solv); return 0; } @@ -1160,6 +1180,15 @@ reorder_dq_for_future_installed(Solver *solv, int level, Queue *dq) /*------------------------------------------------------------------- * * branch handling + * + * format is: + * [ -p1 p2 p3 .. pn opt_pkg opt_data size level ] + * + * pkgs are negative if we tried them (to prevent inifinite recursion) + * opt_pkg: recommends: package with the recommends + * rule: 0 + * opt_data: recommends: depid + * rule: ruleid */ static void @@ -1370,18 +1399,18 @@ solver_free(Solver *solv) map_free(&solv->droporphanedmap); map_free(&solv->cleandepsmap); map_free(&solv->allowuninstallmap); - map_free(&solv->favormap); - map_free(&solv->isdisfavormap); + solv_free(solv->favormap); solv_free(solv->decisionmap); solv_free(solv->rules); solv_free(solv->watches); solv_free(solv->obsoletes); solv_free(solv->obsoletes_data); solv_free(solv->specialupdaters); - solv_free(solv->choicerules_ref); - solv_free(solv->bestrules_pkg); + solv_free(solv->choicerules_info); + solv_free(solv->bestrules_info); solv_free(solv->yumobsrules_info); + solv_free(solv->recommendsrules_info); solv_free(solv->instbuddy); solv_free(solv); } @@ -2058,14 +2087,12 @@ static void prune_disfavored(Solver *solv, Queue *plist) { int i, j; - if (!solv->isdisfavormap.size) - return; - for (i = j = 0; i < plist->count; i++) - { + for (i = j = 0; i < plist->count; i++) + { Id p = plist->elements[i]; - if (!MAPTST(&solv->isdisfavormap, p)) - plist->elements[j++] = p; - } + if (solv->favormap[p] >= 0) + plist->elements[j++] = p; + } if (i != j) queue_truncate(plist, j); } @@ -2141,14 +2168,14 @@ resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, i continue; if (solv->process_orphans && solv->installed && s->repo == solv->installed && (solv->droporphanedmap_all || (solv->droporphanedmap.size && MAPTST(&solv->droporphanedmap, i - solv->installed->start)))) continue; - if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, i)) + if (solv->havedisfavored && solv->favormap[i] < 0) continue; /* disfavored supplements, do not install */ queue_push(dqs, i); } } /* filter out disfavored recommended packages */ - if (dq->count && solv->isdisfavormap.size) + if (dq->count && solv->havedisfavored) prune_disfavored(solv, dq); /* filter out all packages obsoleted by installed packages */ @@ -2348,7 +2375,7 @@ resolve_weak(Solver *solv, int level, int disablerules, Queue *dq, Queue *dqs, i policy_filter_unwanted(solv, dq, POLICY_MODE_CHOOSE); /* if we have multiple candidates we open a branch */ if (dq->count > 1) - createbranch(solv, level, dq, s - pool->solvables, rec); + createbranch(solv, level, dq, s - pool->solvables, rec); p = dq->elements[0]; POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p)); olevel = level; @@ -2455,6 +2482,7 @@ resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *reru break; } *rerunp = 1; + return level; } } return level; @@ -2617,7 +2645,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) if (rerun) continue; } - + /* one final pass to make sure we decided all installed packages */ if (solv->installed) { @@ -2700,7 +2728,7 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) lastsi = -1; break; } - if (solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p)) + if (solv->havedisfavored && solv->favormap[p] < 0) continue; if (lastsi < 0 && (MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p))) lastsi = i; @@ -2708,15 +2736,14 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) if (lastsi >= 0) { /* we have a recommended package that could not be installed */ - /* take it if our current selection is not recommended */ + /* find current selection and take new one if it is not recommended */ for (i = starti; i < endi - 4; i++) { p = -solv->branches.elements[i]; if (p <= 0 || solv->decisionmap[p] != l + 1) continue; - if (solv->favormap.size && MAPTST(&solv->favormap, p)) - if (!(solv->isdisfavormap.size && MAPTST(&solv->isdisfavormap, p))) - continue; /* current selection is favored */ + if (solv->favormap && solv->favormap[p] > solv->favormap[solv->branches.elements[lastsi]]) + continue; /* current selection is more favored */ if (!(MAPTST(&solv->recommendsmap, p) || solver_is_supplementing(solv, pool->solvables + p))) { lasti = lastsi; @@ -3117,10 +3144,6 @@ addedmap2deduceq(Solver *solv, Map *addedmap) for (; i < pool->nsolvables; i++) if (MAPTST(addedmap, i)) queue_push(&solv->addedmap_deduceq, i); - j = 0; - for (i = 2; i < pool->nsolvables; i++) - if (MAPTST(addedmap, i)) - j++; } static void @@ -3187,7 +3210,7 @@ add_complex_jobrules(Solver *solv, Id dep, int flags, int jobidx, int weak) /* sort by package id, last entry wins */ static int -setup_favormaps_cmp(const void *ap, const void *bp, void *dp) +setup_favormap_cmp(const void *ap, const void *bp, void *dp) { const Id *a = ap, *b = bp; if ((*a - *b) != 0) @@ -3196,28 +3219,25 @@ setup_favormaps_cmp(const void *ap, const void *bp, void *dp) } static void -setup_favormaps(Solver *solv) +setup_favormap(Solver *solv) { Queue *q = solv->favorq; Pool *pool = solv->pool; int i; Id oldp = 0; if (q->count > 2) - solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), setup_favormaps_cmp, solv); - map_grow(&solv->favormap, pool->nsolvables); + solv_sort(q->elements, q->count / 2, 2 * sizeof(Id), setup_favormap_cmp, solv); + solv->favormap = solv_calloc(pool->nsolvables, sizeof(Id)); + solv->havedisfavored = 0; for (i = 0; i < q->count; i += 2) { Id p = q->elements[i]; if (p == oldp) continue; oldp = p; - MAPSET(&solv->favormap, p); + solv->favormap[p] = q->elements[i + 1]; if (q->elements[i + 1] < 0) - { - if (!solv->isdisfavormap.size) - map_grow(&solv->isdisfavormap, pool->nsolvables); - MAPSET(&solv->isdisfavormap, p); - } + solv->havedisfavored = 1; } } @@ -3273,9 +3293,10 @@ solver_solve(Solver *solv, Queue *job) queuep_free(&solv->update_targets); queuep_free(&solv->cleandeps_updatepkgs); queue_empty(&solv->ruleassertions); - solv->bestrules_pkg = solv_free(solv->bestrules_pkg); + solv->bestrules_info = solv_free(solv->bestrules_info); solv->yumobsrules_info = solv_free(solv->yumobsrules_info); - solv->choicerules_ref = solv_free(solv->choicerules_ref); + solv->recommendsrules_info = solv_free(solv->recommendsrules_info); + solv->choicerules_info = solv_free(solv->choicerules_info); if (solv->noupdate.size) map_empty(&solv->noupdate); map_zerosize(&solv->multiversion); @@ -3294,8 +3315,7 @@ solver_solve(Solver *solv, Queue *job) map_zerosize(&solv->allowuninstallmap); map_zerosize(&solv->cleandepsmap); map_zerosize(&solv->weakrulemap); - map_zerosize(&solv->favormap); - map_zerosize(&solv->isdisfavormap); + solv->favormap = solv_free(solv->favormap); queue_empty(&solv->weakruleq); solv->watches = solv_free(solv->watches); queue_empty(&solv->ruletojob); @@ -3346,9 +3366,9 @@ solver_solve(Solver *solv, Queue *job) */ initialnrules = solv->pkgrules_end ? solv->pkgrules_end : 1; if (initialnrules > 1) - deduceq2addedmap(solv, &addedmap); + deduceq2addedmap(solv, &addedmap); /* also enables all pkg rules */ if (solv->nrules != initialnrules) - solver_shrinkrules(solv, initialnrules); + solver_shrinkrules(solv, initialnrules); /* shrink to just pkg rules */ solv->lastpkgrule = 0; solv->pkgrules_end = 0; @@ -3839,14 +3859,12 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what)); FOR_JOB_SELECT(p, pp, select, what) { - int j; if (!solv->favorq) { solv->favorq = solv_calloc(1, sizeof(Queue)); queue_init(solv->favorq); } - j = solv->favorq->count + 1; - queue_push2(solv->favorq, p, (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? j : -j); + queue_push2(solv->favorq, p, (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? i + 1 : -(i + 1)); } break; default: @@ -3869,9 +3887,9 @@ solver_solve(Solver *solv, Queue *job) assert(solv->ruletojob.count == solv->nrules - solv->jobrules); solv->jobrules_end = solv->nrules; - /* transform favorq into two maps */ + /* sort favorq and transform it into two maps */ if (solv->favorq) - setup_favormaps(solv); + setup_favormap(solv); /* now create infarch and dup rules */ if (!solv->noinfarchcheck) @@ -3902,16 +3920,16 @@ solver_solve(Solver *solv, Queue *job) else solv->yumobsrules = solv->yumobsrules_end = solv->nrules; + if (solv->havedisfavored && solv->strongrecommends) + solver_addrecommendsrules(solv); + else + solv->recommendsrules = solv->recommendsrules_end = solv->nrules; + if (1) solver_addchoicerules(solv); else solv->choicerules = solv->choicerules_end = solv->nrules; - if (0) - { - for (i = solv->featurerules; i < solv->nrules; i++) - solver_printruleclass(solv, SOLV_DEBUG_RESULT, solv->rules + i); - } /* all rules created * -------------------------------------------------------------- * prepare for solving @@ -4771,6 +4789,8 @@ solver_alternative2str(Solver *solv, int type, Id id, Id from) char buf[64]; if (solver_ruleclass(solv, id) == SOLVER_RULE_CHOICE) id = solver_rule2pkgrule(solv, id); + if (solver_ruleclass(solv, id) == SOLVER_RULE_RECOMMENDS) + id = solver_rule2pkgrule(solv, id); rtype = solver_ruleinfo(solv, id, &depfrom, &depto, &dep); if ((rtype & SOLVER_RULE_TYPEMASK) == SOLVER_RULE_JOB) { diff --git a/src/solver.h b/src/solver.h index 6fc2e9f..93baa34 100644 --- a/src/solver.h +++ b/src/solver.h @@ -70,7 +70,7 @@ struct s_Solver { Id bestrules; /* rules from SOLVER_FORCEBEST */ Id bestrules_up; /* update rule part starts here*/ Id bestrules_end; - Id *bestrules_pkg; + Id *bestrules_info; /* < 0 : install rule, > 0 : pkg that needs to be updated */ Id yumobsrules; /* rules from yum obsoletes handling */ Id yumobsrules_end; @@ -78,7 +78,11 @@ struct s_Solver { Id choicerules; /* choice rules (always weak) */ Id choicerules_end; - Id *choicerules_ref; + Id *choicerules_info; /* the rule we used to generate the choice rule */ + + Id recommendsrules; /* rules from recommends pkg rules with disfavored literals */ + Id recommendsrules_end; + Id *recommendsrules_info; /* the original pkg rule rule */ Id learntrules; /* learnt rules, (end == nrules) */ @@ -202,8 +206,8 @@ struct s_Solver { int allowuninstall_all; Queue *favorq; - Map favormap; /* favored / disfavored packages */ - Map isdisfavormap; + Id *favormap; /* favor job index, > 0: favored, < 0: disfavored */ + int havedisfavored; /* do we have disfavored packages? */ int installedpos; /* for resolve_installed */ int do_extra_reordering; /* reorder for future installed packages */ diff --git a/src/solverdebug.c b/src/solverdebug.c index bb74ef6..b1b55f4 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -128,6 +128,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r) POOL_DEBUG(type, "FEATURE "); else if (p >= solv->yumobsrules && p < solv->yumobsrules_end) POOL_DEBUG(type, "YUMOBS "); + else if (p >= solv->recommendsrules && p < solv->recommendsrules_end) + POOL_DEBUG(type, "RECOMMENDS "); solver_printrule(solv, type, r); } |