assert(solv->decisionq.count == 0);
queue_push(&solv->decisionq, SYSTEMSOLVABLE);
queue_push(&solv->decisionq_why, 0);
+ queue_push2(&solv->decisionq_reason, 0, 0);
solv->decisionmap[SYSTEMSOLVABLE] = 1; /* installed at level '1' */
decisionstart = solv->decisionq.count;
solv->branches.count -= solv->branches.elements[solv->branches.count - 2];
if (solv->recommends_index > solv->decisionq.count)
solv->recommends_index = -1; /* rebuild recommends/suggests maps */
- if (solv->decisionq.count < solv->decisioncnt_jobs)
- solv->decisioncnt_jobs = 0;
- if (solv->decisionq.count < solv->decisioncnt_update)
- solv->decisioncnt_update = 0;
- if (solv->decisionq.count < solv->decisioncnt_keep)
- solv->decisioncnt_keep = 0;
- if (solv->decisionq.count < solv->decisioncnt_resolve)
- solv->decisioncnt_resolve = 0;
- if (solv->decisionq.count < solv->decisioncnt_weak)
- solv->decisioncnt_weak= 0;
- if (solv->decisionq.count < solv->decisioncnt_orphan)
- solv->decisioncnt_orphan = 0;
+ solv->decisionq_reason.count = level + 1;
}
/*-------------------------------------------------------------------
}
queue_empty(&solv->decisionq_why);
queue_empty(&solv->decisionq);
+ queue_empty(&solv->decisionq_reason);
solv->recommends_index = -1;
solv->propagate_index = 0;
- solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
queue_empty(&solv->branches);
/* adapt learnt rule status to new set of enabled/disabled rules */
*/
static int
-setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid)
+setpropagatelearn(Solver *solv, int level, Id decision, int disablerules, Id ruleid, Id reason)
{
Pool *pool = solv->pool;
Rule *r, *lr;
solv->decisionmap[-decision] = -level;
queue_push(&solv->decisionq, decision);
queue_push(&solv->decisionq_why, -ruleid); /* <= 0 -> free decision */
+ queue_push(&solv->decisionq_reason, reason);
}
assert(ruleid >= 0 && level > 0);
for (;;)
{
Pool *pool = solv->pool;
int level;
- Id p, why;
+ Id p, why, reason;
#if 0
{
int i;
/* hack: revert simply sets the count, so we can still access the reverted elements */
why = -solv->decisionq_why.elements[solv->decisionq_why.count];
assert(why >= 0);
- return setpropagatelearn(solv, level, p, disablerules, why);
+ reason = solv->decisionq_reason.elements[level + 1];
+ return setpropagatelearn(solv, level, p, disablerules, why, reason);
}
/*-------------------------------------------------------------------
*/
static int
-selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid)
+selectandinstall(Solver *solv, int level, Queue *dq, int disablerules, Id ruleid, Id reason)
{
Pool *pool = solv->pool;
Id p;
createbranch(solv, level, dq, 0, ruleid);
p = dq->elements[0];
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing %s\n", pool_solvid2str(pool, p));
- return setpropagatelearn(solv, level, p, disablerules, ruleid);
+ return setpropagatelearn(solv, level, p, disablerules, ruleid, reason);
}
queue_init(&solv->ruletojob);
queue_init(&solv->decisionq);
queue_init(&solv->decisionq_why);
+ queue_init(&solv->decisionq_reason);
queue_init(&solv->problems);
queue_init(&solv->orphaned);
queue_init(&solv->learnt_why);
Rule *r;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "resolving job rules\n");
- if (!solv->decisioncnt_jobs)
- solv->decisioncnt_jobs = solv->decisionq.count;
for (i = solv->jobrules, r = solv->rules + i; i < solv->jobrules_end; i++, r++)
{
Id l, pp;
dq->count = k;
}
olevel = level;
- level = selectandinstall(solv, level, dq, disablerules, i);
+ level = selectandinstall(solv, level, dq, disablerules, i, SOLVER_REASON_RESOLVE_JOB);
if (level <= olevel)
{
if (level == olevel)
queue_free(&solv->ruletojob);
queue_free(&solv->decisionq);
queue_free(&solv->decisionq_why);
+ queue_free(&solv->decisionq_reason);
queue_free(&solv->learnt_why);
queue_free(&solv->learnt_pool);
queue_free(&solv->problems);
/*
* installed packages
*/
- if (!solv->decisioncnt_update)
- solv->decisioncnt_update = solv->decisionq.count;
if (level < systemlevel && solv->installed && solv->installed->nsolvables && !solv->installed->disabled)
{
Repo *installed = solv->installed;
{
int passlevel = level;
Id *specialupdaters = solv->specialupdaters;
- if (pass == 1 && !solv->decisioncnt_keep)
- solv->decisioncnt_keep = solv->decisionq.count;
/* start with installedpos, the position that gave us problems the last time */
for (i = installedpos, n = installed->start; n < installed->end; i++, n++)
{
if (dq.count)
{
olevel = level;
- level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules);
+ level = selectandinstall(solv, level, &dq, disablerules, rr - solv->rules, SOLVER_REASON_UPDATE_INSTALLED);
if (level <= olevel)
{
if (level < passlevel)
{
#if 0
POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, i));
- level = setpropagatelearn(solv, level, -i, disablerules, 0);
+ level = setpropagatelearn(solv, level, -i, disablerules, 0, SOLVER_REASON_CLEANDEPS_ERASE);
#else
continue;
#endif
else
{
POOL_DEBUG(SOLV_DEBUG_POLICY, "keeping %s\n", pool_solvid2str(pool, i));
- level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules);
+ level = setpropagatelearn(solv, level, i, disablerules, r - solv->rules, SOLVER_REASON_KEEP_INSTALLED);
}
if (level <= olevel)
{
if (pass < 2)
continue; /* had trouble, retry */
}
- if (!solv->decisioncnt_keep)
- solv->decisioncnt_keep = solv->decisionq.count;
if (level < systemlevel && solv->focus_installed)
{
/*
* decide
*/
- if (!solv->decisioncnt_resolve)
- solv->decisioncnt_resolve = solv->decisionq.count;
POOL_DEBUG(SOLV_DEBUG_POLICY, "deciding unresolved rules\n");
postponed = 0;
for (i = 1, n = 1; ; i++, n++)
}
olevel = level;
- level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules);
+ level = selectandinstall(solv, level, &dq, disablerules, r - solv->rules, SOLVER_REASON_RESOLVE);
if (level < systemlevel)
break; /* trouble */
/* something changed, so look at all rules again */
{
POOL_DEBUG(SOLV_DEBUG_POLICY, "cleandeps erasing %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_CLEANDEPS_ERASE);
if (level < olevel)
break;
}
/* at this point we have a consistent system. now do the extras... */
- if (!solv->decisioncnt_weak)
- solv->decisioncnt_weak = solv->decisionq.count;
if (doweak)
{
int qcount;
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
else
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
- level = setpropagatelearn(solv, level, p, 0, 0);
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
continue; /* back to main loop */
}
continue;
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing supplemented %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
if (level <= olevel)
break;
}
p = dq.elements[0];
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing recommended %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_WEAKDEP);
if (level <= olevel || solv->decisionq.count < decisioncount)
break; /* we had to revert some decisions */
}
}
}
- if (!solv->decisioncnt_orphan)
- solv->decisioncnt_orphan = solv->decisionq.count;
if (solv->installed && (solv->orphaned.count || solv->brokenorphanrules))
{
int installedone = 0;
continue;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "keeping orphaned %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
installedone = 1;
if (level < olevel)
break;
continue; /* already decided */
POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing orphaned %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
if (level < olevel)
break;
}
p = dq.elements[i];
POOL_DEBUG(SOLV_DEBUG_POLICY, "installing orphaned dep %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, p, 0, 0);
+ level = setpropagatelearn(solv, level, p, 0, 0, SOLVER_REASON_RESOLVE_ORPHAN);
if (level < olevel)
break;
}
continue;
POOL_DEBUG(SOLV_DEBUG_SOLVER, "removing unwanted %s\n", pool_solvid2str(pool, p));
olevel = level;
- level = setpropagatelearn(solv, level, -p, 0, 0);
+ level = setpropagatelearn(solv, level, -p, 0, 0, SOLVER_REASON_CLEANDEPS_ERASE);
if (level < olevel)
break;
}
/* no minimization found, we're finally finished! */
break;
}
+ assert(level == -1 || level + 1 == solv->decisionq_reason.count);
POOL_DEBUG(SOLV_DEBUG_STATS, "solver statistics: %d learned rules, %d unsolvable, %d minimization steps\n", solv->stats_learned, solv->stats_unsolvable, minimizationsteps);
POOL_DEBUG(SOLV_DEBUG_STATS, "done solving.\n\n");
queue_free(&dq);
queue_free(&dqs);
- if (level < 0)
- {
- /* unsolvable */
- solv->decisioncnt_jobs = solv->decisionq.count;
- solv->decisioncnt_update = solv->decisionq.count;
- solv->decisioncnt_keep = solv->decisionq.count;
- solv->decisioncnt_resolve = solv->decisionq.count;
- solv->decisioncnt_weak = solv->decisionq.count;
- solv->decisioncnt_orphan = solv->decisionq.count;
- }
#if 0
solver_printdecisionq(solv, SOLV_DEBUG_RESULT);
#endif
memset(solv->decisionmap, 0, pool->nsolvables * sizeof(Id));
queue_empty(&solv->decisionq);
queue_empty(&solv->decisionq_why);
- solv->decisioncnt_jobs = solv->decisioncnt_update = solv->decisioncnt_keep = solv->decisioncnt_resolve = solv->decisioncnt_weak = solv->decisioncnt_orphan = 0;
+ queue_empty(&solv->decisionq_reason);
queue_empty(&solv->learnt_why);
queue_empty(&solv->learnt_pool);
queue_empty(&solv->branches);
MAPZERO(&solv->recommendsmap);
/* put all packages the solver already chose in the map */
- if (solv->decisioncnt_weak)
- {
- for (i = solv->decisioncnt_weak; i < solv->decisioncnt_orphan; i++)
- {
- Id why;
- why = solv->decisionq_why.elements[i];
- if (why)
- continue; /* forced by unit rule or dep resolving */
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
+ for (i = 1; i < solv->decisionq.count; i++)
+ if ((p = solv->decisionq.elements[i]) > 0 && solv->decisionq_why.elements[i] == 0)
+ {
+ if (solv->decisionq_reason.elements[solv->decisionmap[p]] == SOLVER_REASON_WEAKDEP)
MAPSET(&solv->recommendsmap, p);
- }
- }
+ }
for (i = 0; i < solv->decisionq.count; i++)
{
*infop = why > 0 ? why : -why;
if (why > 0)
return SOLVER_REASON_UNIT_RULE;
- why = -why;
- if (i == 0)
- return SOLVER_REASON_KEEP_INSTALLED; /* the systemsolvable */
- if (i < solv->decisioncnt_update)
- return SOLVER_REASON_RESOLVE_JOB;
- if (i < solv->decisioncnt_keep)
- {
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- return SOLVER_REASON_UPDATE_INSTALLED;
- }
- if (i < solv->decisioncnt_resolve)
- {
- if (solv->focus_installed && i >= solv->decisioncnt_jobs)
- return SOLVER_REASON_RESOLVE_JOB;
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- return SOLVER_REASON_KEEP_INSTALLED;
- }
- if (i < solv->decisioncnt_weak)
- {
- if (why == 0 && pp < 0)
- return SOLVER_REASON_CLEANDEPS_ERASE;
- }
- if (why > 0)
- return SOLVER_REASON_RESOLVE;
- /* weak or orphaned */
- if (i < solv->decisioncnt_orphan)
- return SOLVER_REASON_WEAKDEP;
- return SOLVER_REASON_RESOLVE_ORPHAN;
+ i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
+ return solv->decisionq_reason.elements[i];
}
break;
if (decisionno == solv->decisionq.count)
return; /* huh? */
- if (decisionno < solv->decisioncnt_weak || decisionno >= solv->decisioncnt_orphan)
+ i = solv->decisionmap[p] >= 0 ? solv->decisionmap[p] : -solv->decisionmap[p];
+ if (solv->decisionq_reason.elements[i] != SOLVER_REASON_WEAKDEP)
return; /* huh? */
/* 1) list all packages that recommend us */