[zypp-commit] r9364 - in /trunk/sat-solver/src: solvable.c solver.c solver.h
Author: mlschroe Date: Thu Apr 3 20:25:13 2008 New Revision: 9364 URL: http://svn.opensuse.org/viewcvs/zypp?rev=9364&view=rev Log: - fix memory leak - add support to make every rule weak - fix dontinstallrecommended flag - add SOLVER_WEAK job modifier - make recommended/suggest calculation ignore all weak rules (needs some more fixing) Modified: trunk/sat-solver/src/solvable.c trunk/sat-solver/src/solver.c trunk/sat-solver/src/solver.h Modified: trunk/sat-solver/src/solvable.c URL: http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/src/solvable.c?rev=9364&r1=9363&r2=9364&view=diff ============================================================================== --- trunk/sat-solver/src/solvable.c (original) +++ trunk/sat-solver/src/solvable.c Thu Apr 3 20:25:13 2008 @@ -189,6 +189,7 @@ p = sat_malloc(strlen(kn) + strlen(lang) + 2); sprintf(p, "%s:%s", kn, lang); id = str2id(pool, p, 0); + free(p); if (id) { str = repo_lookup_str(s, id); Modified: trunk/sat-solver/src/solver.c URL: http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/src/solver.c?rev=9364&r1=9363&r2=9364&view=diff ============================================================================== --- trunk/sat-solver/src/solver.c (original) +++ trunk/sat-solver/src/solver.c Thu Apr 3 20:25:13 2008 @@ -27,7 +27,7 @@ #define RULES_BLOCK 63 -#define REGARD_RECOMMENDS_OF_INSTALLED_ITEMS 0 +#define REGARD_RECOMMENDS_OF_INSTALLED_ITEMS 1 int @@ -192,13 +192,16 @@ printruleclass(Solver *solv, int type, Rule *r) { Pool *pool = solv->pool; - if (r - solv->rules >= solv->learntrules) + Id p = r - solv->rules; + assert(p >= 0); + if (p < solv->learntrules) + if (MAPTST(&solv->weakrulemap, p)) + POOL_DEBUG(type, "WEAK "); + if (p >= solv->learntrules) POOL_DEBUG(type, "LEARNT "); - else if (r - solv->rules >= solv->weakrules) - POOL_DEBUG(type, "WEAK "); - else if (r - solv->rules >= solv->systemrules) + else if (p >= solv->systemrules) POOL_DEBUG(type, "SYSTEM "); - else if (r - solv->rules >= solv->jobrules) + else if (p >= solv->jobrules) POOL_DEBUG(type, "JOB "); printrule(solv, type, r); } @@ -416,6 +419,7 @@ d = dp[-1]; /* take single literal */ } +#if 0 if (n == 0 && !solv->jobrules) { /* this is a rpm rule assertion, we do not have to allocate it */ @@ -430,6 +434,8 @@ solv->decisionmap[-p] = -1; return 0; } +#endif + if (n == 1 && p > d) { /* smallest literal first so we can find dups */ @@ -605,14 +611,19 @@ decisionstart = solv->decisionq.count; /* rpm rules don't have assertions, so we can start with the job - * rules */ - for (ri = solv->jobrules, r = solv->rules + ri; ri < solv->nrules; ri++, r++) + * rules (rpm assertions are not resulting in a rule, but cause a + * immediate decision) */ + /* nowadays they can be weak, so start with rule 1 */ + for (ri = 1, r = solv->rules + ri; ri < solv->nrules; ri++, r++) { if (!r->w1 || r->w2) /* disabled or no assertion */ continue; + /* do weak rules in phase 2 */ + if (ri < solv->learntrules && MAPTST(&solv->weakrulemap, ri)) + continue; v = r->p; vv = v > 0 ? v : -v; - if (solv->decisionmap[vv] == 0) + if (!solv->decisionmap[vv]) { queue_push(&solv->decisionq, v); queue_push(&solv->decisionq_why, r - solv->rules); @@ -641,21 +652,13 @@ disablerule(solv, r); continue; } - /* if we are weak, just disable ourself */ - if (ri >= solv->weakrules) - { - POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "assertion conflict, but I am weak, disabling "); - printrule(solv, SAT_DEBUG_UNSOLVABLE, r); - disablerule(solv, r); - continue; - } - - /* only job and system rules left in the decisionq*/ + /* only job and system rules left in the decisionq */ /* find the decision which is the "opposite" of the jobrule */ for (i = 0; i < solv->decisionq.count; i++) if (solv->decisionq.elements[i] == -v) break; assert(i < solv->decisionq.count); +/*OBSOLETE*/ if (solv->decisionq_why.elements[i] == 0) { /* conflict with rpm rule, need only disable our rule */ @@ -675,6 +678,24 @@ disableproblem(solv, v); continue; } + if (solv->decisionq_why.elements[i] < solv->jobrules) + { + /* conflict with rpm rule assertion */ + queue_push(&solv->problems, solv->learnt_pool.count); + queue_push(&solv->learnt_pool, ri); + queue_push(&solv->learnt_pool, solv->decisionq_why.elements[i]); + queue_push(&solv->learnt_pool, 0); + assert(v > 0 || v == -SYSTEMSOLVABLE); + POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "conflict with rpm rule, disabling rule #%d\n", ri); + if (ri < solv->systemrules) + v = -(solv->ruletojob.elements[ri - solv->jobrules] + 1); + else + v = ri; + queue_push(&solv->problems, v); + queue_push(&solv->problems, 0); + disableproblem(solv, v); + continue; + } /* conflict with another job or system rule */ /* record proof */ @@ -684,6 +705,7 @@ queue_push(&solv->learnt_pool, 0); POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "conflicting system/job assertions over literal %d\n", vv); + /* push all of our rules asserting this literal on the problem stack */ for (i = solv->jobrules, rr = solv->rules + i; i < solv->nrules; i++, rr++) { @@ -691,10 +713,10 @@ continue; if (rr->p != vv && rr->p != -vv) continue; - /* See the large comment in front of the very first loop in this - function at FIXME. */ if (i >= solv->learntrules) continue; + if (MAPTST(&solv->weakrulemap, i)) + continue; POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, " - disabling rule #%d\n", i); v = i; if (i < solv->systemrules) @@ -716,7 +738,40 @@ r = solv->rules + ri; } - POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- makeruledecisions end; size decisionq: %d -----\n",solv->decisionq.count); + /* phase 2: now do the weak assertions */ + for (ri = 1, r = solv->rules + ri; ri < solv->learntrules; ri++, r++) + { + if (!r->w1 || r->w2) /* disabled or no assertion */ + continue; + if (!MAPTST(&solv->weakrulemap, ri)) + continue; + v = r->p; + vv = v > 0 ? v : -v; + if (!solv->decisionmap[vv]) + { + queue_push(&solv->decisionq, v); + queue_push(&solv->decisionq_why, r - solv->rules); + solv->decisionmap[vv] = v > 0 ? 1 : -1; + IF_POOLDEBUG (SAT_DEBUG_PROPAGATE) + { + Solvable *s = solv->pool->solvables + vv; + if (v < 0) + POOL_DEBUG(SAT_DEBUG_PROPAGATE, "conflicting %s (weak assertion)\n", solvable2str(solv->pool, s)); + else + POOL_DEBUG(SAT_DEBUG_PROPAGATE, "installing %s (weak assertion)\n", solvable2str(solv->pool, s)); + } + continue; + } + if (v > 0 && solv->decisionmap[vv] > 0) + continue; + if (v < 0 && solv->decisionmap[vv] < 0) + continue; + POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "assertion conflict, but I am weak, disabling "); + printrule(solv, SAT_DEBUG_UNSOLVABLE, r); + disablerule(solv, r); + } + + POOL_DEBUG(SAT_DEBUG_SCHUBI, "----- makeruledecisions end; size decisionq: %d -----\n",solv->decisionq.count); } /* @@ -738,8 +793,10 @@ whyp = solv->learnt_pool.elements + solv->learnt_why.elements[i - solv->learntrules]; while ((why = *whyp++) != 0) { +#if 0 if (why < 0) continue; /* rpm assertion */ +#endif assert(why < i); if (!solv->rules[why].w1) break; @@ -749,8 +806,8 @@ { IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "disabling learnt "); - printrule(solv, SAT_DEBUG_SOLUTIONS, r); + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "disabling "); + printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); } disablerule(solv, r); } @@ -758,8 +815,8 @@ { IF_POOLDEBUG (SAT_DEBUG_SOLUTIONS) { - POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "re-enabling learnt "); - printrule(solv, SAT_DEBUG_SOLUTIONS, r); + POOL_DEBUG(SAT_DEBUG_SOLUTIONS, "re-enabling "); + printruleclass(solv, SAT_DEBUG_SOLUTIONS, r); } enablerule(solv, r); } @@ -785,7 +842,7 @@ if (jobidx != -1) { - how = job->elements[jobidx]; + how = job->elements[jobidx] & ~SOLVER_WEAK; switch(how) { case SOLVER_INSTALL_SOLVABLE: @@ -808,7 +865,7 @@ if (j == lastjob) continue; lastjob = j; - how = job->elements[j]; + how = job->elements[j] & ~SOLVER_WEAK; what = job->elements[j + 1]; switch(how) { @@ -856,7 +913,7 @@ { /* we just disabled job #jobidx. enable all update rules * that aren't disabled by the remaining job rules */ - how = job->elements[jobidx]; + how = job->elements[jobidx] & ~SOLVER_WEAK; what = job->elements[jobidx + 1]; switch(how) { @@ -1693,20 +1750,24 @@ */ static void -analyze_unsolvable_rule(Solver *solv, Rule *r) +analyze_unsolvable_rule(Solver *solv, Rule *r, Id *lastweakp) { Pool *pool = solv->pool; int i; Id why = r - solv->rules; + IF_POOLDEBUG (SAT_DEBUG_UNSOLVABLE) printruleclass(solv, SAT_DEBUG_UNSOLVABLE, r); if (solv->learntrules && why >= solv->learntrules) { for (i = solv->learnt_why.elements[why - solv->learntrules]; solv->learnt_pool.elements[i]; i++) if (solv->learnt_pool.elements[i] > 0) - analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i]); + analyze_unsolvable_rule(solv, solv->rules + solv->learnt_pool.elements[i], lastweakp); return; } + if (MAPTST(&solv->weakrulemap, why)) + if (!*lastweakp || why > *lastweakp) + *lastweakp = why; /* do not add rpm rules to problem */ if (why < solv->jobrules) return; @@ -1744,7 +1805,7 @@ Id *decisionmap = solv->decisionmap; int oldproblemcount; int oldlearntpoolcount; - int lastweak; + Id lastweak; POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "ANALYZE UNSOLVABLE ----------------------\n"); oldproblemcount = solv->problems.count; @@ -1758,7 +1819,8 @@ r = cr; map_init(&seen, pool->nsolvables); queue_push(&solv->learnt_pool, r - solv->rules); - analyze_unsolvable_rule(solv, r); + lastweak = 0; + analyze_unsolvable_rule(solv, r, &lastweak); dp = r->d ? pool->whatprovidesdata + r->d : 0; for (i = -1; ; i++) { @@ -1786,6 +1848,8 @@ if (!MAPTST(&seen, vv)) continue; why = solv->decisionq_why.elements[idx]; +#if 0 + /* OBSOLETE */ if (!why) { /* level 1 and no why, must be an rpm assertion */ @@ -1801,9 +1865,10 @@ queue_push(&solv->learnt_pool, v); continue; } +#endif queue_push(&solv->learnt_pool, why); r = solv->rules + why; - analyze_unsolvable_rule(solv, r); + analyze_unsolvable_rule(solv, r, &lastweak); dp = r->d ? pool->whatprovidesdata + r->d : 0; for (i = -1; ; i++) { @@ -1827,26 +1892,14 @@ map_free(&seen); queue_push(&solv->problems, 0); /* mark end of this problem */ - lastweak = 0; - if (solv->weakrules != solv->learntrules) - { - for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++) - { - why = solv->problems.elements[i]; - if (why < solv->weakrules || why >= solv->learntrules) - continue; - if (!lastweak || lastweak < why) - lastweak = why; - } - } if (lastweak) { /* disable last weak rule */ solv->problems.count = oldproblemcount; solv->learnt_pool.count = oldlearntpoolcount; r = solv->rules + lastweak; - POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "disabling weak "); - printrule(solv, SAT_DEBUG_UNSOLVABLE, r); + POOL_DEBUG(SAT_DEBUG_UNSOLVABLE, "disabling "); + printruleclass(solv, SAT_DEBUG_UNSOLVABLE, r); disablerule(solv, r); reset_solver(solv); return 1; @@ -2075,6 +2128,7 @@ queue_init(&solv->learnt_pool); queue_init(&solv->branches); queue_init(&solv->covenantq); + queue_init(&solv->weakruleq); map_init(&solv->recommendsmap, pool->nsolvables); map_init(&solv->suggestsmap, pool->nsolvables); @@ -2107,10 +2161,12 @@ queue_free(&solv->recommendations); queue_free(&solv->branches); queue_free(&solv->covenantq); + queue_free(&solv->weakruleq); map_free(&solv->recommendsmap); map_free(&solv->suggestsmap); map_free(&solv->noupdate); + map_free(&solv->weakrulemap); sat_free(solv->decisionmap); sat_free(solv->rules); @@ -2146,8 +2202,8 @@ IF_POOLDEBUG (SAT_DEBUG_RULE_CREATION) { POOL_DEBUG (SAT_DEBUG_RULE_CREATION, "number of rules: %d\n", solv->nrules); - for (i = 0; i < solv->nrules; i++) - printrule(solv, SAT_DEBUG_RULE_CREATION, solv->rules + i); + for (i = 1; i < solv->nrules; i++) + printruleclass(solv, SAT_DEBUG_RULE_CREATION, solv->rules + i); } POOL_DEBUG(SAT_DEBUG_STATS, "initial decisions: %d\n", solv->decisionq.count); @@ -2161,6 +2217,18 @@ POOL_DEBUG(SAT_DEBUG_STATS, "solving...\n"); queue_init(&dq); + + /* + * here's the main loop: + * 1) propagate new decisions (only needed for level 1) + * 2) try to keep installed packages + * 3) fulfill all unresolved rules + * 4) install recommended packages + * 5) minimalize solution if we had choices + * if we encounter a problem, we rewind to a safe level and restart + * with step 1 + */ + for (;;) { /* @@ -2326,7 +2394,7 @@ IF_POOLDEBUG (SAT_DEBUG_PROPAGATE) { POOL_DEBUG(SAT_DEBUG_PROPAGATE, "unfulfilled "); - printrule(solv, SAT_DEBUG_PROPAGATE, r); + printruleclass(solv, SAT_DEBUG_PROPAGATE, r); } /* dq.count < 2 cannot happen as this means that * the rule is unit */ @@ -2352,6 +2420,7 @@ int qcount; POOL_DEBUG(SAT_DEBUG_STATS, "installing recommended packages\n"); +#if 0 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS) { for (i = 1; i < solv->decisionq.count; i++) @@ -2361,6 +2430,7 @@ solv->decisionmap[p] = -solv->decisionmap[p]; } } +#endif queue_empty(&dq); for (i = 1; i < pool->nsolvables; i++) { @@ -2404,6 +2474,7 @@ queue_pushunique(&dq, i); } } +#if 0 if (!solv->dosplitprovides && !REGARD_RECOMMENDS_OF_INSTALLED_ITEMS) { for (i = 1; i < solv->decisionq.count; i++) @@ -2413,6 +2484,7 @@ solv->decisionmap[p] = -solv->decisionmap[p]; } } +#endif if (dq.count) { if (dq.count > 1) @@ -2548,11 +2620,13 @@ for (;;) { /* re-enable as many weak rules as possible */ - for (i = solv->weakrules; i < solv->learntrules; i++) + for (i = solv->jobrules, r = solv->rules + i; i < solv->learntrules; i++, r++) { - r = solv->rules + i; - if (!r->w1) - enablerule(solv, r); + if (r->w1) + continue; + if (!MAPTST(&solv->weakrulemap, i)) + continue; + enablerule(solv, r); } queue_empty(&solv->problems); @@ -2668,7 +2742,7 @@ { why = solution.elements[j]; /* must be either job descriptor or system rule */ - assert(why < 0 || (why >= solv->systemrules && why < solv->weakrules)); + assert(why < 0 || (why >= solv->systemrules && why < solv->learntrules)); #if 0 printproblem(solv, why); #endif @@ -2711,10 +2785,12 @@ queue_free(&solv->problems); queue_clone(&solv->problems, &solutions); +printf("bring it back!\n"); /* bring solver back into problem state */ revert(solv, 1); /* XXX move to reset_solver? */ reset_solver(solv); +printf("problems %d solutions %d\n", solv->problems.count, solutions.count); assert(solv->problems.count == solutions.count); queue_free(&solutions); } @@ -2948,7 +3024,7 @@ int dontfix = 0; Id p, *pp, req, *reqp, con, *conp, obs, *obsp, *dp; - assert(rid < solv->weakrules); + assert(rid > 0); if (rid >= solv->systemrules) { *depp = 0; @@ -2968,8 +3044,10 @@ return SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP; return SOLVER_PROBLEM_JOB_RULE; } +#if 0 if (rid < 0) { +/*XXX OBSOLETE CODE */ /* a rpm rule assertion */ assert(rid != -SYSTEMSOLVABLE); s = pool->solvables - rid; @@ -3001,13 +3079,38 @@ *targetp = 0; return SOLVER_PROBLEM_NOTHING_PROVIDES_DEP; } +#endif r = solv->rules + rid; assert(r->p < 0); if (r->d == 0 && r->w2 == 0) { - /* an assertion. we don't store them as rpm rules, so - * can't happen */ - assert(0); + /* a rpm rule assertion */ + s = pool->solvables - r->p; + if (installed && !solv->fixsystem && s->repo == installed) + dontfix = 1; + assert(!dontfix); /* dontfix packages never have a neg assertion */ + *sourcep = -r->p; + *targetp = 0; + /* see why the package is not installable */ + if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC && !pool_installable(pool, s)) + { + *depp = 0; + return SOLVER_PROBLEM_NOT_INSTALLABLE; + } + /* check requires */ + assert(s->requires); + reqp = s->repo->idarraydata + s->requires; + while ((req = *reqp++) != 0) + { + if (req == SOLVABLE_PREREQMARKER) + continue; + dp = pool_whatprovides(pool, req); + if (*dp == 0) + break; + } + assert(req); + *depp = req; + return SOLVER_PROBLEM_NOTHING_PROVIDES_DEP; } s = pool->solvables - r->p; if (installed && !solv->fixsystem && s->repo == installed) @@ -3138,6 +3241,7 @@ lreqr = lconr = lsysr = ljobr = 0; while ((rid = solv->learnt_pool.elements[idx++]) != 0) { + 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->systemrules) @@ -3150,7 +3254,7 @@ if (!*jobrp) *jobrp = rid; } - else if (rid >= 0) + else { r = solv->rules + rid; if (!r->d && r->w2 < 0) @@ -3160,6 +3264,12 @@ } else { + if (r->d == 0 && r->w2 == 0 && !reqassert) + { + /* prefer assertions (XXX: bad idea?) */ + *reqrp = rid; + reqassert = 1; + } if (!*reqrp) *reqrp = rid; else if (solv->installed && r->p < 0 && solv->pool->solvables[-r->p].repo == solv->installed) @@ -3171,8 +3281,10 @@ } } } +#if 0 else { + /* XXX OBSOLETE */ /* assertion, counts as require rule */ /* ignore system solvable as we need useful info */ if (rid == -SYSTEMSOLVABLE) @@ -3190,6 +3302,7 @@ *reqrp = rid; } } +#endif } if (!*reqrp && lreqr) *reqrp = lreqr; @@ -3275,7 +3388,7 @@ { Pool *pool = solv->pool; int pcnt; - Id p, rp, what; + Id p, rp, how, what; Id problem, solution, element; Solvable *s, *sd; @@ -3297,8 +3410,9 @@ if (p == 0) { /* job, rp is index into job queue */ + how = job->elements[rp - 1] & ~SOLVER_WEAK; what = job->elements[rp]; - switch (job->elements[rp - 1]) + switch (how) { case SOLVER_INSTALL_SOLVABLE: s = pool->solvables + what; @@ -3467,7 +3581,7 @@ int i; int oldnrules; Map addedmap; /* '1' == have rpm-rules for solvable */ - Id how, what, name, p, *pp, d; + Id how, what, weak, name, p, *pp, d; Queue q; Solvable *s; @@ -3519,7 +3633,7 @@ oldnrules = solv->nrules; for (i = 0; i < job->count; i += 2) { - how = job->elements[i]; + how = job->elements[i] & ~SOLVER_WEAK; what = job->elements[i + 1]; switch(how) @@ -3597,7 +3711,8 @@ { oldnrules = solv->nrules; - how = job->elements[i]; + how = job->elements[i] & ~SOLVER_WEAK; + weak = job->elements[i] & SOLVER_WEAK; what = job->elements[i + 1]; switch(how) { @@ -3606,12 +3721,16 @@ POOL_DEBUG(SAT_DEBUG_JOB, "job: install solvable %s\n", solvable2str(pool, s)); addrule(solv, what, 0); /* install by Id */ queue_push(&solv->ruletojob, i); + if (weak) + queue_push(&solv->weakruleq, solv->nrules - 1); break; case SOLVER_ERASE_SOLVABLE: s = pool->solvables + what; POOL_DEBUG(SAT_DEBUG_JOB, "job: erase solvable %s\n", solvable2str(pool, s)); addrule(solv, -what, 0); /* remove by Id */ queue_push(&solv->ruletojob, i); + if (weak) + queue_push(&solv->weakruleq, solv->nrules - 1); break; case SOLVER_INSTALL_SOLVABLE_NAME: /* install by capability */ case SOLVER_INSTALL_SOLVABLE_PROVIDES: @@ -3646,6 +3765,8 @@ d = pool_queuetowhatprovides(pool, &q); /* get all providers */ addrule(solv, p, d); /* add 'requires' rule */ queue_push(&solv->ruletojob, i); + if (weak) + queue_push(&solv->weakruleq, solv->nrules - 1); break; case SOLVER_ERASE_SOLVABLE_NAME: /* remove by capability */ case SOLVER_ERASE_SOLVABLE_PROVIDES: @@ -3666,6 +3787,8 @@ continue; addrule(solv, -p, 0); /* add 'remove' rule */ queue_push(&solv->ruletojob, i); + if (weak) + queue_push(&solv->weakruleq, solv->nrules - 1); } break; case SOLVER_INSTALL_SOLVABLE_UPDATE: /* find update for solvable */ @@ -3673,6 +3796,8 @@ POOL_DEBUG(SAT_DEBUG_JOB, "job: update %s\n", solvable2str(pool, s)); addupdaterule(solv, s, 0); queue_push(&solv->ruletojob, i); + if (weak) + queue_push(&solv->weakruleq, solv->nrules - 1); break; } IF_POOLDEBUG (SAT_DEBUG_JOB) @@ -3746,20 +3871,12 @@ map_free(&addedmap); queue_free(&q); - solv->weakrules = solv->nrules; - - /* try real hard to keep packages installed */ - if (0) + /* create weak map */ + map_init(&solv->weakrulemap, solv->nrules); + for (i = 0; i < solv->weakruleq.count; i++) { - FOR_REPO_SOLVABLES(installed, p, s) - { - /* FIXME: can't work with refine_suggestion! */ - /* need to always add the rule but disable it */ - if (MAPTST(&solv->noupdate, p - installed->start)) - continue; - d = solv->weaksystemrules[p - installed->start]; - addrule(solv, p, d); - } + p = solv->weakruleq.elements[i]; + MAPSET(&solv->weakrulemap, p); } /* all new rules are learnt after this point */ @@ -3777,55 +3894,102 @@ POOL_DEBUG(SAT_DEBUG_STATS, "problems so far: %d\n", solv->problems.count); /* solve! */ - run_solver(solv, solv->dontinstallrecommended ? 0 : 1, 1); + run_solver(solv, 1, solv->dontinstallrecommended ? 0 : 1); /* find recommended packages */ - if (!solv->problems.count && solv->dontinstallrecommended) + if (!solv->problems.count) { Id rec, *recp, p, *pp; + int gotweak = 0; + Queue olddecisions; + Rule *r; - /* create map of all suggests that are still open */ - solv->recommends_index = -1; - MAPZERO(&solv->recommendsmap); - for (i = 0; i < solv->decisionq.count; i++) + /* disable all weak erase rules */ + for (i = 1, r = solv->rules + i; i < solv->learntrules; i++, r++) { - p = solv->decisionq.elements[i]; - if (p < 0) + if (!MAPTST(&solv->weakrulemap, i)) continue; - s = pool->solvables + p; - if (s->recommends) + if (!r->w1) + continue; + disablerule(solv, r); + gotweak++; + } + if (gotweak) + { + queue_clone(&olddecisions, &solv->decisionq); + reset_solver(solv); + r = propagate(solv, 1); + assert(!r); + for (i = 0; i < olddecisions.count; i++) { - recp = s->repo->idarraydata + s->recommends; - while ((rec = *recp++) != 0) - { - FOR_PROVIDES(p, pp, rec) - if (solv->decisionmap[p] > 0) - break; - if (p) - continue; /* already fulfilled */ - FOR_PROVIDES(p, pp, rec) - MAPSET(&solv->recommendsmap, p); - } + p = olddecisions.elements[i]; + if (p < 0) + continue; + if (solv->decisionmap[p] > 0) + continue; + assert(solv->decisionmap[p] == 0); + solv->decisionmap[p] = 1; + queue_push(&solv->decisionq, p); + queue_push(&solv->decisionq_why, 0); + r = propagate(solv, 1); + assert(!r); } } - for (i = 1; i < pool->nsolvables; i++) + + if (gotweak || solv->dontinstallrecommended) { - if (solv->decisionmap[i] != 0) - continue; - s = pool->solvables + i; - if (!MAPTST(&solv->recommendsmap, i)) + /* create map of all suggests that are still open */ + solv->recommends_index = -1; + MAPZERO(&solv->recommendsmap); + for (i = 0; i < solv->decisionq.count; i++) { - if (!s->supplements) - continue; - if (!pool_installable(pool, s)) + p = solv->decisionq.elements[i]; + if (p < 0) continue; - if (!solver_is_supplementing(solv, s)) + s = pool->solvables + p; + if (s->recommends) + { + recp = s->repo->idarraydata + s->recommends; + while ((rec = *recp++) != 0) + { + FOR_PROVIDES(p, pp, rec) + if (solv->decisionmap[p] > 0) + break; + if (p) + continue; /* already fulfilled */ + FOR_PROVIDES(p, pp, rec) + MAPSET(&solv->recommendsmap, p); + } + } + } + for (i = 1; i < pool->nsolvables; i++) + { + if (solv->decisionmap[i] != 0) continue; + s = pool->solvables + i; + if (!MAPTST(&solv->recommendsmap, i)) + { + if (!s->supplements) + continue; + if (!pool_installable(pool, s)) + continue; + if (!solver_is_supplementing(solv, s)) + continue; + } + if (solv->dontinstallrecommended) + queue_push(&solv->recommendations, i); + else + queue_pushunique(&solv->recommendations, i); } - queue_push(&solv->recommendations, i); + /* we use MODE_SUGGEST here so that repo prio is ignored */ + policy_filter_unwanted(solv, &solv->recommendations, 0, POLICY_MODE_SUGGEST); + } + if (gotweak) + { + queue_clone(&solv->decisionq, &olddecisions); + queue_free(&olddecisions); + /* XXX restore everything */ } - /* we use MODE_SUGGEST here so that repo prio is ignored */ - policy_filter_unwanted(solv, &solv->recommendations, 0, POLICY_MODE_SUGGEST); } /* find suggested packages */ Modified: trunk/sat-solver/src/solver.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/sat-solver/src/solver.h?rev=9364&r1=9363&r2=9364&view=diff ============================================================================== --- trunk/sat-solver/src/solver.h (original) +++ trunk/sat-solver/src/solver.h Thu Apr 3 20:25:13 2008 @@ -64,12 +64,13 @@ Id jobrules; /* user rules */ Id systemrules; /* policy rules, e.g. keep packages installed or update. All literals > 0 */ - Id weakrules; /* rules that can be autodisabled */ Id learntrules; /* learnt rules */ Id *weaksystemrules; /* please try to install (r->d) */ Map noupdate; /* don't try to update these installed solvables */ + Queue weakruleq; + Map weakrulemap; Id *watches; /* Array of rule offsets * watches has nsolvables*2 entries and is addressed from the middle @@ -179,7 +180,8 @@ SOLVER_ERASE_SOLVABLE_NAME, SOLVER_INSTALL_SOLVABLE_PROVIDES, SOLVER_ERASE_SOLVABLE_PROVIDES, - SOLVER_INSTALL_SOLVABLE_UPDATE + SOLVER_INSTALL_SOLVABLE_UPDATE, + SOLVER_WEAK = 0x100, } SolverCmd; typedef enum { -- To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org For additional commands, e-mail: zypp-commit+help@opensuse.org
participants (1)
-
mlschroe@svn.opensuse.org