+solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist)
+{
+ Pool *pool = solv->pool;
+ Queue pq;
+ int i, j, k;
+ Id name;
+
+ queue_init(&pq);
+ solv_sort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp, pool);
+ queue_push(&pq, plist->elements[0]);
+ name = pool->solvables[pq.elements[0]].name;
+ for (i = 1, j = 0; i < plist->count; i++)
+ {
+ if (pool->solvables[plist->elements[i]].name != name)
+ {
+ if (pq.count > 2)
+ solver_prune_to_highest_prio(solv, &pq);
+ for (k = 0; k < pq.count; k++)
+ plist->elements[j++] = pq.elements[k];
+ queue_empty(&pq);
+ queue_push(&pq, plist->elements[i]);
+ name = pool->solvables[pq.elements[0]].name;
+ }
+ }
+ if (pq.count > 2)
+ solver_prune_to_highest_prio(solv, &pq);
+ for (k = 0; k < pq.count; k++)
+ plist->elements[j++] = pq.elements[k];
+ queue_free(&pq);
+ plist->count = j;
+}
+
+
+#ifdef ENABLE_COMPLEX_DEPS
+
+/* simple fixed-size hash for package ids */
+#define CPLXDEPHASH_EMPTY(elements) (memset(elements, 0, sizeof(Id) * 256))
+#define CPLXDEPHASH_SET(elements, p) (elements[(p) & 255] |= (1 << ((p) >> 8 & 31)))
+#define CPLXDEPHASH_TST(elements, p) (elements[(p) & 255] && (elements[(p) & 255] & (1 << ((p) >> 8 & 31))))
+
+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++)
+ {
+ /* we rely on the fact that blocks are ordered here.
+ * if we reach a positive element, we know that we
+ * saw all negative ones */
+ for (; (p = q.elements[i]) < 0; i++)
+ {
+ if (solv->decisionmap[-p] < 0)
+ break;
+ if (solv->decisionmap[-p] == 0)
+ queue_push(&q, -p); /* undecided negative literal */
+ }
+ if (p <= 0)
+ {
+#if 0
+ printf("complex dep block cannot be true or no pos literals\n");
+#endif
+ while (q.elements[i])
+ i++;
+ if (qcnt != q.count)
+ queue_truncate(&q, qcnt);
+ continue;
+ }
+ if (qcnt == q.count)
+ {
+ /* all negative literals installed, add positive literals to map */
+ for (; (p = q.elements[i]) != 0; i++)
+ MAPSET(m, p);
+ }
+ else
+ {
+ /* at least one undecided negative literal, postpone */
+ int j, k;
+ Queue *cq;
+#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
+ while (q.elements[i])
+ i++;
+ if (!(cq = *cqp))
+ {
+ cq = solv_calloc(1, sizeof(Queue));
+ queue_init(cq);
+ queue_insertn(cq, 0, 256, 0); /* allocate hash area */
+ *cqp = cq;
+ }
+ for (j = qcnt; j < q.count; j++)
+ {
+ p = q.elements[j];
+ /* check if we already have this (dep, p) entry */
+ for (k = 256; k < cq->count; k += 2)
+ if (cq->elements[k + 1] == dep && cq->elements[k] == p)
+ break;
+ if (k == cq->count)
+ {
+ /* a new one. add to cq and hash */
+ queue_push2(cq, p, dep);
+ CPLXDEPHASH_SET(cq->elements, p);
+ }
+ }
+ queue_truncate(&q, qcnt);
+ }
+ }
+ queue_free(&q);
+}
+
+static void
+recheck_complex_deps(Solver *solv, Id p, Map *m, Queue **cqp)
+{
+ Queue *cq = *cqp;
+ Id pp;
+ int i;
+#if 0
+ printf("recheck_complex_deps for package %s\n", pool_solvid2str(solv->pool, p));
+#endif
+ /* make sure that we don't have a false hit */
+ 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... */
+
+ /* rebuild the hash, call check_complex_dep for our package */
+ CPLXDEPHASH_EMPTY(cq->elements);
+ for (i = 256; i < cq->count; i += 2)
+ if ((pp = 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
+ CPLXDEPHASH_SET(cq->elements, pp);
+}
+
+#endif
+
+
+void
+policy_update_recommendsmap(Solver *solv)