From 1e12ce5b74c95061bc696304c14aa6d25dce0406 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Thu, 16 Apr 2009 18:59:46 +0200 Subject: [PATCH] - create transaction as solver result --- src/repodata.c | 2 +- src/solver.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/solver.h | 24 ++++++ src/solverdebug.c | 107 ++++++++++++----------- tools/repo_rpmmd.c | 4 +- 5 files changed, 328 insertions(+), 54 deletions(-) diff --git a/src/repodata.c b/src/repodata.c index 1e54ff6..fc7798c 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -1265,7 +1265,7 @@ dataiterator_step(Dataiterator *di) continue; } if (!datamatcher_match(&di->matcher, di->kv.str)) - continue; + continue; } /* found something! */ return 1; diff --git a/src/solver.c b/src/solver.c index a2e82f4..2d64b66 100644 --- a/src/solver.c +++ b/src/solver.c @@ -2603,6 +2603,8 @@ solver_create(Pool *pool) solv->pool = pool; solv->installed = pool->installed; + queue_init(&solv->transaction); + queue_init(&solv->transaction_info); queue_init(&solv->ruletojob); queue_init(&solv->decisionq); queue_init(&solv->decisionq_why); @@ -2639,6 +2641,8 @@ solver_create(Pool *pool) void solver_free(Solver *solv) { + queue_free(&solv->transaction); + queue_free(&solv->transaction_info); queue_free(&solv->job); queue_free(&solv->ruletojob); queue_free(&solv->decisionq); @@ -4588,6 +4592,241 @@ findrecommendedsuggested(Solver *solv) map_free(&obsmap); } + +Solver *obsq_sortcmp_data; + +static int +obsq_sortcmp(const void *ap, const void *bp) +{ + Id a, b, oa, ob; + Solver *solv = obsq_sortcmp_data; + Pool *pool = solv->pool; + Solvable *s, *oas, *obs; + int r; + + a = ((Id *)ap)[0]; + oa = ((Id *)ap)[1]; + b = ((Id *)bp)[0]; + ob = ((Id *)bp)[1]; + if (a != b) + return a - b; + if (oa == ob) + return 0; + s = pool->solvables + a; + oas = pool->solvables + oa; + obs = pool->solvables + ob; + if (oas->name != obs->name) + { + if (oas->name == s->name) + return -1; + if (obs->name == s->name) + return 1; + return strcmp(id2str(pool, oas->name), id2str(pool, obs->name)); + } + r = evrcmp(pool, oas->evr, obs->evr, EVRCMP_COMPARE); + if (r) + return -r; /* highest version first */ + return oa - ob; +} + +void +solver_transaction_info(Solver *solv, Id p, Queue *out) +{ + Pool *pool = solv->pool; + Solvable *s = pool->solvables + p; + Queue *ti = &solv->transaction_info; + int i; + + queue_empty(out); + if (p <= 0 || !s->repo) + return; + if (s->repo == solv->installed) + { + /* find which packages obsolete us */ + for (i = 0; i < ti->count; i += 2) + if (ti->elements[i + 1] == p) + { + queue_push(out, p); + queue_push(out, ti->elements[i]); + } + if (out->count > 2) + { + /* sort obsoleters */ + obsq_sortcmp_data = solv; + qsort(out->elements, out->count / 2, 2 * sizeof(Id), obsq_sortcmp); + } + for (i = 0; i < out->count; i += 2) + out->elements[i] = out->elements[i / 2 + 1]; + out->count /= 2; + } + else + { + /* find the packages we obsolete */ + for (i = 0; i < ti->count; i += 2) + { + if (ti->elements[i] == p) + queue_push(out, ti->elements[i + 1]); + else if (out->count) + break; + } + } +} + +Id +solver_transaction_pkg(Solver *solv, Id p) +{ + Queue ti; + Id tibuf[5]; + + queue_init_buffer(&ti, tibuf, sizeof(tibuf)/sizeof(*tibuf)); + solver_transaction_info(solv, p, &ti); + p = ti.count ? ti.elements[0] : 0; + queue_free(&ti); + return p; +} + +static void +create_transaction(Solver *solv) +{ + Pool *pool = solv->pool; + Repo *installed = solv->installed; + Queue *ti = &solv->transaction_info; + int i, j, r, noobs; + Id p, p2, pp2; + Solvable *s, *s2; + + queue_empty(&solv->transaction); + queue_empty(ti); + + /* first create obsoletes index */ + if (installed) + { + for (i = 0; i < solv->decisionq.count; i++) + { + p = solv->decisionq.elements[i]; + if (p <= 0 || p == SYSTEMSOLVABLE) + continue; + s = pool->solvables + p; + if (s->repo == installed) + continue; + noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p); + FOR_PROVIDES(p2, pp2, s->name) + { + if (solv->decisionmap[p2] > 0) + continue; + s2 = pool->solvables + p2; + if (s2->repo != installed) + continue; + if (noobs && (s->name != s2->name || s->evr != s2->evr || s->arch != s2->arch)) + continue; + if (!solv->implicitobsoleteusesprovides && s->name != s2->name) + continue; + queue_push(ti, p); + queue_push(ti, p2); + } + if (s->obsoletes && !noobs) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(p2, pp2, obs) + { + s2 = pool->solvables + p2; + if (s2->repo != installed) + continue; + if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs)) + continue; + queue_push(ti, p); + queue_push(ti, p2); + } + } + } + } + obsq_sortcmp_data = solv; + qsort(ti->elements, ti->count / 2, 2 * sizeof(Id), obsq_sortcmp); + /* now unify */ + for (i = j = 0; i < ti->count; i += 2) + { + if (j && ti->elements[i] == ti->elements[j - 2] && ti->elements[i + 1] == ti->elements[j - 1]) + continue; + ti->elements[j++] = ti->elements[i]; + ti->elements[j++] = ti->elements[i + 1]; + } + ti->count = j; + } + + if (installed) + { + FOR_REPO_SOLVABLES(installed, p, s) + { + if (solv->decisionmap[p] > 0) + continue; + p2 = solver_transaction_pkg(solv, p); + if (!p2) + queue_push(&solv->transaction, SOLVER_TRANSACTION_ERASE); + else + { + s2 = pool->solvables + p2; + if (s->name == s2->name) + { + if (s->evr == s2->evr && solvable_identical(s, s2)) + queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALLED); + else + { + r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE); + if (r < 0) + queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADED); + else if (r > 0) + queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADED); + else + queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGED); + } + } + else + queue_push(&solv->transaction, SOLVER_TRANSACTION_OBSOLETED); + } + queue_push(&solv->transaction, p); + } + } + for (i = 0; i < solv->decisionq.count; i++) + { + p = solv->decisionq.elements[i]; + if (p < 0 || p == SYSTEMSOLVABLE) + continue; + s = pool->solvables + p; + if (solv->installed && s->repo == solv->installed) + continue; + noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p); + p2 = solver_transaction_pkg(solv, p); + if (noobs) + queue_push(&solv->transaction, p2 ? SOLVER_TRANSACTION_MULTIREINSTALL : SOLVER_TRANSACTION_MULTIINSTALL); + else if (!p2) + queue_push(&solv->transaction, SOLVER_TRANSACTION_INSTALL); + else + { + s2 = pool->solvables + p2; + if (s->name == s2->name) + { + if (s->evr == s2->evr && solvable_identical(s, s2)) + queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALL); + else + { + r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE); + if (r > 0) + queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADE); + else if (r < 0) + queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADE); + else + queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGE); + } + } + else + queue_push(&solv->transaction, SOLVER_TRANSACTION_RENAME); + } + queue_push(&solv->transaction, p); + } +} + /* * * solve job queue @@ -5097,6 +5336,12 @@ solver_solve(Solver *solv, Queue *job) } solv->problems.count = j; } + + /* + * finally prepare transaction info + */ + create_transaction(solv); + POOL_DEBUG(SAT_DEBUG_STATS, "final solver statistics: %d problems, %d learned rules, %d unsolvable\n", solv->problems.count / 2, solv->stats_learned, solv->stats_unsolvable); POOL_DEBUG(SAT_DEBUG_STATS, "solver_solve took %d ms\n", sat_timems(solve_start)); } diff --git a/src/solver.h b/src/solver.h index 2731306..c271591 100644 --- a/src/solver.h +++ b/src/solver.h @@ -63,6 +63,9 @@ typedef struct solver { Pool *pool; Queue job; /* copy of the job we're solving */ + Queue transaction; /* solver result */ + Queue transaction_info; /* transaction obsoletes info */ + Repo *installed; /* copy of pool->installed */ /* list of rules, ordered @@ -325,9 +328,30 @@ typedef enum { #define SOLVER_SOLUTION_DISTUPGRADE (-1) #define SOLVER_SOLUTION_INFARCH (-2) +#define SOLVER_TRANSACTION_ERASE 0x10 +#define SOLVER_TRANSACTION_REINSTALLED 0x11 +#define SOLVER_TRANSACTION_DOWNGRADED 0x12 +#define SOLVER_TRANSACTION_CHANGED 0x13 +#define SOLVER_TRANSACTION_UPGRADED 0x14 +#define SOLVER_TRANSACTION_OBSOLETED 0x15 + +#define SOLVER_TRANSACTION_INSTALL 0x20 +#define SOLVER_TRANSACTION_REINSTALL 0x21 +#define SOLVER_TRANSACTION_DOWNGRADE 0x22 +#define SOLVER_TRANSACTION_CHANGE 0x23 +#define SOLVER_TRANSACTION_UPGRADE 0x24 +#define SOLVER_TRANSACTION_RENAME 0x25 + +#define SOLVER_TRANSACTION_MULTIINSTALL 0x30 +#define SOLVER_TRANSACTION_MULTIREINSTALL 0x31 + + extern Solver *solver_create(Pool *pool); extern void solver_free(Solver *solv); extern void solver_solve(Solver *solv, Queue *job); +extern void solver_transaction_info(Solver *solv, Id p, Queue *info); +extern Id solver_transaction_pkg(Solver *solv, Id p); + extern int solver_dep_installed(Solver *solv, Id dep); extern int solver_splitprovides(Solver *solv, Id dep); diff --git a/src/solverdebug.c b/src/solverdebug.c index 3da35d8..c63a280 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -253,9 +253,10 @@ solver_printdecisions(Solver *solv) { Pool *pool = solv->pool; Repo *installed = solv->installed; - Id p, *obsoletesmap = solver_create_decisions_obsoletesmap(solv); - int i; + Id p; + int i, j; Solvable *s; + Queue iq; IF_POOLDEBUG (SAT_DEBUG_SCHUBI) { @@ -271,64 +272,68 @@ solver_printdecisions(Solver *solv) POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); POOL_DEBUG(SAT_DEBUG_RESULT, "transaction:\n"); - /* print solvables to be erased */ - - if (installed) - { - FOR_REPO_SOLVABLES(installed, p, s) - { - if (solv->decisionmap[p] > 0) - continue; - if (obsoletesmap[p]) - continue; - POOL_DEBUG(SAT_DEBUG_RESULT, " erase %s\n", solvable2str(pool, s)); - } - } - - /* print solvables to be installed */ - - for (i = 0; i < solv->decisionq.count; i++) + queue_init(&iq); + for (i = 0; i < solv->transaction.count; i += 2) { - int j; - p = solv->decisionq.elements[i]; - if (p < 0) - continue; - if (p == SYSTEMSOLVABLE) - continue; - s = pool->solvables + p; - if (installed && s->repo == installed) - continue; - - if (!obsoletesmap[p]) + s = pool->solvables + solv->transaction.elements[i + 1]; + switch(solv->transaction.elements[i]) { + case SOLVER_TRANSACTION_MULTI_INSTALL: + POOL_DEBUG(SAT_DEBUG_RESULT, " multi install %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_MULTI_REINSTALL: + POOL_DEBUG(SAT_DEBUG_RESULT, " multi reinstall %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_INSTALL: POOL_DEBUG(SAT_DEBUG_RESULT, " install %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_REINSTALL: + POOL_DEBUG(SAT_DEBUG_RESULT, " reinstall %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_DOWNGRADE: + POOL_DEBUG(SAT_DEBUG_RESULT, " downgrade %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_CHANGE: + POOL_DEBUG(SAT_DEBUG_RESULT, " change %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_UPGRADE: + case SOLVER_TRANSACTION_RENAME: + POOL_DEBUG(SAT_DEBUG_RESULT, " upgrade %s", solvable2str(pool, s)); + break; + case SOLVER_TRANSACTION_ERASE: + POOL_DEBUG(SAT_DEBUG_RESULT, " erase %s", solvable2str(pool, s)); + break; + default: + break; } - else - { - Id xp, xpp; - FOR_PROVIDES(xp, xpp, s->name) + switch(solv->transaction.elements[i]) + { + case SOLVER_TRANSACTION_INSTALL: + case SOLVER_TRANSACTION_ERASE: + POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); + break; + case SOLVER_TRANSACTION_REINSTALL: + case SOLVER_TRANSACTION_DOWNGRADE: + case SOLVER_TRANSACTION_CHANGE: + case SOLVER_TRANSACTION_UPGRADE: + case SOLVER_TRANSACTION_RENAME: + solver_transaction_info(solv, solv->transaction.elements[i + 1], &iq); + if (iq.count) { - Solvable *s2 = pool->solvables + xp; - if (s2->name != s->name) - continue; - if (evrcmp(pool, s->evr, s2->evr, EVRCMP_MATCH_RELEASE) < 0) - break; + POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes"); + for (j = 0; j < iq.count; j++) + POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + iq.elements[j])); + POOL_DEBUG(SAT_DEBUG_RESULT, ")"); } - if (xp) - POOL_DEBUG(SAT_DEBUG_RESULT, " downgrade %s", solvable2str(pool, s)); - else - POOL_DEBUG(SAT_DEBUG_RESULT, " upgrade %s", solvable2str(pool, s)); - POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes"); - for (j = installed->start; j < installed->end; j++) - if (obsoletesmap[j] == p) - POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j)); - POOL_DEBUG(SAT_DEBUG_RESULT, ")"); + POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); + break; + default: + break; } - POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); } - POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); + queue_free(&iq); - sat_free(obsoletesmap); + POOL_DEBUG(SAT_DEBUG_RESULT, "\n"); if (solv->recommendations.count) { diff --git a/tools/repo_rpmmd.c b/tools/repo_rpmmd.c index c72aba5..027c723 100644 --- a/tools/repo_rpmmd.c +++ b/tools/repo_rpmmd.c @@ -586,18 +586,18 @@ set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm) return; sevr = p + 1; pool = s->repo->pool; - name = id2str(pool, s->name); - evr = id2str(pool, s->evr); if (!strcmp(sarch, "src.rpm")) repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC); else if (!strcmp(sarch, "nosrc.rpm")) repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC); else repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1)); + evr = id2str(pool, s->evr); if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0) repodata_set_void(data, handle, SOLVABLE_SOURCEEVR); else repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1)); + name = id2str(pool, s->name); if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0) repodata_set_void(data, handle, SOLVABLE_SOURCENAME); else -- 2.7.4