From 96275a1cb13044d4914c25f33387b1a98a5e9605 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Mon, 19 Nov 2012 17:18:51 +0100 Subject: [PATCH] implement SOLVER_FORCRBEST for install/up/dup --- src/problems.c | 54 +++++++++++-- src/problems.h | 1 + src/rules.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++------- src/rules.h | 6 +- src/solver.c | 54 +++++++++++-- src/solver.h | 9 +++ src/solverdebug.c | 19 +++++ 7 files changed, 340 insertions(+), 39 deletions(-) diff --git a/src/problems.c b/src/problems.c index 5a2ae60..5cf42a3 100644 --- a/src/problems.c +++ b/src/problems.c @@ -434,14 +434,11 @@ convertsolution(Solver *solv, Id why, Queue *solutionq) Id p, *dp, rp = 0; Rule *rr; - assert(why >= solv->updaterules && why < solv->updaterules_end); /* check if this is a false positive, i.e. the update rule is fulfilled */ rr = solv->rules + why; FOR_RULELITERALS(p, dp, rr) if (p > 0 && solv->decisionmap[p] > 0) - break; - if (p) - return; /* false alarm */ + return; /* false alarm */ p = solv->installed->start + (why - solv->updaterules); rr = solv->rules + solv->featurerules + (why - solv->updaterules); @@ -480,6 +477,51 @@ convertsolution(Solver *solv, Id why, Queue *solutionq) queue_push(solutionq, rp); return; } + if (why >= solv->bestrules && why < solv->bestrules_end) + { + int mvrp; + Id p, *dp, rp = 0; + Rule *rr; + /* check false positive */ + rr = solv->rules + why; + FOR_RULELITERALS(p, dp, rr) + if (p > 0 && solv->decisionmap[p] > 0) + return; /* false alarm */ + /* check update/feature rule */ + p = solv->bestrules_pkg[why - solv->bestrules]; + if (p < 0) + { + /* install job */ + queue_push(solutionq, 0); + queue_push(solutionq, solv->ruletojob.elements[-p - solv->jobrules] + 1); + return; + } + rr = solv->rules + solv->featurerules + (p - solv->installed->start); + if (!rr->p) + rr = solv->rules + solv->updaterules + (p - solv->installed->start); + mvrp = 0; /* multi-version replacement */ + FOR_RULELITERALS(rp, dp, rr) + if (rp > 0 && solv->decisionmap[rp] > 0) + { + mvrp = rp; + if (!(solv->noobsoletes.size && MAPTST(&solv->noobsoletes, rp))) + break; + } + if (!rp && mvrp) + { + queue_push(solutionq, SOLVER_SOLUTION_BEST); /* split, see above */ + queue_push(solutionq, mvrp); + queue_push(solutionq, p); + queue_push(solutionq, 0); + return; + } + if (rp) + { + queue_push(solutionq, SOLVER_SOLUTION_BEST); + queue_push(solutionq, rp); + } + return; + } } /* @@ -722,6 +764,8 @@ solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution) * -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job * SOLVER_SOLUTION_DISTUPGRADE pkgid * -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job + * SOLVER_SOLUTION_BEST pkgid + * -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job * SOLVER_SOLUTION_JOB jobidx * -> remove job (jobidx - 1, jobidx) from job queue * pkgid (> 0) 0 @@ -823,7 +867,7 @@ findproblemrule_internal(Solver *solv, Id idx, Id *reqrp, Id *conrp, Id *sysrp, assert(rid > 0); if (rid >= solv->learntrules) findproblemrule_internal(solv, solv->learnt_why.elements[rid - solv->learntrules], &lreqr, &lconr, &lsysr, &ljobr); - else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end)) + else if ((rid >= solv->jobrules && rid < solv->jobrules_end) || (rid >= solv->infarchrules && rid < solv->infarchrules_end) || (rid >= solv->duprules && rid < solv->duprules_end) || (rid >= solv->bestrules && rid < solv->bestrules_end)) { if (!*jobrp) *jobrp = rid; diff --git a/src/problems.h b/src/problems.h index d01f2fa..cb37139 100644 --- a/src/problems.h +++ b/src/problems.h @@ -23,6 +23,7 @@ struct _Solver; #define SOLVER_SOLUTION_JOB (0) #define SOLVER_SOLUTION_DISTUPGRADE (-1) #define SOLVER_SOLUTION_INFARCH (-2) +#define SOLVER_SOLUTION_BEST (-3) void solver_disableproblem(struct _Solver *solv, Id v); void solver_enableproblem(struct _Solver *solv, Id v); diff --git a/src/rules.c b/src/rules.c index c5b6917..9e292d7 100644 --- a/src/rules.c +++ b/src/rules.c @@ -958,6 +958,13 @@ solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) } qs.count = j; } + else if (p != -SYSTEMSOLVABLE) + { + /* could fallthrough, but then we would do pool_queuetowhatprovides twice */ + queue_free(&qs); + solver_addrule(solv, p, d); /* allow update of s */ + return; + } } if (qs.count && p == -SYSTEMSOLVABLE) p = queue_shift(&qs); @@ -978,6 +985,14 @@ 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) + { + int i, ni; + ni = solv->bestrules_end - solv->bestrules; + for (i = 0; i < ni; i++) + if (solv->bestrules_pkg[i] == p) + solver_disablerule(solv, solv->rules + solv->bestrules + i); + } } static inline void @@ -990,26 +1005,37 @@ reenableupdaterule(Solver *solv, Id p) r = solv->rules + solv->updaterules + (p - solv->installed->start); if (r->p) { - if (r->d >= 0) - return; - solver_enablerule(solv, r); - IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) + if (r->d > 0) { - POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); + solver_enablerule(solv, r); + IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); + } } - return; } - r = solv->rules + solv->featurerules + (p - solv->installed->start); - if (r->p && r->d < 0) + else { - solver_enablerule(solv, r); - IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) + r = solv->rules + solv->featurerules + (p - solv->installed->start); + if (r->p && r->d < 0) { - POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); + solver_enablerule(solv, r); + IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r); + } } } + if (solv->bestrules_pkg) + { + int i, ni; + ni = solv->bestrules_end - solv->bestrules; + for (i = 0; i < ni; i++) + if (solv->bestrules_pkg[i] == p) + solver_enablerule(solv, solv->rules + solv->bestrules + i); + } } @@ -1159,6 +1185,7 @@ solver_createdupmaps(Solver *solv) Queue *job = &solv->job; Pool *pool = solv->pool; Repo *repo; + Repo *installed = solv->installed; Id select, how, what, p, pi, pp, pip, obs, *obsp; Solvable *s, *ps; int i; @@ -1177,10 +1204,10 @@ solver_createdupmaps(Solver *solv) { int haveinstalled; p = 0; - if (solv->installed) + if (installed) { FOR_JOB_SELECT(p, pp, select, what) - if (pool->solvables[p].repo == solv->installed) + if (pool->solvables[p].repo == installed) break; } haveinstalled = p != 0; @@ -1189,9 +1216,9 @@ solver_createdupmaps(Solver *solv) Solvable *s = pool->solvables + p; if (!s->repo) continue; - if (haveinstalled && s->repo != solv->installed) + if (haveinstalled && s->repo != installed) continue; - if (s->repo != solv->installed && !pool_installable(pool, s)) + if (s->repo != installed && !pool_installable(pool, s)) continue; MAPSET(&solv->dupinvolvedmap, p); if (!haveinstalled) @@ -1202,18 +1229,24 @@ solver_createdupmaps(Solver *solv) if (ps->name != s->name) continue; MAPSET(&solv->dupinvolvedmap, pi); - if (haveinstalled && ps->repo != solv->installed) + if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } + if (haveinstalled && ps->repo != installed) MAPSET(&solv->dupmap, pi); } if (haveinstalled) { - if (solv->obsoletes && solv->obsoletes[p - solv->installed->start]) + if (solv->obsoletes && solv->obsoletes[p - installed->start]) { Id *opp; - for (opp = solv->obsoletes_data + solv->obsoletes[p - solv->installed->start]; (pi = *opp++) != 0;) + for (opp = solv->obsoletes_data + solv->obsoletes[p - installed->start]; (pi = *opp++) != 0;) { ps = pool->solvables + pi; - if (ps->repo == solv->installed) + if (ps->repo == installed) continue; MAPSET(&solv->dupinvolvedmap, pi); MAPSET(&solv->dupmap, pi); @@ -1228,12 +1261,18 @@ solver_createdupmaps(Solver *solv) { FOR_PROVIDES(pi, pp, obs) { - Solvable *pis = pool->solvables + pi; - if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pis, obs)) + Solvable *ps = pool->solvables + pi; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) continue; - if (pool->obsoleteusescolors && !pool_colormatch(pool, s, pis)) + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) continue; MAPSET(&solv->dupinvolvedmap, pi); + if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } } } } @@ -1245,7 +1284,7 @@ solver_createdupmaps(Solver *solv) repo = pool_id2repo(pool, what); FOR_REPO_SOLVABLES(repo, p, s) { - if (repo != solv->installed && !pool_installable(pool, s)) + if (repo != installed && !pool_installable(pool, s)) continue; MAPSET(&solv->dupmap, p); FOR_PROVIDES(pi, pip, s->name) @@ -1254,6 +1293,12 @@ solver_createdupmaps(Solver *solv) if (ps->name != s->name) continue; MAPSET(&solv->dupinvolvedmap, pi); + if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } } if (s->obsoletes) { @@ -1263,12 +1308,18 @@ solver_createdupmaps(Solver *solv) { FOR_PROVIDES(pi, pp, obs) { - Solvable *pis = pool->solvables + pi; - if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pis, obs)) + Solvable *ps = pool->solvables + pi; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) continue; - if (pool->obsoleteusescolors && !pool_colormatch(pool, s, pis)) + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) continue; MAPSET(&solv->dupinvolvedmap, pi); + if (ps->repo == installed && (how & SOLVER_FORCEBEST) != 0) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } } } } @@ -2102,6 +2153,10 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp) *depp = pool->solvables[-r->p].name; return SOLVER_RULE_INFARCH; } + if (rid >= solv->bestrules && rid < solv->bestrules_end) + { + return SOLVER_RULE_BEST; + } if (rid >= solv->choicerules && rid < solv->choicerules_end) { return SOLVER_RULE_CHOICE; @@ -2130,6 +2185,8 @@ solver_ruleclass(Solver *solv, Id rid) return SOLVER_RULE_DISTUPGRADE; if (rid >= solv->infarchrules && rid < solv->infarchrules_end) return SOLVER_RULE_INFARCH; + if (rid >= solv->bestrules && rid < solv->bestrules_end) + return SOLVER_RULE_BEST; if (rid >= solv->choicerules && rid < solv->choicerules_end) return SOLVER_RULE_CHOICE; if (rid >= solv->learntrules) @@ -2375,6 +2432,129 @@ solver_disablechoicerules(Solver *solv, Rule *r) } } +void +solver_addbestrules(Solver *solv, int havebestinstalljobs) +{ + Pool *pool = solv->pool; + Id p; + Solvable *s; + Repo *installed = solv->installed; + Queue q, q2; + Rule *r; + Queue r2pkg; + int i, oldcnt; + + solv->bestrules = solv->nrules; + if (!installed) + { + solv->bestrules_end = solv->nrules; + return; + } + queue_init(&q); + queue_init(&q2); + queue_init(&r2pkg); + + if (havebestinstalljobs) + { + for (i = 0; i < solv->job.count; i += 2) + { + if ((solv->job.elements[i] & (SOLVER_JOBMASK | SOLVER_FORCEBEST)) == (SOLVER_INSTALL | SOLVER_FORCEBEST)) + { + int j; + Id p2, *pp2; + for (j = 0; j < solv->ruletojob.count; j++) + if (solv->ruletojob.elements[j] == i) + break; + if (j == solv->ruletojob.count) + continue; + r = solv->rules + solv->jobrules + j; + queue_empty(&q); + FOR_RULELITERALS(p2, pp2, r) + if (p2 > 0) + queue_push(&q, p2); + if (!q.count) + continue; /* orphaned */ + /* select best packages, just look at prio and version */ + oldcnt = q.count; + policy_filter_unwanted(solv, &q, POLICY_MODE_RECOMMEND); + if (q.count == oldcnt) + continue; /* nothing filtered */ + p2 = queue_shift(&q); + solver_addrule(solv, p2, q.count ? pool_queuetowhatprovides(pool, &q) : 0); + queue_push(&r2pkg, -(solv->jobrules + j)); + } + } + } + + if (solv->bestupdatemap_all || solv->bestupdatemap.size) + { + FOR_REPO_SOLVABLES(installed, p, s) + { + Id d, p2, *pp2; + if (!solv->updatemap_all && (!solv->updatemap.size || !MAPTST(&solv->updatemap, p - installed->start))) + continue; + if (!solv->bestupdatemap_all && (!solv->bestupdatemap.size || !MAPTST(&solv->bestupdatemap, p - installed->start))) + continue; + queue_empty(&q); + if (solv->bestobeypolicy) + r = solv->rules + solv->updaterules + (p - installed->start); + else + { + r = solv->rules + solv->featurerules + (p - installed->start); + if (!r->p) /* identical to update rule? */ + r = solv->rules + solv->updaterules + (p - installed->start); + } + if (solv->multiversionupdaters && (d = solv->multiversionupdaters[p - installed->start]) != 0 && r == solv->rules + solv->updaterules + (p - installed->start)) + { + /* need to check multiversionupdaters */ + if (r->p == p) /* be careful with the dup case */ + queue_push(&q, p); + while ((p2 = pool->whatprovidesdata[d++]) != 0) + queue_push(&q, p2); + } + else + { + FOR_RULELITERALS(p2, pp2, r) + if (p2 > 0) + queue_push(&q, p2); + } + /* select best packages, just look at prio and version */ + oldcnt = q.count; + policy_filter_unwanted(solv, &q, POLICY_MODE_RECOMMEND); + if (!q.count) + continue; /* orphaned */ + if (solv->bestobeypolicy) + { + /* also filter the best of the feature rule packages and add them */ + r = solv->rules + solv->featurerules + (p - installed->start); + if (r->p) + { + int j; + queue_empty(&q2); + FOR_RULELITERALS(p2, pp2, r) + if (p2 > 0) + queue_push(&q2, p2); + policy_filter_unwanted(solv, &q2, POLICY_MODE_RECOMMEND); + for (j = 0; j < q2.count; j++) + queue_pushunique(&q, q2.elements[j]); + } + } + p2 = queue_shift(&q); + solver_addrule(solv, p2, q.count ? pool_queuetowhatprovides(pool, &q) : 0); + queue_push(&r2pkg, p); + } + } + if (r2pkg.count) + { + solv->bestrules_pkg = solv_calloc(r2pkg.count, sizeof(Id)); + memcpy(solv->bestrules_pkg, r2pkg.elements, r2pkg.count * sizeof(Id)); + } + solv->bestrules_end = solv->nrules; + queue_free(&q); + queue_free(&q2); + queue_free(&r2pkg); +} + #undef CLEANDEPSDEBUG /* diff --git a/src/rules.h b/src/rules.h index a7ba790..ea56aa7 100644 --- a/src/rules.h +++ b/src/rules.h @@ -65,7 +65,8 @@ typedef enum { SOLVER_RULE_DISTUPGRADE = 0x500, SOLVER_RULE_INFARCH = 0x600, SOLVER_RULE_CHOICE = 0x700, - SOLVER_RULE_LEARNT = 0x800 + SOLVER_RULE_LEARNT = 0x800, + SOLVER_RULE_BEST = 0x900 } SolverRuleinfo; #define SOLVER_RULE_TYPEMASK 0xff00 @@ -118,6 +119,9 @@ extern void solver_addduprules(struct _Solver *solv, Map *addedmap); extern void solver_addchoicerules(struct _Solver *solv); extern void solver_disablechoicerules(struct _Solver *solv, Rule *r); +/* best rules */ +extern void solver_addbestrules(struct _Solver *solv, int havebestinstalljobs); + /* policy rule disabling/reenabling */ extern void solver_disablepolicyrules(struct _Solver *solv); extern void solver_reenablepolicyrules(struct _Solver *solv, int jobidx); diff --git a/src/solver.c b/src/solver.c index 56c57d2..6e2acba 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1438,6 +1438,7 @@ solver_free(Solver *solv) map_free(&solv->noobsoletes); map_free(&solv->updatemap); + map_free(&solv->bestupdatemap); map_free(&solv->fixmap); map_free(&solv->dupmap); map_free(&solv->dupinvolvedmap); @@ -1451,6 +1452,7 @@ solver_free(Solver *solv) solv_free(solv->obsoletes_data); solv_free(solv->multiversionupdaters); solv_free(solv->choicerules_ref); + solv_free(solv->bestrules_pkg); solv_free(solv); } @@ -1481,6 +1483,8 @@ solver_get_flag(Solver *solv, int flag) return solv->noinfarchcheck; case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES: return solv->keepexplicitobsoletes; + case SOLVER_FLAG_BEST_OBEY_POLICY: + return solv->bestobeypolicy; default: break; } @@ -1526,6 +1530,9 @@ solver_set_flag(Solver *solv, int flag, int value) case SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES: solv->keepexplicitobsoletes = value; break; + case SOLVER_FLAG_BEST_OBEY_POLICY: + solv->bestobeypolicy = value; + break; default: break; } @@ -2591,7 +2598,7 @@ solver_addjobrule(Solver *solv, Id p, Id d, Id job, int weak) } static void -add_update_target(Solver *solv, Id p) +add_update_target(Solver *solv, Id p, Id how) { Pool *pool = solv->pool; Solvable *s = pool->solvables + p; @@ -2607,6 +2614,12 @@ add_update_target(Solver *solv, Id p) Solvable *si = pool->solvables + pi; if (si->repo != installed || si->name != s->name) continue; + if (how & SOLVER_FORCEBEST) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } queue_push2(solv->update_targets, pi, p); /* check if it's ok to keep the installed package */ if (s->evr == si->evr && solvable_identical(s, si)) @@ -2628,6 +2641,12 @@ add_update_target(Solver *solv, Id p) continue; if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si)) continue; + if (how & SOLVER_FORCEBEST) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, pi - installed->start); + } queue_push2(solv->update_targets, pi, p); } } @@ -2706,6 +2725,7 @@ solver_solve(Solver *solv, Queue *job) Rule *r; int now, solve_start; int hasdupjob = 0; + int hasbestinstalljob = 0; solve_start = solv_timems(0); @@ -2778,7 +2798,11 @@ solver_solve(Solver *solv, Queue *job) break; case SOLVER_UPDATE: if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid)) - solv->updatemap_all = 1; + { + solv->updatemap_all = 1; + if (how & SOLVER_FORCEBEST) + solv->bestupdatemap_all = 1; + } else if (select == SOLVER_SOLVABLE_REPO && what != installed->repoid) { Repo *repo = pool_id2repo(pool, what); @@ -2786,7 +2810,7 @@ solver_solve(Solver *solv, Queue *job) break; /* targeted update */ FOR_REPO_SOLVABLES(repo, p, s) - add_update_target(solv, p); + add_update_target(solv, p, how); } else { @@ -2799,12 +2823,18 @@ solver_solve(Solver *solv, Queue *job) if (!solv->updatemap.size) map_grow(&solv->updatemap, installed->end - installed->start); MAPSET(&solv->updatemap, p - installed->start); + if (how & SOLVER_FORCEBEST) + { + if (!solv->bestupdatemap.size) + map_grow(&solv->bestupdatemap, installed->end - installed->start); + MAPSET(&solv->bestupdatemap, p - installed->start); + } targeted = 0; } if (targeted) { FOR_JOB_SELECT(p, pp, select, what) - add_update_target(solv, p); + add_update_target(solv, p, how); } } break; @@ -2852,6 +2882,8 @@ solver_solve(Solver *solv, Queue *job) { solv->dupmap_all = 1; solv->updatemap_all = 1; + if (how & SOLVER_FORCEBEST) + solv->bestupdatemap_all = 1; } if (!solv->dupmap_all) hasdupjob = 1; @@ -3022,6 +3054,8 @@ solver_solve(Solver *solv, Queue *job) d = !q.count ? 0 : pool_queuetowhatprovides(pool, &q); /* internalize */ } solver_addjobrule(solv, p, d, i, weak); + if (how & SOLVER_FORCEBEST) + hasbestinstalljob = 1; break; case SOLVER_ERASE: POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s%serase %s\n", weak ? "weak " : "", how & SOLVER_CLEANDEPS ? "clean deps " : "", solver_select2str(pool, select, what)); @@ -3210,11 +3244,21 @@ solver_solve(Solver *solv, Queue *job) else solv->duprules = solv->duprules_end = solv->nrules; + if (solv->bestupdatemap_all || solv->bestupdatemap.size || hasbestinstalljob) + solver_addbestrules(solv, hasbestinstalljob); + else + solv->bestrules = solv->bestrules_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 @@ -3225,7 +3269,7 @@ solver_solve(Solver *solv, Queue *job) map_free(&installcandidatemap); queue_free(&q); - POOL_DEBUG(SOLV_DEBUG_STATS, "%d rpm rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules\n", solv->rpmrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules); + POOL_DEBUG(SOLV_DEBUG_STATS, "%d rpm rules, 2 * %d update rules, %d job rules, %d infarch rules, %d dup rules, %d choice rules, %d best rules\n", solv->rpmrules_end - 1, solv->updaterules_end - solv->updaterules, solv->jobrules_end - solv->jobrules, solv->infarchrules_end - solv->infarchrules, solv->duprules_end - solv->duprules, solv->choicerules_end - solv->choicerules, solv->bestrules_end - solv->bestrules); POOL_DEBUG(SOLV_DEBUG_STATS, "overall rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024); /* create weak map */ diff --git a/src/solver.h b/src/solver.h index 08fed65..7ba1f51 100644 --- a/src/solver.h +++ b/src/solver.h @@ -113,6 +113,10 @@ struct _Solver { Id duprules; /* dist upgrade rules */ Id duprules_end; + Id bestrules; /* rules from SOLVER_FORCEBEST */ + Id bestrules_end; + Id *bestrules_pkg; + Id choicerules; /* choice rules (always weak) */ Id choicerules_end; Id *choicerules_ref; @@ -126,6 +130,9 @@ struct _Solver { Map updatemap; /* bring these installed packages to the newest version */ int updatemap_all; /* bring all packages to the newest version */ + Map bestupdatemap; /* create best rule for those packages */ + int bestupdatemap_all; /* bring all packages to the newest version */ + Map fixmap; /* fix these packages */ int fixmap_all; /* fix all packages */ @@ -195,6 +202,7 @@ struct _Solver { int noinfarchcheck; /* true: do not forbid inferior architectures */ int keepexplicitobsoletes; /* true: honor obsoletes during multiinstall */ + int bestobeypolicy; /* true: stay in policy with the best rules */ Map dupmap; /* dup these packages*/ @@ -296,6 +304,7 @@ typedef struct _Solver Solver; #define SOLVER_FLAG_NO_INFARCHCHECK 9 #define SOLVER_FLAG_ALLOW_NAMECHANGE 10 #define SOLVER_FLAG_KEEP_EXPLICIT_OBSOLETES 11 +#define SOLVER_FLAG_BEST_OBEY_POLICY 12 extern Solver *solver_create(Pool *pool); extern void solver_free(Solver *solv); diff --git a/src/solverdebug.c b/src/solverdebug.c index 676c01d..a755da3 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -206,6 +206,8 @@ solver_printruleclass(Solver *solv, int type, Rule *r) POOL_DEBUG(type, "WEAK "); if (solv->learntrules && p >= solv->learntrules) POOL_DEBUG(type, "LEARNT "); + else if (p >= solv->bestrules && p < solv->bestrules_end) + POOL_DEBUG(type, "BEST "); else if (p >= solv->choicerules && p < solv->choicerules_end) POOL_DEBUG(type, "CHOICE "); else if (p >= solv->infarchrules && p < solv->infarchrules_end) @@ -601,6 +603,7 @@ solver_printproblemruleinfo(Solver *solv, Id probr) case SOLVER_RULE_FEATURE: case SOLVER_RULE_LEARNT: case SOLVER_RULE_CHOICE: + case SOLVER_RULE_BEST: POOL_DEBUG(SOLV_DEBUG_RESULT, "bad rule type\n"); return; } @@ -701,6 +704,14 @@ solver_printsolution(Solver *solv, Id problem, Id solution) else POOL_DEBUG(SOLV_DEBUG_RESULT, " - install %s from excluded repository\n", pool_solvable2str(pool, s)); } + else if (p == SOLVER_SOLUTION_BEST) + { + s = pool->solvables + rp; + if (solv->installed && s->repo == solv->installed) + POOL_DEBUG(SOLV_DEBUG_RESULT, " - keep old %s\n", pool_solvable2str(pool, s)); + else + POOL_DEBUG(SOLV_DEBUG_RESULT, " - install %s despite the old version\n", pool_solvable2str(pool, s)); + } else { /* policy, replace p with rp */ @@ -1048,6 +1059,14 @@ solver_solutionelement2str(Solver *solv, Id p, Id rp) else return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " from excluded repository"); } + else if (p == SOLVER_SOLUTION_BEST) + { + Solvable *s = pool->solvables + rp; + if (solv->installed && s->repo == solv->installed) + return pool_tmpjoin(pool, "keep old ", pool_solvable2str(pool, s), 0); + else + return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version"); + } else if (p > 0 && rp == 0) return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0); else if (p > 0 && rp > 0) -- 2.7.4