also support complex deps when doing recommends/suggests filtering
authorMichael Schroeder <mls@suse.de>
Fri, 7 Mar 2014 15:55:36 +0000 (16:55 +0100)
committerMichael Schroeder <mls@suse.de>
Fri, 7 Mar 2014 15:55:36 +0000 (16:55 +0100)
src/policy.c
src/solver.c
src/solver.h

index 6287b7c..98991c5 100644 (file)
@@ -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);
+           }
        }
     }
 
index 8ca9efe..7a634ec 100644 (file)
@@ -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);
index ae05bb1..7646624 100644 (file)
@@ -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 */