From: Michael Schroeder Date: Mon, 4 Feb 2013 14:43:27 +0000 (+0100) Subject: make it possible to re-run an existing solver (re-using the rpm rules) X-Git-Tag: BASE-SuSE-Code-12_3-Branch~97 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41c5eb1cdfff8c8ed92194eafbb3070c86350c4e;p=thirdparty%2Flibsolv.git make it possible to re-run an existing solver (re-using the rpm rules) --- diff --git a/src/rules.c b/src/rules.c index 729268d7..11634e99 100644 --- a/src/rules.c +++ b/src/rules.c @@ -377,6 +377,12 @@ solver_addrule(Solver *solv, Id p, Id d) return r; } +void +solver_shrinkrules(Solver *solv, int nrules) +{ + solv->nrules = nrules; + solv->rules = solv_extend_resize(solv->rules, solv->nrules, sizeof(Rule), RULES_BLOCK); +} /****************************************************************************** *** diff --git a/src/rules.h b/src/rules.h index 144b6833..4d6b8ad1 100644 --- a/src/rules.h +++ b/src/rules.h @@ -99,6 +99,7 @@ solver_enablerule(struct _Solver *solv, Rule *r) extern Rule *solver_addrule(struct _Solver *solv, Id p, Id d); extern void solver_unifyrules(struct _Solver *solv); extern int solver_rulecmp(struct _Solver *solv, Rule *r1, Rule *r2); +extern void solver_shrinkrules(struct _Solver *solv, int nrules); /* rpm rules */ extern void solver_addrpmrulesforsolvable(struct _Solver *solv, Solvable *s, Map *m); diff --git a/src/solver.c b/src/solver.c index 43668d54..883c46ab 100644 --- a/src/solver.c +++ b/src/solver.c @@ -1436,6 +1436,7 @@ solver_create(Pool *pool) queue_init(&solv->branches); queue_init(&solv->weakruleq); queue_init(&solv->ruleassertions); + queue_init(&solv->addedmap_deduceq); queue_push(&solv->learnt_pool, 0); /* so that 0 does not describe a proof */ @@ -1473,6 +1474,7 @@ solver_free(Solver *solv) queue_free(&solv->branches); queue_free(&solv->weakruleq); queue_free(&solv->ruleassertions); + queue_free(&solv->addedmap_deduceq); if (solv->cleandeps_updatepkgs) { queue_free(solv->cleandeps_updatepkgs); @@ -2831,6 +2833,74 @@ transform_update_targets(Solver *solv) } +static void +addedmap2deduceq(Solver *solv, Map *addedmap) +{ + Pool *pool = solv->pool; + int i, j; + Id p; + Rule *r; + + queue_empty(&solv->addedmap_deduceq); + for (i = 2, j = solv->rpmrules_end - 1; i < pool->nsolvables && j > 0; j--) + { + r = solv->rules + j; + if (r->p >= 0) + continue; + if ((r->d == 0 || r->d == -1) && r->w2 < 0) + continue; + p = -r->p; + if (!MAPTST(addedmap, p)) + { + /* should never happen, but... */ + if (!solv->addedmap_deduceq.count || solv->addedmap_deduceq.elements[solv->addedmap_deduceq.count - 1] != -p) + queue_push(&solv->addedmap_deduceq, -p); + continue; + } + for (; i < p; i++) + if (MAPTST(addedmap, i)) + queue_push(&solv->addedmap_deduceq, i); + if (i == p) + i++; + } + 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 +deduceq2addedmap(Solver *solv, Map *addedmap) +{ + int j; + Id p; + Rule *r; + for (j = solv->rpmrules_end - 1; j > 0; j--) + { + r = solv->rules + j; + if (r->d < 0 && r->p) + solver_enablerule(solv, r); + if (r->p >= 0) + continue; + if ((r->d == 0 || r->d == -1) && r->w2 < 0) + continue; + p = -r->p; + MAPSET(addedmap, p); + } + for (j = 0; j < solv->addedmap_deduceq.count; j++) + { + p = solv->addedmap_deduceq.elements[j]; + if (p > 0) + MAPSET(addedmap, p); + else + MAPCLR(addedmap, p); + } +} + + /* * * solve job queue @@ -2843,7 +2913,7 @@ solver_solve(Solver *solv, Queue *job) Pool *pool = solv->pool; Repo *installed = solv->installed; int i; - int oldnrules; + int oldnrules, initialnrules; Map addedmap; /* '1' == have rpm-rules for solvable */ Map installcandidatemap; Id how, what, select, name, weak, p, pp, d; @@ -2893,6 +2963,83 @@ solver_solve(Solver *solv, Queue *job) queue_free(solv->cleandeps_updatepkgs); solv->cleandeps_updatepkgs = solv_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->noobsoletes.size) + { + map_free(&solv->noobsoletes); + map_init(&solv->noobsoletes, 0); + } + solv->updatemap_all = 0; + if (solv->updatemap.size) + { + map_free(&solv->updatemap); + map_init(&solv->updatemap, 0); + } + solv->bestupdatemap_all = 0; + if (solv->bestupdatemap.size) + { + map_free(&solv->bestupdatemap); + map_init(&solv->bestupdatemap, 0); + } + solv->fixmap_all = 0; + if (solv->fixmap.size) + { + map_free(&solv->fixmap); + map_init(&solv->fixmap, 0); + } + 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); + } + 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); + } + + queue_empty(&solv->weakruleq); + solv->watches = solv_free(solv->watches); + queue_empty(&solv->ruletojob); + if (solv->decisionq.count) + memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id)); + queue_empty(&solv->decisionq); + queue_empty(&solv->decisionq_why); + solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0; + queue_empty(&solv->learnt_why); + queue_empty(&solv->learnt_pool); + queue_empty(&solv->branches); + solv->propagate_index = 0; + queue_empty(&solv->problems); + queue_empty(&solv->solutions); + queue_empty(&solv->orphaned); + solv->stats_learned = solv->stats_unsolvable = 0; + if (solv->recommends_index) + { + map_empty(&solv->recommendsmap); + map_empty(&solv->suggestsmap); + solv->recommends_index = 0; + } + solv->obsoletes = solv_free(solv->obsoletes); + solv->obsoletes_data = solv_free(solv->obsoletes_data); + solv->multiversionupdaters = solv_free(solv->multiversionupdaters); + /* * create basic rule set of all involved packages @@ -2914,6 +3061,14 @@ solver_solve(Solver *solv, Queue *job) * so called: rpm rules * */ + initialnrules = solv->rpmrules_end ? solv->rpmrules_end : 1; + if (initialnrules > 1) + deduceq2addedmap(solv, &addedmap); + if (solv->nrules != initialnrules) + solver_shrinkrules(solv, initialnrules); + solv->nrules = initialnrules; + solv->rpmrules_end = 0; + if (installed) { /* check for update/verify jobs as they need to be known early */ @@ -3087,8 +3242,12 @@ solver_solve(Solver *solv, Queue *job) POOL_DEBUG(SOLV_DEBUG_STATS, "%d of %d installable solvables considered for solving\n", possible, installable); } - solver_unifyrules(solv); /* remove duplicate rpm rules */ - solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */ + if (solv->nrules > initialnrules) + solver_unifyrules(solv); /* remove duplicate rpm rules */ + solv->rpmrules_end = solv->nrules; /* mark end of rpm rules */ + + if (solv->nrules > initialnrules) + addedmap2deduceq(solv, &addedmap); /* so that we can recreate the addedmap */ POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule memory used: %d K\n", solv->nrules * (int)sizeof(Rule) / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "rpm rule creation took %d ms\n", solv_timems(now)); diff --git a/src/solver.h b/src/solver.h index a1347186..a51b1738 100644 --- a/src/solver.h +++ b/src/solver.h @@ -229,6 +229,8 @@ struct _Solver { Queue *update_targets; /* update to specific packages */ Queue *installsuppdepq; /* deps from the install namespace provides hack */ + + Queue addedmap_deduceq; /* deduce addedmap from rpm rules */ #endif /* LIBSOLV_INTERNAL */ }; diff --git a/tools/installcheck.c b/tools/installcheck.c index 4859bc27..a0513eae 100644 --- a/tools/installcheck.c +++ b/tools/installcheck.c @@ -250,10 +250,11 @@ main(int argc, char **argv) } } + solv = solver_create(pool); + /* prune cand by doing weak installs */ while (cand.count) { - solv = solver_create(pool); queue_empty(&job); for (i = 0; i < cand.count; i++) { @@ -326,7 +327,6 @@ main(int argc, char **argv) continue; } s = pool->solvables + p; - solv = solver_create(pool); queue_empty(&job); queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE); queue_push(&job, p); @@ -442,7 +442,7 @@ main(int argc, char **argv) } } #endif - solver_free(solv); } + solver_free(solv); exit(status); }