summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2014-03-07 16:55:36 +0100
committerMichael Schroeder <mls@suse.de>2014-03-07 16:55:36 +0100
commitab5d2c56c168ae56fea013007798039228be5529 (patch)
treee89b853e6f3487740e34aefe6404ff58721c3001
parentab01c1711732273e571d70dbbbd2da6d0645f774 (diff)
downloadlibsolv-ab5d2c56c168ae56fea013007798039228be5529.tar.gz
libsolv-ab5d2c56c168ae56fea013007798039228be5529.tar.bz2
libsolv-ab5d2c56c168ae56fea013007798039228be5529.zip
also support complex deps when doing recommends/suggests filtering
-rw-r--r--src/policy.c160
-rw-r--r--src/solver.c119
-rw-r--r--src/solver.h2
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 */