From: Michael Schroeder Date: Tue, 26 May 2009 10:38:49 +0000 (+0200) Subject: - move rest of rule functions from solver.c to rules.c X-Git-Tag: BASE-SuSE-Code-12_1-Branch~282 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ee15afaf4897db444d2370b41eb806de5e6e02ef;p=platform%2Fupstream%2Flibsolv.git - move rest of rule functions from solver.c to rules.c --- diff --git a/src/rules.c b/src/rules.c index 07b365b..288252a 100644 --- a/src/rules.c +++ b/src/rules.c @@ -31,8 +31,7 @@ static void addrpmruleinfo(Solver *solv, Id p, Id d, int type, Id dep); /*------------------------------------------------------------------- * Check if dependency is possible * - * this mirrors solver_dep_fulfilled - * but uses map m instead of the decisionmap + * mirrors solver_dep_fulfilled but uses map m instead of the decisionmap */ static inline int @@ -162,9 +161,10 @@ solver_unifyrules(Solver *solv) /* adapt rule buffer */ solv->nrules = j; solv->rules = sat_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK); - /* - * debug: statistics - */ + + /* + * debug: log rule statistics + */ IF_POOLDEBUG (SAT_DEBUG_STATS) { int binr = 0; @@ -373,27 +373,12 @@ solver_addrule(Solver *solv, Id p, Id d) return r; } -/*------------------------------------------------------------------- - * disable rule - */ - -static inline void -disablerule(Solver *solv, Rule *r) -{ - if (r->d >= 0) - r->d = -r->d - 1; -} - -/*------------------------------------------------------------------- - * enable rule - */ -static inline void -enablerule(Solver *solv, Rule *r) -{ - if (r->d < 0) - r->d = -r->d - 1; -} +/****************************************************************************** + *** + *** rpm rule part: create rules representing the package dependencies + *** + ***/ /* * special multiversion patch conflict handling: @@ -828,6 +813,691 @@ solver_addrpmrulesforupdaters(Solver *solv, Solvable *s, Map *m, int allow_all) } +/*********************************************************************** + *** + *** Update/Feature rule part + *** + *** Those rules make sure an installed package isn't silently deleted + *** + ***/ + +static Id +finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) +{ + Pool *pool = solv->pool; + int i; + + policy_findupdatepackages(solv, s, qs, allow_all); + if (!qs->count) + { + if (allow_all) + return 0; /* orphaned, don't create feature rule */ + /* check if this is an orphaned package */ + policy_findupdatepackages(solv, s, qs, 1); + if (!qs->count) + return 0; /* orphaned, don't create update rule */ + qs->count = 0; + return -SYSTEMSOLVABLE; /* supported but not installable */ + } + if (allow_all) + return s - pool->solvables; + /* check if it is ok to keep the installed package */ + for (i = 0; i < qs->count; i++) + { + Solvable *ns = pool->solvables + qs->elements[i]; + if (s->evr == ns->evr && solvable_identical(s, ns)) + return s - pool->solvables; + } + /* nope, it must be some other package */ + return -SYSTEMSOLVABLE; +} + +/* add packages from the dup repositories to the update candidates + * this isn't needed for the global dup mode as all packages are + * from dup repos in that case */ +static void +addduppackages(Solver *solv, Solvable *s, Queue *qs) +{ + Queue dupqs; + Id p, dupqsbuf[64]; + int i; + int oldnoupdateprovide = solv->noupdateprovide; + + queue_init_buffer(&dupqs, dupqsbuf, sizeof(dupqsbuf)/sizeof(*dupqsbuf)); + solv->noupdateprovide = 1; + policy_findupdatepackages(solv, s, &dupqs, 2); + solv->noupdateprovide = oldnoupdateprovide; + for (i = 0; i < dupqs.count; i++) + { + p = dupqs.elements[i]; + if (MAPTST(&solv->dupmap, p)) + queue_pushunique(qs, p); + } + queue_free(&dupqs); +} + +/*------------------------------------------------------------------- + * + * add rule for update + * (A|A1|A2|A3...) An = update candidates for A + * + * s = (installed) solvable + */ + +void +solver_addupdaterule(Solver *solv, Solvable *s, int allow_all) +{ + /* installed packages get a special upgrade allowed rule */ + Pool *pool = solv->pool; + Id p, d; + Queue qs; + Id qsbuf[64]; + + POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule -----\n"); + queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); + p = s - pool->solvables; + /* find update candidates for 's' */ + if (solv->distupgrade) + p = finddistupgradepackages(solv, s, &qs, allow_all); + else + policy_findupdatepackages(solv, s, &qs, allow_all); + if (!allow_all && !solv->distupgrade && solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) + addduppackages(solv, s, &qs); + + if (!allow_all && qs.count && solv->noobsoletes.size) + { + int i, j; + + d = pool_queuetowhatprovides(pool, &qs); + /* filter out all noobsoletes packages as they don't update */ + for (i = j = 0; i < qs.count; i++) + { + if (MAPTST(&solv->noobsoletes, qs.elements[i])) + { + /* it's ok if they have same nevra */ + Solvable *ps = pool->solvables + qs.elements[i]; + if (ps->name != s->name || ps->evr != s->evr || ps->arch != s->arch) + continue; + } + qs.elements[j++] = qs.elements[i]; + } + if (j == 0 && p == -SYSTEMSOLVABLE && solv->distupgrade) + { + queue_push(&solv->orphaned, s - pool->solvables); /* treat as orphaned */ + j = qs.count; + } + if (j < qs.count) + { + if (d && solv->updatesystem && solv->installed && s->repo == solv->installed) + { + if (!solv->multiversionupdaters) + solv->multiversionupdaters = sat_calloc(solv->installed->end - solv->installed->start, sizeof(Id)); + solv->multiversionupdaters[s - pool->solvables - solv->installed->start] = d; + } + qs.count = j; + } + } + if (qs.count && p == -SYSTEMSOLVABLE) + p = queue_shift(&qs); + d = qs.count ? pool_queuetowhatprovides(pool, &qs) : 0; + queue_free(&qs); + solver_addrule(solv, p, d); /* allow update of s */ + POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule end -----\n"); +} + +static inline void +disableupdaterule(Solver *solv, Id p) +{ + Rule *r; + + MAPSET(&solv->noupdate, p - solv->installed->start); + r = solv->rules + solv->updaterules + (p - solv->installed->start); + if (r->p && r->d >= 0) + solver_disablerule(solv, r); + r = solv->rules + solv->featurerules + (p - solv->installed->start); + if (r->p && r->d >= 0) + solver_disablerule(solv, r); +} + +static inline void +reenableupdaterule(Solver *solv, Id p) +{ + Pool *pool = solv->pool; + Rule *r; + + MAPCLR(&solv->noupdate, p - solv->installed->start); + r = solv->rules + solv->updaterules + (p - solv->installed->start); + if (r->p) + { + if (r->d >= 0) + return; + solver_enablerule(solv, r); + IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); + } + return; + } + r = solv->rules + solv->featurerules + (p - solv->installed->start); + if (r->p && r->d < 0) + { + solver_enablerule(solv, r); + IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); + } + } +} + + +/*********************************************************************** + *** + *** Infarch rule part + *** + *** Infarch rules make sure the solver uses the best architecture of + *** a package if multiple archetectures are available + *** + ***/ + +void +solver_addinfarchrules(Solver *solv, Map *addedmap) +{ + Pool *pool = solv->pool; + int first, i, j; + Id p, pp, a, aa, bestarch; + Solvable *s, *ps, *bests; + Queue badq, allowedarchs; + + queue_init(&badq); + queue_init(&allowedarchs); + solv->infarchrules = solv->nrules; + for (i = 1; i < pool->nsolvables; i++) + { + if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) + continue; + s = pool->solvables + i; + first = i; + bestarch = 0; + bests = 0; + queue_empty(&allowedarchs); + FOR_PROVIDES(p, pp, s->name) + { + ps = pool->solvables + p; + if (ps->name != s->name || !MAPTST(addedmap, p)) + continue; + if (p == i) + first = 0; + if (first) + break; + a = ps->arch; + a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + if (a != 1 && pool->installed && ps->repo == pool->installed) + { + if (!solv->distupgrade) + queue_pushunique(&allowedarchs, ps->arch); /* also ok to keep this architecture */ + continue; /* ignore installed solvables when calculating the best arch */ + } + if (a && a != 1 && (!bestarch || a < bestarch)) + { + bestarch = a; + bests = ps; + } + } + if (first) + continue; + /* speed up common case where installed package already has best arch */ + if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch) + allowedarchs.count--; /* installed arch is best */ + queue_empty(&badq); + FOR_PROVIDES(p, pp, s->name) + { + ps = pool->solvables + p; + if (ps->name != s->name || !MAPTST(addedmap, p)) + continue; + a = ps->arch; + a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; + if (a != 1 && bestarch && ((a ^ bestarch) & 0xffff0000) != 0) + { + for (j = 0; j < allowedarchs.count; j++) + { + aa = allowedarchs.elements[j]; + if (ps->arch == aa) + break; + aa = (aa <= pool->lastarch) ? pool->id2arch[aa] : 0; + if (aa && ((a ^ aa) & 0xffff0000) == 0) + break; /* compatible */ + } + if (j == allowedarchs.count) + queue_push(&badq, p); + } + } + if (!badq.count) + continue; + /* block all solvables in the badq! */ + for (j = 0; j < badq.count; j++) + { + p = badq.elements[j]; + solver_addrule(solv, -p, 0); + } + } + queue_free(&badq); + queue_free(&allowedarchs); + solv->infarchrules_end = solv->nrules; +} + +static inline void +disableinfarchrule(Solver *solv, Id name) +{ + Pool *pool = solv->pool; + Rule *r; + int i; + for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) + { + if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) + solver_disablerule(solv, r); + } +} + +static inline void +reenableinfarchrule(Solver *solv, Id name) +{ + Pool *pool = solv->pool; + Rule *r; + int i; + for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) + { + if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) + { + solver_enablerule(solv, r); + IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); + } + } + } +} + + +/*********************************************************************** + *** + *** Dup rule part + *** + *** Dup rules make sure a package is selected from the specified dup + *** repositories if an update candidate is included in one of them. + *** + ***/ + +void +solver_createdupmaps(Solver *solv) +{ + Queue *job = &solv->job; + Pool *pool = solv->pool; + Repo *repo; + Id how, what, p, pi, pp, obs, *obsp; + Solvable *s, *ps; + int i; + + map_init(&solv->dupmap, pool->nsolvables); + map_init(&solv->dupinvolvedmap, pool->nsolvables); + for (i = 0; i < job->count; i += 2) + { + how = job->elements[i]; + what = job->elements[i + 1]; + switch (how & SOLVER_JOBMASK) + { + case SOLVER_DISTUPGRADE: + if (what < 0 || what > pool->nrepos) + break; + repo = pool->repos[what]; + FOR_REPO_SOLVABLES(repo, p, s) + { + MAPSET(&solv->dupmap, p); + FOR_PROVIDES(pi, pp, s->name) + { + ps = pool->solvables + pi; + if (ps->name != s->name) + continue; + MAPSET(&solv->dupinvolvedmap, pi); + } + if (s->obsoletes) + { + /* FIXME: check obsoletes/provides combination */ + obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(pi, pp, obs) + { + if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + pi, obs)) + continue; + MAPSET(&solv->dupinvolvedmap, pi); + } + } + } + } + break; + default: + break; + } + } + MAPCLR(&solv->dupinvolvedmap, SYSTEMSOLVABLE); +} + +void +solver_freedupmaps(Solver *solv) +{ + map_free(&solv->dupmap); + map_free(&solv->dupinvolvedmap); +} + +void +solver_addduprules(Solver *solv, Map *addedmap) +{ + Pool *pool = solv->pool; + Id p, pp; + Solvable *s, *ps; + int first, i; + + solv->duprules = solv->nrules; + for (i = 1; i < pool->nsolvables; i++) + { + if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) + continue; + s = pool->solvables + i; + first = i; + FOR_PROVIDES(p, pp, s->name) + { + ps = pool->solvables + p; + if (ps->name != s->name || !MAPTST(addedmap, p)) + continue; + if (p == i) + first = 0; + if (first) + break; + if (!MAPTST(&solv->dupinvolvedmap, p)) + continue; + if (solv->installed && ps->repo == solv->installed) + { + if (!solv->updatemap.size) + map_init(&solv->updatemap, pool->nsolvables); + MAPSET(&solv->updatemap, p); + if (!MAPTST(&solv->dupmap, p)) + { + Id ip, ipp; + /* is installed identical to a good one? */ + FOR_PROVIDES(ip, ipp, s->name) + { + Solvable *is = pool->solvables + ip; + if (!MAPTST(&solv->dupmap, ip)) + continue; + if (is->evr == s->evr && solvable_identical(s, is)) + break; + } + if (!ip) + solver_addrule(solv, -p, 0); /* no match, sorry */ + } + } + else if (!MAPTST(&solv->dupmap, p)) + solver_addrule(solv, -p, 0); + } + } + solv->duprules_end = solv->nrules; +} + + +static inline void +disableduprule(Solver *solv, Id name) +{ + Pool *pool = solv->pool; + Rule *r; + int i; + for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) + { + if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) + solver_disablerule(solv, r); + } +} + +static inline void +reenableduprule(Solver *solv, Id name) +{ + Pool *pool = solv->pool; + Rule *r; + int i; + for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) + { + if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) + { + solver_enablerule(solv, r); + IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) + { + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); + solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); + } + } + } +} + + +/*********************************************************************** + *** + *** Policy rule disabling/reenabling + *** + *** Disable all policy rules that conflict with our jobs. If a job + *** gets disabled later on, reenable the involved policy rules again. + *** + ***/ + +#define DISABLE_UPDATE 1 +#define DISABLE_INFARCH 2 +#define DISABLE_DUP 3 + +static void +jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) +{ + Pool *pool = solv->pool; + Id select, p, pp; + Repo *installed; + Solvable *s; + int i; + + installed = solv->installed; + select = how & SOLVER_SELECTMASK; + switch (how & SOLVER_JOBMASK) + { + case SOLVER_INSTALL: + if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && solv->infarchrules != solv->infarchrules_end && ISRELDEP(what)) + { + Reldep *rd = GETRELDEP(pool, what); + if (rd->flags == REL_ARCH) + { + int qcnt = q->count; + FOR_JOB_SELECT(p, pp, select, what) + { + s = pool->solvables + p; + /* unify names */ + for (i = qcnt; i < q->count; i += 2) + if (q->elements[i + 1] == s->name) + break; + if (i < q->count) + continue; + queue_push(q, DISABLE_INFARCH); + queue_push(q, s->name); + } + } + } + if (select != SOLVER_SOLVABLE) + break; + s = pool->solvables + what; + if (solv->infarchrules != solv->infarchrules_end) + { + queue_push(q, DISABLE_INFARCH); + queue_push(q, s->name); + } + if (solv->duprules != solv->duprules_end) + { + queue_push(q, DISABLE_DUP); + queue_push(q, s->name); + } + if (!installed) + return; + if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what)) + return; + if (s->repo == installed) + { + queue_push(q, DISABLE_UPDATE); + queue_push(q, what); + return; + } + if (s->obsoletes) + { + Id obs, *obsp; + obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + FOR_PROVIDES(p, pp, obs) + { + Solvable *ps = pool->solvables + p; + if (ps->repo != installed) + continue; + if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) + continue; + queue_push(q, DISABLE_UPDATE); + queue_push(q, p); + } + } + FOR_PROVIDES(p, pp, s->name) + { + Solvable *ps = pool->solvables + p; + if (ps->repo != installed) + continue; + if (!solv->implicitobsoleteusesprovides && ps->name != s->name) + continue; + queue_push(q, DISABLE_UPDATE); + queue_push(q, p); + } + return; + case SOLVER_ERASE: + if (!installed) + break; + FOR_JOB_SELECT(p, pp, select, what) + if (pool->solvables[p].repo == installed) + { + queue_push(q, DISABLE_UPDATE); + queue_push(q, p); + } + return; + default: + return; + } +} + +/* disable all policy rules that are in conflict with our job list */ +void +solver_disablepolicyrules(Solver *solv) +{ + Queue *job = &solv->job; + int i, j; + Queue allq; + Rule *r; + Id lastjob = -1; + Id allqbuf[128]; + + queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); + + for (i = solv->jobrules; i < solv->jobrules_end; i++) + { + r = solv->rules + i; + if (r->d < 0) /* disabled? */ + continue; + j = solv->ruletojob.elements[i - solv->jobrules]; + if (j == lastjob) + continue; + lastjob = j; + jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); + } + MAPZERO(&solv->noupdate); + for (i = 0; i < allq.count; i += 2) + { + Id type = allq.elements[i], arg = allq.elements[i + 1]; + switch(type) + { + case DISABLE_UPDATE: + disableupdaterule(solv, arg); + break; + case DISABLE_INFARCH: + disableinfarchrule(solv, arg); + break; + case DISABLE_DUP: + disableduprule(solv, arg); + break; + default: + break; + } + } + queue_free(&allq); +} + +/* we just disabled job #jobidx, now reenable all policy rules that were + * disabled because of this job */ +void +solver_reenablepolicyrules(Solver *solv, int jobidx) +{ + Queue *job = &solv->job; + int i, j; + Queue q, allq; + Rule *r; + Id lastjob = -1; + Id qbuf[32], allqbuf[128]; + + queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); + queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); + jobtodisablelist(solv, job->elements[jobidx], job->elements[jobidx + 1], &q); + if (!q.count) + return; + for (i = solv->jobrules; i < solv->jobrules_end; i++) + { + r = solv->rules + i; + if (r->d < 0) /* disabled? */ + continue; + j = solv->ruletojob.elements[i - solv->jobrules]; + if (j == lastjob) + continue; + lastjob = j; + jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); + } + for (j = 0; j < q.count; j += 2) + { + Id type = q.elements[j], arg = q.elements[j + 1]; + for (i = 0; i < allq.count; i += 2) + if (allq.elements[i] == type && allq.elements[i + 1] == arg) + break; + if (i < allq.count) + continue; /* still disabled */ + switch(type) + { + case DISABLE_UPDATE: + reenableupdaterule(solv, arg); + break; + case DISABLE_INFARCH: + reenableinfarchrule(solv, arg); + break; + case DISABLE_DUP: + reenableduprule(solv, arg); + break; + } + } + queue_free(&allq); + queue_free(&q); +} + + +/*********************************************************************** + *** + *** Rule info part, tell the user what the rule is about. + *** + ***/ static void addrpmruleinfo(Solver *solv, Id p, Id d, int type, Id dep) diff --git a/src/rules.h b/src/rules.h index 084fecd..d9f4e36 100644 --- a/src/rules.h +++ b/src/rules.h @@ -95,9 +95,28 @@ solver_enablerule(struct _Solver *solv, Rule *r) Rule *solver_addrule(struct _Solver *solv, Id p, Id d); void solver_unifyrules(struct _Solver *solv); int solver_samerule(struct _Solver *solv, Rule *r1, Rule *r2); + +/* rpm rules */ void solver_addrpmrulesforsolvable(struct _Solver *solv, Solvable *s, Map *m); void solver_addrpmrulesforweak(struct _Solver *solv, Map *m); void solver_addrpmrulesforupdaters(struct _Solver *solv, Solvable *s, Map *m, int allow_all); + +/* update/feature rules */ +void solver_addupdaterule(struct _Solver *solv, Solvable *s, int allow_all); + +/* infarch rules */ +void solver_addinfarchrules(struct _Solver *solv, Map *addedmap); + +/* dup rules */ +void solver_createdupmaps(struct _Solver *solv); +void solver_freedupmaps(struct _Solver *solv); +void solver_addduprules(struct _Solver *solv, Map *addedmap); + +/* policy rule disabling/reenabling */ +void solver_disablepolicyrules(struct _Solver *solv); +void solver_reenablepolicyrules(struct _Solver *solv, int jobidx); + +/* rule info */ int solver_allruleinfos(struct _Solver *solv, Id rid, Queue *rq); SolverRuleinfo solver_ruleinfo(struct _Solver *solv, Id rid, Id *fromp, Id *top, Id *depp); diff --git a/src/solver.c b/src/solver.c index 5854e1e..f551865 100644 --- a/src/solver.c +++ b/src/solver.c @@ -396,458 +396,6 @@ enabledisablelearntrules(Solver *solv) } -/*------------------------------------------------------------------- - * policy rule enabling/disabling - * - * we need to disable policy rules that conflict with our job list, and - * also reenable such rules with the job was changed due to solution generation - * - */ - -static inline void -disableinfarchrule(Solver *solv, Id name) -{ - Pool *pool = solv->pool; - Rule *r; - int i; - for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) - { - if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) - solver_disablerule(solv, r); - } -} - -static inline void -reenableinfarchrule(Solver *solv, Id name) -{ - Pool *pool = solv->pool; - Rule *r; - int i; - for (i = solv->infarchrules, r = solv->rules + i; i < solv->infarchrules_end; i++, r++) - { - if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) - { - solver_enablerule(solv, r); - IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) - { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); - } - } - } -} - -static inline void -disableduprule(Solver *solv, Id name) -{ - Pool *pool = solv->pool; - Rule *r; - int i; - for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) - { - if (r->p < 0 && r->d >= 0 && pool->solvables[-r->p].name == name) - solver_disablerule(solv, r); - } -} - -static inline void -reenableduprule(Solver *solv, Id name) -{ - Pool *pool = solv->pool; - Rule *r; - int i; - for (i = solv->duprules, r = solv->rules + i; i < solv->duprules_end; i++, r++) - { - if (r->p < 0 && r->d < 0 && pool->solvables[-r->p].name == name) - { - solver_enablerule(solv, r); - IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) - { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); - } - } - } -} - -static inline void -disableupdaterule(Solver *solv, Id p) -{ - Rule *r; - - MAPSET(&solv->noupdate, p - solv->installed->start); - r = solv->rules + solv->updaterules + (p - solv->installed->start); - if (r->p && r->d >= 0) - solver_disablerule(solv, r); - r = solv->rules + solv->featurerules + (p - solv->installed->start); - if (r->p && r->d >= 0) - solver_disablerule(solv, r); -} - -static inline void -reenableupdaterule(Solver *solv, Id p) -{ - Pool *pool = solv->pool; - Rule *r; - - MAPCLR(&solv->noupdate, p - solv->installed->start); - r = solv->rules + solv->updaterules + (p - solv->installed->start); - if (r->p) - { - if (r->d >= 0) - return; - solver_enablerule(solv, r); - IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) - { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); - } - return; - } - r = solv->rules + solv->featurerules + (p - solv->installed->start); - if (r->p && r->d < 0) - { - solver_enablerule(solv, r); - IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) - { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "@@@ re-enabling "); - solver_printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); - } - } -} - -#define DISABLE_UPDATE 1 -#define DISABLE_INFARCH 2 -#define DISABLE_DUP 3 - -static void -jobtodisablelist(Solver *solv, Id how, Id what, Queue *q) -{ - Pool *pool = solv->pool; - Id select, p, pp; - Repo *installed; - Solvable *s; - int i; - - installed = solv->installed; - select = how & SOLVER_SELECTMASK; - switch (how & SOLVER_JOBMASK) - { - case SOLVER_INSTALL: - if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && solv->infarchrules != solv->infarchrules_end && ISRELDEP(what)) - { - Reldep *rd = GETRELDEP(pool, what); - if (rd->flags == REL_ARCH) - { - int qcnt = q->count; - FOR_JOB_SELECT(p, pp, select, what) - { - s = pool->solvables + p; - /* unify names */ - for (i = qcnt; i < q->count; i += 2) - if (q->elements[i + 1] == s->name) - break; - if (i < q->count) - continue; - queue_push(q, DISABLE_INFARCH); - queue_push(q, s->name); - } - } - } - if (select != SOLVER_SOLVABLE) - break; - s = pool->solvables + what; - if (solv->infarchrules != solv->infarchrules_end) - { - queue_push(q, DISABLE_INFARCH); - queue_push(q, s->name); - } - if (solv->duprules != solv->duprules_end) - { - queue_push(q, DISABLE_DUP); - queue_push(q, s->name); - } - if (!installed) - return; - if (solv->noobsoletes.size && MAPTST(&solv->noobsoletes, what)) - return; - if (s->repo == installed) - { - queue_push(q, DISABLE_UPDATE); - queue_push(q, what); - return; - } - if (s->obsoletes) - { - Id obs, *obsp; - obsp = s->repo->idarraydata + s->obsoletes; - while ((obs = *obsp++) != 0) - FOR_PROVIDES(p, pp, obs) - { - Solvable *ps = pool->solvables + p; - if (ps->repo != installed) - continue; - if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) - continue; - queue_push(q, DISABLE_UPDATE); - queue_push(q, p); - } - } - FOR_PROVIDES(p, pp, s->name) - { - Solvable *ps = pool->solvables + p; - if (ps->repo != installed) - continue; - if (!solv->implicitobsoleteusesprovides && ps->name != s->name) - continue; - queue_push(q, DISABLE_UPDATE); - queue_push(q, p); - } - return; - case SOLVER_ERASE: - if (!installed) - break; - FOR_JOB_SELECT(p, pp, select, what) - if (pool->solvables[p].repo == installed) - { - queue_push(q, DISABLE_UPDATE); - queue_push(q, p); - } - return; - default: - return; - } -} - -/* disable all policy rules that are in conflict with our job list */ -void -solver_disablepolicyrules(Solver *solv) -{ - Queue *job = &solv->job; - int i, j; - Queue allq; - Rule *r; - Id lastjob = -1; - Id allqbuf[128]; - - queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); - - for (i = solv->jobrules; i < solv->jobrules_end; i++) - { - r = solv->rules + i; - if (r->d < 0) /* disabled? */ - continue; - j = solv->ruletojob.elements[i - solv->jobrules]; - if (j == lastjob) - continue; - lastjob = j; - jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); - } - MAPZERO(&solv->noupdate); - for (i = 0; i < allq.count; i += 2) - { - Id type = allq.elements[i], arg = allq.elements[i + 1]; - switch(type) - { - case DISABLE_UPDATE: - disableupdaterule(solv, arg); - break; - case DISABLE_INFARCH: - disableinfarchrule(solv, arg); - break; - case DISABLE_DUP: - disableduprule(solv, arg); - break; - default: - break; - } - } - queue_free(&allq); -} - -/* we just disabled job #jobidx, now reenable all policy rules that were - * disabled because of this job */ -void -solver_reenablepolicyrules(Solver *solv, int jobidx) -{ - Queue *job = &solv->job; - int i, j; - Queue q, allq; - Rule *r; - Id lastjob = -1; - Id qbuf[32], allqbuf[128]; - - queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf)); - queue_init_buffer(&allq, allqbuf, sizeof(allqbuf)/sizeof(*allqbuf)); - jobtodisablelist(solv, job->elements[jobidx], job->elements[jobidx + 1], &q); - if (!q.count) - return; - for (i = solv->jobrules; i < solv->jobrules_end; i++) - { - r = solv->rules + i; - if (r->d < 0) /* disabled? */ - continue; - j = solv->ruletojob.elements[i - solv->jobrules]; - if (j == lastjob) - continue; - lastjob = j; - jobtodisablelist(solv, job->elements[j], job->elements[j + 1], &allq); - } - for (j = 0; j < q.count; j += 2) - { - Id type = q.elements[j], arg = q.elements[j + 1]; - for (i = 0; i < allq.count; i += 2) - if (allq.elements[i] == type && allq.elements[i + 1] == arg) - break; - if (i < allq.count) - continue; /* still disabled */ - switch(type) - { - case DISABLE_UPDATE: - reenableupdaterule(solv, arg); - break; - case DISABLE_INFARCH: - reenableinfarchrule(solv, arg); - break; - case DISABLE_DUP: - reenableduprule(solv, arg); - break; - } - } - queue_free(&allq); - queue_free(&q); -} - -/*------------------------------------------------------------------- - * rule generation - * - */ - -static Id -finddistupgradepackages(Solver *solv, Solvable *s, Queue *qs, int allow_all) -{ - Pool *pool = solv->pool; - int i; - - policy_findupdatepackages(solv, s, qs, allow_all); - if (!qs->count) - { - if (allow_all) - return 0; /* orphaned, don't create feature rule */ - /* check if this is an orphaned package */ - policy_findupdatepackages(solv, s, qs, 1); - if (!qs->count) - return 0; /* orphaned, don't create update rule */ - qs->count = 0; - return -SYSTEMSOLVABLE; /* supported but not installable */ - } - if (allow_all) - return s - pool->solvables; - /* check if it is ok to keep the installed package */ - for (i = 0; i < qs->count; i++) - { - Solvable *ns = pool->solvables + qs->elements[i]; - if (s->evr == ns->evr && solvable_identical(s, ns)) - return s - pool->solvables; - } - /* nope, it must be some other package */ - return -SYSTEMSOLVABLE; -} - -/* add packages from the dup repositories to the update candidates - * this isn't needed for the global dup mode as all packages are - * from dup repos in that case */ -static void -addduppackages(Solver *solv, Solvable *s, Queue *qs) -{ - Queue dupqs; - Id p, dupqsbuf[64]; - int i; - int oldnoupdateprovide = solv->noupdateprovide; - - queue_init_buffer(&dupqs, dupqsbuf, sizeof(dupqsbuf)/sizeof(*dupqsbuf)); - solv->noupdateprovide = 1; - policy_findupdatepackages(solv, s, &dupqs, 2); - solv->noupdateprovide = oldnoupdateprovide; - for (i = 0; i < dupqs.count; i++) - { - p = dupqs.elements[i]; - if (MAPTST(&solv->dupmap, p)) - queue_pushunique(qs, p); - } - queue_free(&dupqs); -} - -/*------------------------------------------------------------------- - * - * add rule for update - * (A|A1|A2|A3...) An = update candidates for A - * - * s = (installed) solvable - */ - -static void -addupdaterule(Solver *solv, Solvable *s, int allow_all) -{ - /* installed packages get a special upgrade allowed rule */ - Pool *pool = solv->pool; - Id p, d; - Queue qs; - Id qsbuf[64]; - - POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule -----\n"); - queue_init_buffer(&qs, qsbuf, sizeof(qsbuf)/sizeof(*qsbuf)); - p = s - pool->solvables; - /* find update candidates for 's' */ - if (solv->distupgrade) - p = finddistupgradepackages(solv, s, &qs, allow_all); - else - policy_findupdatepackages(solv, s, &qs, allow_all); - if (!allow_all && !solv->distupgrade && solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p)) - addduppackages(solv, s, &qs); - - if (!allow_all && qs.count && solv->noobsoletes.size) - { - int i, j; - - d = pool_queuetowhatprovides(pool, &qs); - /* filter out all noobsoletes packages as they don't update */ - for (i = j = 0; i < qs.count; i++) - { - if (MAPTST(&solv->noobsoletes, qs.elements[i])) - { - /* it's ok if they have same nevra */ - Solvable *ps = pool->solvables + qs.elements[i]; - if (ps->name != s->name || ps->evr != s->evr || ps->arch != s->arch) - continue; - } - qs.elements[j++] = qs.elements[i]; - } - if (j == 0 && p == -SYSTEMSOLVABLE && solv->distupgrade) - { - queue_push(&solv->orphaned, s - pool->solvables); /* treat as orphaned */ - j = qs.count; - } - if (j < qs.count) - { - if (d && solv->updatesystem && solv->installed && s->repo == solv->installed) - { - if (!solv->multiversionupdaters) - solv->multiversionupdaters = sat_calloc(solv->installed->end - solv->installed->start, sizeof(Id)); - solv->multiversionupdaters[s - pool->solvables - solv->installed->start] = d; - } - qs.count = j; - } - } - if (qs.count && p == -SYSTEMSOLVABLE) - p = queue_shift(&qs); - d = qs.count ? pool_queuetowhatprovides(pool, &qs) : 0; - queue_free(&qs); - solver_addrule(solv, p, d); /* allow update of s */ - POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- addupdaterule end -----\n"); -} - - /********************************************************************/ /* watches */ @@ -2604,208 +2152,6 @@ weaken_solvable_deps(Solver *solv, Id p) static void -addinfarchrules(Solver *solv, Map *addedmap) -{ - Pool *pool = solv->pool; - int first, i, j; - Id p, pp, a, aa, bestarch; - Solvable *s, *ps, *bests; - Queue badq, allowedarchs; - - queue_init(&badq); - queue_init(&allowedarchs); - solv->infarchrules = solv->nrules; - for (i = 1; i < pool->nsolvables; i++) - { - if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) - continue; - s = pool->solvables + i; - first = i; - bestarch = 0; - bests = 0; - queue_empty(&allowedarchs); - FOR_PROVIDES(p, pp, s->name) - { - ps = pool->solvables + p; - if (ps->name != s->name || !MAPTST(addedmap, p)) - continue; - if (p == i) - first = 0; - if (first) - break; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; - if (a != 1 && pool->installed && ps->repo == pool->installed) - { - if (!solv->distupgrade) - queue_pushunique(&allowedarchs, ps->arch); /* also ok to keep this architecture */ - continue; /* ignore installed solvables when calculating the best arch */ - } - if (a && a != 1 && (!bestarch || a < bestarch)) - { - bestarch = a; - bests = ps; - } - } - if (first) - continue; - /* speed up common case where installed package already has best arch */ - if (allowedarchs.count == 1 && bests && allowedarchs.elements[0] == bests->arch) - allowedarchs.count--; /* installed arch is best */ - queue_empty(&badq); - FOR_PROVIDES(p, pp, s->name) - { - ps = pool->solvables + p; - if (ps->name != s->name || !MAPTST(addedmap, p)) - continue; - a = ps->arch; - a = (a <= pool->lastarch) ? pool->id2arch[a] : 0; - if (a != 1 && bestarch && ((a ^ bestarch) & 0xffff0000) != 0) - { - for (j = 0; j < allowedarchs.count; j++) - { - aa = allowedarchs.elements[j]; - if (ps->arch == aa) - break; - aa = (aa <= pool->lastarch) ? pool->id2arch[aa] : 0; - if (aa && ((a ^ aa) & 0xffff0000) == 0) - break; /* compatible */ - } - if (j == allowedarchs.count) - queue_push(&badq, p); - } - } - if (!badq.count) - continue; - /* block all solvables in the badq! */ - for (j = 0; j < badq.count; j++) - { - p = badq.elements[j]; - solver_addrule(solv, -p, 0); - } - } - queue_free(&badq); - queue_free(&allowedarchs); - solv->infarchrules_end = solv->nrules; -} - -static void -createdupmaps(Solver *solv, Queue *job) -{ - Pool *pool = solv->pool; - Repo *repo; - Id how, what, p, pi, pp, obs, *obsp; - Solvable *s, *ps; - int i; - - map_init(&solv->dupmap, pool->nsolvables); - map_init(&solv->dupinvolvedmap, pool->nsolvables); - for (i = 0; i < job->count; i += 2) - { - how = job->elements[i]; - what = job->elements[i + 1]; - switch (how & SOLVER_JOBMASK) - { - case SOLVER_DISTUPGRADE: - if (what < 0 || what > pool->nrepos) - break; - repo = pool->repos[what]; - FOR_REPO_SOLVABLES(repo, p, s) - { - MAPSET(&solv->dupmap, p); - FOR_PROVIDES(pi, pp, s->name) - { - ps = pool->solvables + pi; - if (ps->name != s->name) - continue; - MAPSET(&solv->dupinvolvedmap, pi); - } - if (s->obsoletes) - { - /* FIXME: check obsoletes/provides combination */ - obsp = s->repo->idarraydata + s->obsoletes; - while ((obs = *obsp++) != 0) - { - FOR_PROVIDES(pi, pp, obs) - { - if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + pi, obs)) - continue; - MAPSET(&solv->dupinvolvedmap, pi); - } - } - } - } - break; - default: - break; - } - } - MAPCLR(&solv->dupinvolvedmap, SYSTEMSOLVABLE); -} - -static void -freedupmaps(Solver *solv) -{ - map_free(&solv->dupmap); - map_free(&solv->dupinvolvedmap); -} - -static void -addduprules(Solver *solv, Map *addedmap) -{ - Pool *pool = solv->pool; - Id p, pp; - Solvable *s, *ps; - int first, i; - - solv->duprules = solv->nrules; - for (i = 1; i < pool->nsolvables; i++) - { - if (i == SYSTEMSOLVABLE || !MAPTST(addedmap, i)) - continue; - s = pool->solvables + i; - first = i; - FOR_PROVIDES(p, pp, s->name) - { - ps = pool->solvables + p; - if (ps->name != s->name || !MAPTST(addedmap, p)) - continue; - if (p == i) - first = 0; - if (first) - break; - if (!MAPTST(&solv->dupinvolvedmap, p)) - continue; - if (solv->installed && ps->repo == solv->installed) - { - if (!solv->updatemap.size) - map_init(&solv->updatemap, pool->nsolvables); - MAPSET(&solv->updatemap, p); - if (!MAPTST(&solv->dupmap, p)) - { - Id ip, ipp; - /* is installed identical to a good one? */ - FOR_PROVIDES(ip, ipp, s->name) - { - Solvable *is = pool->solvables + ip; - if (!MAPTST(&solv->dupmap, ip)) - continue; - if (is->evr == s->evr && solvable_identical(s, is)) - break; - } - if (!ip) - solver_addrule(solv, -p, 0); /* no match, sorry */ - } - } - else if (!MAPTST(&solv->dupmap, p)) - solver_addrule(solv, -p, 0); - } - } - solv->duprules_end = solv->nrules; -} - - -static void findrecommendedsuggested(Solver *solv) { Pool *pool = solv->pool; @@ -3162,7 +2508,7 @@ solver_solve(Solver *solv, Queue *job) /* create dup maps if needed. We need the maps early to create our * update rules */ if (hasdupjob) - createdupmaps(solv, job); + solver_createdupmaps(solv); /* * create feature rules @@ -3188,7 +2534,7 @@ solver_solve(Solver *solv, Queue *job) solver_addrule(solv, 0, 0); /* create dummy rule */ continue; } - addupdaterule(solv, s, 1); /* allow s to be updated */ + solver_addupdaterule(solv, s, 1); /* allow s to be updated */ } /* make sure we accounted for all rules */ assert(solv->nrules - solv->featurerules == installed->end - installed->start); @@ -3217,7 +2563,7 @@ solver_solve(Solver *solv, Queue *job) solver_addrule(solv, 0, 0); /* create dummy rule */ continue; } - addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */ + solver_addupdaterule(solv, s, 0); /* allowall = 0: downgrades not allowed */ /* * check for and remove duplicate */ @@ -3405,14 +2751,14 @@ solver_solve(Solver *solv, Queue *job) /* now create infarch and dup rules */ if (!solv->noinfarchcheck) - addinfarchrules(solv, &addedmap); + solver_addinfarchrules(solv, &addedmap); else solv->infarchrules = solv->infarchrules_end = solv->nrules; if (hasdupjob) { - addduprules(solv, &addedmap); - freedupmaps(solv); /* no longer needed */ + solver_addduprules(solv, &addedmap); + solver_freedupmaps(solv); /* no longer needed */ } else solv->duprules = solv->duprules_end = solv->nrules; diff --git a/src/solver.h b/src/solver.h index aaf0bea..08e6101 100644 --- a/src/solver.h +++ b/src/solver.h @@ -271,8 +271,6 @@ extern void solver_solve(Solver *solv, Queue *job); extern void solver_run_sat(Solver *solv, int disablerules, int doweak); extern void solver_reset(Solver *solv); -extern void solver_reenablepolicyrules(Solver *solv, int jobidx); -extern void solver_disablepolicyrules(Solver *solv); extern int solver_dep_installed(Solver *solv, Id dep); extern int solver_splitprovides(Solver *solv, Id dep);