From 21090e6067660e4a22d6227118d5cfc30629d548 Mon Sep 17 00:00:00 2001 From: Nicola Sella Date: Wed, 7 Dec 2022 16:11:10 +0100 Subject: [PATCH 1/3] Revert "Improve choice rule generation" This reverts commit 1da9bef88dd269055cbd7eda2f3572963d6d9b64. --- src/rules.c | 169 ++++++++++++++++++++++++++++++++++++++------------- src/solver.c | 45 -------------- 2 files changed, 126 insertions(+), 88 deletions(-) diff --git a/src/rules.c b/src/rules.c index 2c56959c..a260c2de 100644 --- a/src/rules.c +++ b/src/rules.c @@ -3255,12 +3255,6 @@ solver_rule2rules(Solver *solv, Id rid, Queue *q, int recursive) /* check if the newest versions of pi still provides the dependency we're looking for */ -/* pi: installed package - * r: rule for the dependency - * m: map with all positive elements of r - * return 0: at least one provider - * return 1: the newest versions do not provide the dependency - */ static int solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) { @@ -3309,6 +3303,94 @@ solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q) return 1; /* none of the new packages provided it */ } +static int +solver_choicerulecheck2(Solver *solv, Id pi, Id pt, Queue *q) +{ + Pool *pool = solv->pool; + Rule *ur; + Id p, pp; + int i; + + if (!q->count || q->elements[0] != pi) + { + if (q->count) + queue_empty(q); + ur = solv->rules + solv->updaterules + (pi - pool->installed->start); + if (!ur->p) + ur = solv->rules + solv->featurerules + (pi - pool->installed->start); + if (!ur->p) + return 1; /* orphaned, thus newest */ + queue_push2(q, pi, 0); + FOR_RULELITERALS(p, pp, ur) + if (p > 0 && p != pi) + queue_push(q, p); + queue_push(q, pi); + } + if (q->count <= 3) + return q->count == 3 && q->elements[2] == pt ? 1 : 0; + if (!q->elements[1]) + { + queue_deleten(q, 0, 2); + policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); + queue_unshift(q, 1); /* filter mark */ + queue_unshift(q, pi); + } + for (i = 2; i < q->count; i++) + if (q->elements[i] == pt) + return 1; + return 0; /* not newest */ +} + +static int +solver_choicerulecheck3(Solver *solv, Id pt, Queue *q) +{ + Pool *pool = solv->pool; + Id p, pp; + int i; + + if (!q->count || q->elements[0] != pt) + { + Solvable *s = pool->solvables + pt; + if (q->count) + queue_empty(q); + /* no installed package, so check all with same name */ + queue_push2(q, pt, 0); + FOR_PROVIDES(p, pp, s->name) + if (pool->solvables[p].name == s->name && p != pt) + queue_push(q, p); + queue_push(q, pt); + } + if (q->count <= 3) + return q->count == 3 && q->elements[2] == pt ? 1 : 0; + if (!q->elements[1]) + { + queue_deleten(q, 0, 2); + policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE); + queue_unshift(q, 1); /* filter mark */ + queue_unshift(q, pt); + } + for (i = 2; i < q->count; i++) + if (q->elements[i] == pt) + return 1; + return 0; /* not newest */ +} + +static inline void +queue_removeelement(Queue *q, Id el) +{ + int i, j; + for (i = 0; i < q->count; i++) + if (q->elements[i] == el) + break; + if (i < q->count) + { + for (j = i++; i < q->count; i++) + if (q->elements[i] != el) + q->elements[j++] = q->elements[i]; + queue_truncate(q, j); + } +} + static Id choicerule_find_installed(Pool *pool, Id p) { @@ -3357,14 +3439,14 @@ solver_addchoicerules(Solver *solv) Pool *pool = solv->pool; Map m, mneg; Rule *r; - Queue q, qi, qcheck, infoq; + Queue q, qi, qcheck, qcheck2, infoq; int i, j, rid, havechoice, negcnt; Id p, d, pp, p2; Solvable *s; Id lastaddedp, lastaddedd; int lastaddedcnt; unsigned int now; - int isinstalled; + int isnewest = 0; solv->choicerules = solv->nrules; if (!pool->installed) @@ -3376,6 +3458,7 @@ solver_addchoicerules(Solver *solv) queue_init(&q); queue_init(&qi); queue_init(&qcheck); + queue_init(&qcheck2); queue_init(&infoq); map_init(&m, pool->nsolvables); map_init(&mneg, pool->nsolvables); @@ -3395,28 +3478,20 @@ solver_addchoicerules(Solver *solv) if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 <= 0)) continue; /* only look at requires rules */ /* solver_printrule(solv, SOLV_DEBUG_RESULT, r); */ + queue_empty(&q); queue_empty(&qi); havechoice = 0; - isinstalled = 0; FOR_RULELITERALS(p, pp, r) { if (p < 0) - { - Solvable *s = pool->solvables - p; - p2 = s->repo == pool->installed ? -p : 0; - if (p2) - { - if (!(solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start)))) - isinstalled = 1; - } - continue; - } + continue; s = pool->solvables + p; if (!s->repo) continue; if (s->repo == pool->installed) { queue_push2(&qi, p, p); + queue_push(&q, p); continue; } /* find an installed package p2 that we can update/downgrade to p */ @@ -3428,6 +3503,7 @@ solver_addchoicerules(Solver *solv) if (policy_is_illegal(solv, pool->solvables + p2, s, 0)) continue; queue_push2(&qi, p2, p); + queue_push(&q, p); continue; } /* package p is independent of the installed ones */ @@ -3436,31 +3512,47 @@ solver_addchoicerules(Solver *solv) #if 0 printf("havechoice: %d qcount %d qicount %d\n", havechoice, q.count, qi.count); #endif - if (!havechoice || !qi.count) + if (!havechoice || !q.count || !qi.count) continue; /* no choice */ FOR_RULELITERALS(p, pp, r) if (p > 0) MAPSET(&m, p); - if (!isinstalled) + isnewest = 1; + FOR_RULELITERALS(p, pp, r) { - /* do extra checking for packages related to installed packages */ - for (i = j = 0; i < qi.count; i += 2) + if (p > 0) + break; + p2 = choicerule_find_installed(pool, -p); + if (p2 && !solver_choicerulecheck2(solv, p2, -p, &qcheck2)) { - p2 = qi.elements[i]; - if (solv->updatemap_all || (solv->updatemap.size && MAPTST(&solv->updatemap, p2 - solv->installed->start))) - { - if (solver_choicerulecheck(solv, p2, r, &m, &qcheck)) - continue; - } - qi.elements[j++] = p2; - qi.elements[j++] = qi.elements[i + 1]; + isnewest = 0; + break; + } + if (!p2 && !solver_choicerulecheck3(solv, -p, &qcheck2)) + { + isnewest = 0; + break; } - queue_truncate(&qi, j); } + /* do extra checking */ + for (i = j = 0; i < qi.count; i += 2) + { + p2 = qi.elements[i]; + if (!p2) + continue; + if (isnewest && solver_choicerulecheck(solv, p2, r, &m, &qcheck)) + { + /* oops, remove element p from q */ + queue_removeelement(&q, qi.elements[i + 1]); + continue; + } + qi.elements[j++] = p2; + } + queue_truncate(&qi, j); - if (!qi.count) + if (!q.count || !qi.count) { FOR_RULELITERALS(p, pp, r) if (p > 0) @@ -3468,15 +3560,6 @@ solver_addchoicerules(Solver *solv) continue; } - queue_empty(&q); - /* split q from qi */ - for (i = j = 0; i < qi.count; i += 2) - { - queue_push(&q, qi.elements[i + 1]); - qi.elements[j++] = qi.elements[i]; - } - queue_truncate(&qi, j); - /* now check the update rules of the installed package. * if all packages of the update rules are contained in @@ -3496,7 +3579,6 @@ solver_addchoicerules(Solver *solv) break; if (p) break; - /* speed improvement: only check each package once */ for (j = i + 1; j < qi.count; j++) if (qi.elements[i] == qi.elements[j]) qi.elements[j] = 0; @@ -3554,6 +3636,7 @@ solver_addchoicerules(Solver *solv) queue_free(&q); queue_free(&qi); queue_free(&qcheck); + queue_free(&qcheck2); queue_free(&infoq); map_free(&m); map_free(&mneg); diff --git a/src/solver.c b/src/solver.c index 28341d6d..23285ff2 100644 --- a/src/solver.c +++ b/src/solver.c @@ -2620,43 +2620,6 @@ resolve_orphaned(Solver *solv, int level, int disablerules, Queue *dq, int *reru return level; } -int -solver_check_unneeded_choicerules(Solver *solv) -{ - Pool *pool = solv->pool; - Rule *r, *or; - Id p, pp, p2, pp2; - int i; - int havedisabled = 0; - - /* check if some choice rules could have been broken */ - for (i = solv->choicerules, r = solv->rules + i; i < solv->choicerules_end; i++, r++) - { - if (r->d < 0) - continue; - or = solv->rules + solv->choicerules_info[i - solv->choicerules]; - if (or->d < 0) - continue; - FOR_RULELITERALS(p, pp, or) - { - if (p < 0 || solv->decisionmap[p] <= 0) - continue; - FOR_RULELITERALS(p2, pp2, r) - if (p2 == p) - break; - if (!p2) - { - /* did not find p in choice rule, disable it */ - POOL_DEBUG(SOLV_DEBUG_SOLVER, "disabling unneeded choice rule #%d\n", i); - solver_disablechoicerules(solv, r); - havedisabled = 1; - break; - } - } - } - return havedisabled; -} - /*------------------------------------------------------------------- * * solver_run_sat @@ -2842,14 +2805,6 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) continue; } - if (solv->choicerules != solv->choicerules_end && solver_check_unneeded_choicerules(solv)) - { - POOL_DEBUG(SOLV_DEBUG_SOLVER, "did choice rule minimization, rerunning solver\n"); - solver_reset(solv); - level = 0; /* restart from scratch */ - continue; - } - if (solv->solution_callback) { solv->solution_callback(solv, solv->solution_callback_data); -- 2.38.1