diff options
author | Michael Schroeder <mls@suse.de> | 2014-03-07 16:55:36 +0100 |
---|---|---|
committer | Michael Schroeder <mls@suse.de> | 2014-03-07 16:55:36 +0100 |
commit | ab5d2c56c168ae56fea013007798039228be5529 (patch) | |
tree | e89b853e6f3487740e34aefe6404ff58721c3001 | |
parent | ab01c1711732273e571d70dbbbd2da6d0645f774 (diff) | |
download | libsolv-ab5d2c56c168ae56fea013007798039228be5529.tar.gz libsolv-ab5d2c56c168ae56fea013007798039228be5529.tar.bz2 libsolv-ab5d2c56c168ae56fea013007798039228be5529.zip |
also support complex deps when doing recommends/suggests filtering
-rw-r--r-- | src/policy.c | 160 | ||||
-rw-r--r-- | src/solver.c | 119 | ||||
-rw-r--r-- | src/solver.h | 2 |
3 files changed, 199 insertions, 82 deletions
diff --git a/src/policy.c b/src/policy.c index 6287b7c..98991c5 100644 --- a/src/policy.c +++ b/src/policy.c @@ -21,6 +21,7 @@ #include "policy.h" #include "poolvendor.h" #include "poolarch.h" +#include "cplxdeps.h" /*-----------------------------------------------------------------*/ @@ -217,6 +218,119 @@ solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist) } +#ifdef ENABLE_COMPLEX_DEPS + +static void +check_complex_dep(Solver *solv, Id dep, Map *m, Queue **cqp) +{ + Pool *pool = solv->pool; + Queue q; + queue_init(&q); + Id p; + int i, qcnt; + +#if 0 + printf("check_complex_dep %s\n", pool_dep2str(pool, dep)); +#endif + i = pool_normalize_complex_dep(pool, dep, &q, CPLXDEPS_EXPAND); + if (i == 0 || i == 1) + { + queue_free(&q); + return; + } + qcnt = q.count; + for (i = 0; i < qcnt; i++) + { + for (; (p = q.elements[i]) != 0; i++) + { + if (p < 0) + { + if (solv->decisionmap[-p] > 0) + continue; + if (solv->decisionmap[-p] < 0) + break; + queue_push(&q, -p); + } + if (p > 0 && qcnt == q.count) + MAPSET(m, p); + } + if (q.elements[i]) + { +#if 0 + printf("complex dep block cannot be true\n"); +#endif + while (q.elements[i]) + i++; + if (qcnt != q.count) + queue_truncate(&q, qcnt); + } + else if (qcnt != q.count) + { + int j, k; + Queue *cq = *cqp; +#if 0 + printf("add new complex dep block\n"); + for (j = qcnt; j < q.count; j++) + printf(" - %s\n", pool_solvid2str(pool, q.elements[j])); +#endif + if (!cq) + { + cq = solv_calloc(1, sizeof(Queue)); + queue_init(cq); + *cqp = cq; + queue_insertn(cq, 0, 256, 0); + } + for (j = qcnt; j < q.count; j++) + { + p = q.elements[j]; + for (k = 256; k < cq->count; k += 2) + if (cq->elements[k + 1] == dep && cq->elements[k] == p) + break; + if (k == cq->count) + { + queue_push2(cq, p, dep); + cq->elements[p & 255] |= (1 << (p >> 8 & 31)); + } + } + queue_truncate(&q, qcnt); + } + } + queue_free(&q); +} + +static void +recheck_complex_dep(Solver *solv, Id p, Map *m, Queue **cqp) +{ + Queue *cq = *cqp; + int i; +#if 0 + printf("recheck_complex_dep for package %s\n", pool_solvid2str(solv->pool, p)); +#endif + for (i = 256; i < cq->count; i += 2) + if (cq->elements[i] == p) + break; + if (i == cq->count) + return; /* false alert */ + if (solv->decisionmap[p] <= 0) + return; /* just in case... */ + memset(cq->elements, 0, sizeof(Id) * 256); + for (i = 256; i < cq->count; i += 2) + if (cq->elements[i] == p) + { + Id dep = cq->elements[i + 1]; + queue_deleten(cq, i, 2); + i -= 2; + check_complex_dep(solv, dep, m, &cq); + } + else + { + Id pp = cq->elements[i]; + cq->elements[pp & 255] |= (1 << (pp >> 8 & 31)); + } +} + +#endif + /* * prune to recommended/suggested packages. * does not prune installed packages (they are also somewhat recommended). @@ -249,6 +363,18 @@ prune_to_recommended(Solver *solv, Queue *plist) { MAPZERO(&solv->recommendsmap); MAPZERO(&solv->suggestsmap); +#ifdef ENABLE_COMPLEX_DEPS + if (solv->recommendscplxq) + { + queue_free(solv->recommendscplxq); + solv->recommendscplxq = solv_free(solv->recommendscplxq); + } + if (solv->suggestscplxq) + { + queue_free(solv->suggestscplxq); + solv->suggestscplxq = solv_free(solv->suggestscplxq); + } +#endif solv->recommends_index = 0; } while (solv->recommends_index < solv->decisionq.count) @@ -257,19 +383,45 @@ prune_to_recommended(Solver *solv, Queue *plist) if (p < 0) continue; s = pool->solvables + p; +#ifdef ENABLE_COMPLEX_DEPS + if (solv->recommendscplxq && solv->recommendscplxq->elements[p & 255]) + if (solv->recommendscplxq->elements[p & 255] & (1 << (p >> 8 & 31))) + recheck_complex_dep(solv, p, &solv->recommendsmap, &solv->recommendscplxq); + if (solv->suggestscplxq && solv->suggestscplxq->elements[p & 255]) + if (solv->suggestscplxq->elements[p & 255] & (1 << (p >> 8 & 31))) + recheck_complex_dep(solv, p, &solv->suggestsmap, &solv->suggestscplxq); +#endif if (s->recommends) { recp = s->repo->idarraydata + s->recommends; while ((rec = *recp++) != 0) - FOR_PROVIDES(p, pp, rec) - MAPSET(&solv->recommendsmap, p); + { +#ifdef ENABLE_COMPLEX_DEPS + if (pool_is_complex_dep(pool, rec)) + { + check_complex_dep(solv, rec, &solv->recommendsmap, &solv->recommendscplxq); + continue; + } +#endif + FOR_PROVIDES(p, pp, rec) + MAPSET(&solv->recommendsmap, p); + } } if (s->suggests) { sugp = s->repo->idarraydata + s->suggests; while ((sug = *sugp++) != 0) - FOR_PROVIDES(p, pp, sug) - MAPSET(&solv->suggestsmap, p); + { +#ifdef ENABLE_COMPLEX_DEPS + if (pool_is_complex_dep(pool, sug)) + { + check_complex_dep(solv, sug, &solv->suggestsmap, &solv->suggestscplxq); + continue; + } +#endif + FOR_PROVIDES(p, pp, sug) + MAPSET(&solv->suggestsmap, p); + } } } diff --git a/src/solver.c b/src/solver.c index 8ca9efe..7a634ec 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1247,7 +1247,8 @@ revert(Solver *solv, int level) while (solv->branches.count && solv->branches.elements[solv->branches.count - 1] >= 0) solv->branches.count--; } - solv->recommends_index = -1; + if (solv->recommends_index > solv->decisionq.count) + solv->recommends_index = -1; /* rebuild recommends/suggests maps */ if (solv->decisionq.count < solv->decisioncnt_update) solv->decisioncnt_update = 0; if (solv->decisionq.count < solv->decisioncnt_keep) @@ -1530,6 +1531,25 @@ solver_create(Pool *pool) * solver_free */ +static inline void +queuep_free(Queue **qp) +{ + if (!*qp) + return; + queue_free(*qp); + *qp = solv_free(*qp); +} + +static inline void +map_zerosize(Map *m) +{ + if (m->size) + { + map_free(m); + map_init(m, 0); + } +} + void solver_free(Solver *solv) { @@ -1546,26 +1566,12 @@ solver_free(Solver *solv) queue_free(&solv->weakruleq); queue_free(&solv->ruleassertions); queue_free(&solv->addedmap_deduceq); - if (solv->cleandeps_updatepkgs) - { - queue_free(solv->cleandeps_updatepkgs); - solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs); - } - if (solv->cleandeps_mistakes) - { - queue_free(solv->cleandeps_mistakes); - solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes); - } - if (solv->update_targets) - { - queue_free(solv->update_targets); - solv->update_targets = solv_free(solv->update_targets); - } - if (solv->installsuppdepq) - { - queue_free(solv->installsuppdepq); - solv->installsuppdepq = solv_free(solv->installsuppdepq); - } + queuep_free(&solv->cleandeps_updatepkgs); + queuep_free(&solv->cleandeps_mistakes); + queuep_free(&solv->update_targets); + queuep_free(&solv->installsuppdepq); + queuep_free(&solv->recommendscplxq); + queuep_free(&solv->suggestscplxq); map_free(&solv->recommendsmap); map_free(&solv->suggestsmap); @@ -3194,73 +3200,28 @@ solver_solve(Solver *solv, Queue *job) queue_insertn(&solv->job, 0, pool->pooljobs.count, pool->pooljobs.elements); job = &solv->job; - /* free old stuff */ - if (solv->update_targets) - { - queue_free(solv->update_targets); - solv->update_targets = solv_free(solv->update_targets); - } - if (solv->cleandeps_updatepkgs) - { - queue_free(solv->cleandeps_updatepkgs); - solv->cleandeps_updatepkgs = solv_free(solv->cleandeps_updatepkgs); - } + /* free old stuff in jase we re-run a solver */ + queuep_free(&solv->update_targets); + queuep_free(&solv->cleandeps_updatepkgs); queue_empty(&solv->ruleassertions); solv->bestrules_pkg = solv_free(solv->bestrules_pkg); solv->choicerules_ref = solv_free(solv->choicerules_ref); if (solv->noupdate.size) map_empty(&solv->noupdate); - if (solv->multiversion.size) - { - map_free(&solv->multiversion); - map_init(&solv->multiversion, 0); - } + map_zerosize(&solv->multiversion); solv->updatemap_all = 0; - if (solv->updatemap.size) - { - map_free(&solv->updatemap); - map_init(&solv->updatemap, 0); - } + map_zerosize(&solv->updatemap); solv->bestupdatemap_all = 0; - if (solv->bestupdatemap.size) - { - map_free(&solv->bestupdatemap); - map_init(&solv->bestupdatemap, 0); - } + map_zerosize(&solv->bestupdatemap); solv->fixmap_all = 0; - if (solv->fixmap.size) - { - map_free(&solv->fixmap); - map_init(&solv->fixmap, 0); - } + map_zerosize(&solv->fixmap); solv->dupmap_all = 0; - if (solv->dupmap.size) - { - map_free(&solv->dupmap); - map_init(&solv->dupmap, 0); - } - if (solv->dupinvolvedmap.size) - { - map_free(&solv->dupinvolvedmap); - map_init(&solv->dupinvolvedmap, 0); - } + map_zerosize(&solv->dupmap); + map_zerosize(&solv->dupinvolvedmap); solv->droporphanedmap_all = 0; - if (solv->droporphanedmap.size) - { - map_free(&solv->droporphanedmap); - map_init(&solv->droporphanedmap, 0); - } - if (solv->cleandepsmap.size) - { - map_free(&solv->cleandepsmap); - map_init(&solv->cleandepsmap, 0); - } - if (solv->weakrulemap.size) - { - map_free(&solv->weakrulemap); - map_init(&solv->weakrulemap, 0); - } - + map_zerosize(&solv->droporphanedmap); + map_zerosize(&solv->cleandepsmap); + map_zerosize(&solv->weakrulemap); queue_empty(&solv->weakruleq); solv->watches = solv_free(solv->watches); queue_empty(&solv->ruletojob); @@ -3281,6 +3242,8 @@ solver_solve(Solver *solv, Queue *job) { map_empty(&solv->recommendsmap); map_empty(&solv->suggestsmap); + queuep_free(&solv->recommendscplxq); + queuep_free(&solv->suggestscplxq); solv->recommends_index = 0; } solv->specialupdaters = solv_free(solv->specialupdaters); diff --git a/src/solver.h b/src/solver.h index ae05bb1..7646624 100644 --- a/src/solver.h +++ b/src/solver.h @@ -133,6 +133,8 @@ struct _Solver { Map recommendsmap; /* recommended packages from decisionmap */ Map suggestsmap; /* suggested packages from decisionmap */ int recommends_index; /* recommendsmap/suggestsmap is created up to this level */ + Queue *recommendscplxq; + Queue *suggestscplxq; Id *obsoletes; /* obsoletes for each installed solvable */ Id *obsoletes_data; /* data area for obsoletes */ |