From 5ed9867b973d98b8405926f9ba11134a01337b32 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Mon, 29 Jun 2009 12:35:50 +0200 Subject: [PATCH] - add some comments, move code around - add support for RPM_ADD_WITH_PKGID, RPM_ADD_NO_FILELIST, RPM_ADD_NO_RPMLIBREQS --- examples/solv.c | 21 ++++-- ext/repo_rpmdb.c | 222 +++++++++++++++++++++++++++++++----------------------- ext/repo_rpmdb.h | 5 +- src/repo.c | 201 ++++++++++++++++++++++++------------------------ src/repo.h | 8 +- src/repodata.c | 31 +++++--- src/repodata.h | 2 +- src/repopage.c | 10 ++- src/solverdebug.c | 2 +- src/transaction.c | 12 ++- 10 files changed, 294 insertions(+), 220 deletions(-) diff --git a/examples/solv.c b/examples/solv.c index 89253d1..01c02a3 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -68,6 +68,14 @@ struct repoinfo { #define TYPE_RPMMD 2 #define TYPE_PLAINDIR 3 +static int +read_repoinfos_sort(const void *ap, const void *bp) +{ + const struct repoinfo *a = ap; + const struct repoinfo *b = bp; + return strcmp(a->alias, b->alias); +} + struct repoinfo * read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) { @@ -171,6 +179,7 @@ read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp) cinfo = 0; } closedir(dir); + qsort(repoinfos, nrepoinfos, sizeof(*repoinfos), read_repoinfos_sort); *nrepoinfosp = nrepoinfos; return repoinfos; } @@ -589,13 +598,15 @@ main(int argc, char **argv) FILE **newpkgsfps; struct fcstate fcstate; - if (!strcmp(argv[1], "install") || !strcmp(argv[1], "in")) + argc--; + argv++; + if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in")) mode = SOLVER_INSTALL; - else if (!strcmp(argv[1], "erase") || !strcmp(argv[1], "rm")) + else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm")) mode = SOLVER_ERASE; - else if (!strcmp(argv[1], "show")) + else if (!strcmp(argv[0], "show")) mode = 0; - else if (!strcmp(argv[1], "update") || !strcmp(argv[1], "up")) + else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up")) mode = SOLVER_UPDATE; else { @@ -615,7 +626,7 @@ main(int argc, char **argv) pool_createwhatprovides(pool); queue_init(&job); - for (i = 2; i < argc; i++) + for (i = 1; i < argc; i++) mkselect(pool, argv[i], 0, &job); if (!job.count && mode == SOLVER_UPDATE) updateall = 1; diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index 826fa13..5de20b0 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -88,6 +88,11 @@ #define TAG_ENHANCESVERSION 1160 #define TAG_ENHANCESFLAGS 1161 +#define SIGTAG_SIZE 1000 +#define SIGTAG_PGP 1002 /* RSA signature */ +#define SIGTAG_MD5 1004 /* header+payload md5 checksum */ +#define SIGTAG_GPG 1005 /* DSA signature */ + #define DEP_LESS (1 << 1) #define DEP_GREATER (1 << 2) #define DEP_EQUAL (1 << 3) @@ -107,12 +112,12 @@ typedef struct rpmhead { unsigned char data[1]; } RpmHead; -static int -headexists(RpmHead *h, int tag) + +static inline unsigned char * +headfindtag(RpmHead *h, int tag) { unsigned int i; unsigned char *d, taga[4]; - d = h->dp - 16; taga[0] = tag >> 24; taga[1] = tag >> 16; @@ -120,27 +125,23 @@ headexists(RpmHead *h, int tag) taga[3] = tag; for (i = 0; i < h->cnt; i++, d -= 16) if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - return 1; + return d; return 0; } +static int +headexists(RpmHead *h, int tag) +{ + return headfindtag(h, tag) ? 1 : 0; +} + static unsigned int * headint32array(RpmHead *h, int tag, int *cnt) { unsigned int i, o, *r; - unsigned char *d, taga[4]; + unsigned char *d = headfindtag(h, tag); - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) return 0; o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; @@ -155,23 +156,14 @@ headint32array(RpmHead *h, int tag, int *cnt) return r; } +/* returns the first entry of an integer array */ static unsigned int headint32(RpmHead *h, int tag) { unsigned int i, o; - unsigned char *d, taga[4]; + unsigned char *d = headfindtag(h, tag); - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4) return 0; o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; @@ -185,19 +177,9 @@ static unsigned int * headint16array(RpmHead *h, int tag, int *cnt) { unsigned int i, o, *r; - unsigned char *d, taga[4]; + unsigned char *d = headfindtag(h, tag); - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3) + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3) return 0; o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; @@ -215,22 +197,14 @@ headint16array(RpmHead *h, int tag, int *cnt) static char * headstring(RpmHead *h, int tag) { - unsigned int i, o; - unsigned char *d, taga[4]; - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; + unsigned int o; + unsigned char *d = headfindtag(h, tag); /* 6: STRING, 9: I18NSTRING */ - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9)) + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9)) return 0; o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; + if (o >= h->dcnt) + return 0; return (char *)h->dp + o; } @@ -238,20 +212,10 @@ static char ** headstringarray(RpmHead *h, int tag, int *cnt) { unsigned int i, o; - unsigned char *d, taga[4]; + unsigned char *d = headfindtag(h, tag); char **r; - d = h->dp - 16; - taga[0] = tag >> 24; - taga[1] = tag >> 16; - taga[2] = tag >> 8; - taga[3] = tag; - for (i = 0; i < h->cnt; i++, d -= 16) - if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) - break; - if (i >= h->cnt) - return 0; - if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8) + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8) return 0; o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; @@ -273,6 +237,22 @@ headstringarray(RpmHead *h, int tag, int *cnt) return r; } +static unsigned char * +headbinary(RpmHead *h, int tag, unsigned int *sizep) +{ + unsigned int i, o; + unsigned char *d = headfindtag(h, tag); + if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 7) + return 0; + o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]; + i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15]; + if (o > h->dcnt || o + i < o || o + i > h->dcnt) + return 0; + if (sizep) + *sizep = i; + return h->dp + o; +} + static char *headtoevr(RpmHead *h) { unsigned int epoch; @@ -381,16 +361,28 @@ setutf8string(Repodata *repodata, Id handle, Id tag, const char *str) sat_free(buf); } + +#define MAKEDEPS_FILTER_WEAK (1 << 0) +#define MAKEDEPS_FILTER_STRONG (1 << 1) +#define MAKEDEPS_NO_RPMLIB (1 << 2) + +/* + * strong: 0: ignore strongness + * 1: filter to strong + * 2: filter to weak + */ static unsigned int -makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int strong) +makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int flags) { char **n, **v; unsigned int *f; int i, cc, nc, vc, fc; - int haspre = 0; + int haspre; unsigned int olddeps; Id *ida; + int strong; + strong = flags & (MAKEDEPS_FILTER_STRONG|MAKEDEPS_FILTER_WEAK); n = headstringarray(rpmhead, tagn, &nc); if (!n) return 0; @@ -414,19 +406,26 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, } cc = nc; - if (strong) + haspre = 0; /* add no prereq marker */ + if (flags) { + /* we do filtering */ cc = 0; for (i = 0; i < nc; i++) - if ((f[i] & DEP_STRONG) == (strong == 1 ? 0 : DEP_STRONG)) - { - cc++; - if ((f[i] & DEP_PRE) != 0) - haspre = 1; - } + { + if (strong && (f[i] & DEP_STRONG) != (strong == MAKEDEPS_FILTER_WEAK ? 0 : DEP_STRONG)) + continue; + if ((flags & MAKEDEPS_NO_RPMLIB) != 0) + if (!strncmp(n[i], "rpmlib(", 7)) + continue; + if ((f[i] & DEP_PRE) != 0) + haspre = 1; + cc++; + } } - else + else if (tagn == TAG_REQUIRENAME) { + /* no filtering, just look for the first prereq */ for (i = 0; i < nc; i++) if ((f[i] & DEP_PRE) != 0) { @@ -434,8 +433,6 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, break; } } - if (tagn != TAG_REQUIRENAME) - haspre = 0; if (cc == 0) { sat_free(n); @@ -452,16 +449,19 @@ makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, { if (haspre != 1) break; - haspre = 2; + haspre = 2; /* pass two: prereqs */ i = 0; *ida++ = SOLVABLE_PREREQMARKER; } - if (strong && (f[i] & DEP_STRONG) != (strong == 1 ? 0 : DEP_STRONG)) + if (strong && (f[i] & DEP_STRONG) != (strong == MAKEDEPS_FILTER_WEAK ? 0 : DEP_STRONG)) continue; if (haspre == 1 && (f[i] & DEP_PRE) != 0) continue; if (haspre == 2 && (f[i] & DEP_PRE) == 0) continue; + if ((flags & MAKEDEPS_NO_RPMLIB) != 0) + if (!strncmp(n[i], "rpmlib(", 7)) + continue; if (f[i] & (DEP_LESS|DEP_GREATER|DEP_EQUAL)) { Id name, evr; @@ -796,7 +796,7 @@ addsourcerpm(Pool *pool, Repodata *data, Id handle, char *sourcerpm, char *name, } static int -rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead) +rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, int flags) { char *name; char *evr; @@ -828,17 +828,18 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead) s->vendor = str2id(pool, headstring(rpmhead, TAG_VENDOR), 1); s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0); - s->provides = addfileprovides(pool, repo, data, s, rpmhead, s->provides); + if ((flags & RPM_ADD_NO_FILELIST) == 0) + s->provides = addfileprovides(pool, repo, data, s, rpmhead, s->provides); if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, 0); + s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, (flags & RPM_ADD_NO_RPMLIBREQS) ? MAKEDEPS_NO_RPMLIB : 0); s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0); s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0); - s->recommends = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 2); - s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 1); - s->supplements = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 2); - s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 1); + s->recommends = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, MAKEDEPS_FILTER_STRONG); + s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, MAKEDEPS_FILTER_WEAK); + s->supplements = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, MAKEDEPS_FILTER_STRONG); + s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, MAKEDEPS_FILTER_WEAK); s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0); s->conflicts = repo_fix_conflicts(repo, s->conflicts); @@ -1378,7 +1379,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt); rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; - if (rpm2solv(pool, repo, data, s, rpmhead)) + if (rpm2solv(pool, repo, data, s, rpmhead, flags)) { i++; s = 0; @@ -1613,7 +1614,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt); rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; - rpm2solv(pool, repo, data, s, rpmhead); + rpm2solv(pool, repo, data, s, rpmhead, flags); if ((flags & RPMDB_REPORT_PROGRESS) != 0) { if (done < count) @@ -1668,6 +1669,8 @@ repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags) int headerstart, headerend; struct stat stb; Repodata *data; + unsigned char pkgid[16]; + int gotpkgid; if (!(flags & REPO_REUSE_REPODATA)) data = repo_add_repodata(repo, 0); @@ -1718,16 +1721,47 @@ repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags) sigdsize += sigcnt * 16; sigdsize = (sigdsize + 7) & ~7; headerstart = 96 + 16 + sigdsize; - while (sigdsize) + gotpkgid = 0; + if ((flags & RPM_ADD_WITH_PKGID) != 0) { - l = sigdsize > 4096 ? 4096 : sigdsize; - if (fread(lead, l, 1, fp) != 1) + unsigned char *chksum; + unsigned int chksumsize; + /* extract pkgid from the signature header */ + if (sigdsize > rpmheadsize) + { + rpmheadsize = sigdsize + 128; + rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize); + } + if (fread(rpmhead->data, sigdsize, 1, fp) != 1) { fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); fclose(fp); continue; } - sigdsize -= l; + rpmhead->cnt = sigcnt; + rpmhead->dcnt = sigdsize - sigcnt * 16; + rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; + chksum = headbinary(rpmhead, SIGTAG_MD5, &chksumsize); + if (chksum && chksumsize == 16) + { + gotpkgid = 1; + memcpy(pkgid, chksum, 16); + } + } + else + { + /* just skip the signature header */ + while (sigdsize) + { + l = sigdsize > 4096 ? 4096 : sigdsize; + if (fread(lead, l, 1, fp) != 1) + { + fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); + fclose(fp); + continue; + } + sigdsize -= l; + } } if (fread(lead, 16, 1, fp) != 1) { @@ -1780,13 +1814,15 @@ repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags) } fclose(fp); s = pool_id2solvable(pool, repo_add_solvable(repo)); - rpm2solv(pool, repo, data, s, rpmhead); + rpm2solv(pool, repo, data, s, rpmhead, flags); if (data) { Id handle = s - pool->solvables; repodata_set_location(data, handle, 0, 0, rpms[i]); repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)((stb.st_size + 1023) / 1024)); repodata_set_num(data, handle, SOLVABLE_HEADEREND, headerend); + if (gotpkgid) + repodata_set_bin_checksum(data, handle, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid); } } if (rpmhead) diff --git a/ext/repo_rpmdb.h b/ext/repo_rpmdb.h index 3e80302..abd7364 100644 --- a/ext/repo_rpmdb.h +++ b/ext/repo_rpmdb.h @@ -10,7 +10,10 @@ extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags); extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags); -#define RPMDB_REPORT_PROGRESS (1 << 8) +#define RPMDB_REPORT_PROGRESS (1 << 8) +#define RPM_ADD_WITH_PKGID (1 << 9) +#define RPM_ADD_NO_FILELIST (1 << 10) +#define RPM_ADD_NO_RPMLIBREQS (1 << 11) #define RPM_ITERATE_FILELIST_ONLYDIRS (1 << 0) #define RPM_ITERATE_FILELIST_WITHMD5 (1 << 1) diff --git a/src/repo.c b/src/repo.c index 58632eb..494896e 100644 --- a/src/repo.c +++ b/src/repo.c @@ -69,11 +69,108 @@ repo_freedata(Repo *repo) } /* - * add Id to repo - * olddeps = old array to extend + * remove repo from pool, zero out (i.e. free) solvables * */ +void +repo_free(Repo *repo, int reuseids) +{ + Pool *pool = repo->pool; + Solvable *s; + int i; + + pool_freewhatprovides(pool); + if (repo == pool->installed) + pool->installed = 0; + + if (reuseids && repo->end == pool->nsolvables) + { + /* it's ok to reuse the ids. As this is the last repo, we can + just shrink the solvable array */ + for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--) + if (s->repo != repo) + break; + repo->end = i + 1; + pool->nsolvables = i + 1; + } + /* zero out (i.e. free) solvables belonging to this repo */ + for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++) + if (s->repo == repo) + memset(s, 0, sizeof(*s)); + for (i = 0; i < pool->nrepos; i++) /* find repo in pool */ + if (pool->repos[i] == repo) + break; + if (i == pool->nrepos) /* repo not in pool, return */ + return; + if (i < pool->nrepos - 1) + { + memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *)); + /* fix repo ids */ + for (; i < pool->nrepos - 1; i++) + pool->repos[i]->repoid = i + 1; + } + pool->nrepos--; + repo_freedata(repo); +} + +void +repo_freeallrepos(Pool *pool, int reuseids) +{ + int i; + + pool_freewhatprovides(pool); + for (i = 0; i < pool->nrepos; i++) + repo_freedata(pool->repos[i]); + pool->repos = sat_free(pool->repos); + pool->nrepos = 0; + /* the first two solvables don't belong to a repo */ + pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids); +} + + +/* repository sidedata is solvable data allocated on demand. + * It is used for data that is normally not present + * in the solvable like the rpmdbid. + * The solvable allocation funcions need to make sure that + * the sidedata gets extended if new solvables get added. + */ + +#define REPO_SIDEDATA_BLOCK 63 + +void * +repo_sidedata_create(Repo *repo, size_t size) +{ + return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK); +} + +void * +repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count) +{ + int n = repo->end - repo->start; + if (p < repo->start) + { + int d = repo->start - p; + b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK); + memmove((char *)b + d * size, b, n * size); + memset(b, 0, d * size); + n += d; + } + if (p + count > repo->end) + { + int d = p + count - repo->end; + b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK); + memset((char *)b + n * size, 0, d * size); + } + return b; +} + +/* + * add Id to idarraydata used to store dependencies + * olddeps: old array offset to extend + * returns new array offset + */ + Offset repo_addid(Repo *repo, Offset olddeps, Id id) { @@ -129,7 +226,7 @@ repo_addid(Repo *repo, Offset olddeps, Id id) * marker= 0 for normal dep * marker > 0 add dep after marker * marker < 0 add dep after -marker - * + * returns new start of dependency array */ Offset repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker) @@ -211,6 +308,9 @@ repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker) /* * reserve Ids * make space for 'num' more dependencies + * returns new start of dependency array + * + * reserved ids will always begin at offset idarraysize */ Offset @@ -263,95 +363,6 @@ repo_reserve_ids(Repo *repo, Offset olddeps, int num) } -/* - * remove repo from pool, zero out solvables - * - */ - -void -repo_free(Repo *repo, int reuseids) -{ - Pool *pool = repo->pool; - Solvable *s; - int i; - - pool_freewhatprovides(pool); - if (repo == pool->installed) - pool->installed = 0; - - if (reuseids && repo->end == pool->nsolvables) - { - /* it's ok to reuse the ids. As this is the last repo, we can - just shrink the solvable array */ - for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--) - if (s->repo != repo) - break; - repo->end = i + 1; - pool->nsolvables = i + 1; - } - /* zero out solvables belonging to this repo */ - for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++) - if (s->repo == repo) - memset(s, 0, sizeof(*s)); - for (i = 0; i < pool->nrepos; i++) /* find repo in pool */ - if (pool->repos[i] == repo) - break; - if (i == pool->nrepos) /* repo not in pool, return */ - return; - if (i < pool->nrepos - 1) - { - memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *)); - /* fix repo ids */ - for (; i < pool->nrepos - 1; i++) - pool->repos[i]->repoid = i + 1; - } - pool->nrepos--; - repo_freedata(repo); -} - -void -repo_freeallrepos(Pool *pool, int reuseids) -{ - int i; - - pool_freewhatprovides(pool); - for (i = 0; i < pool->nrepos; i++) - repo_freedata(pool->repos[i]); - pool->repos = sat_free(pool->repos); - pool->nrepos = 0; - /* the first two solvables don't belong to a repo */ - pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids); -} - - -#define REPO_SIDEDATA_BLOCK 63 - -void * -repo_sidedata_create(Repo *repo, size_t size) -{ - return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK); -} - -void * -repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count) -{ - int n = repo->end - repo->start; - if (p < repo->start) - { - int d = repo->start - p; - b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK); - memmove((char *)b + d * size, b, n * size); - memset(b, 0, d * size); - n += d; - } - if (p + count > repo->end) - { - int d = p + count - repo->end; - b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK); - memset((char *)b + n * size, 0, d * size); - } - return b; -} Offset repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens) @@ -895,11 +906,7 @@ repo_lookup_id(Repo *repo, Id entry, Id keyname) { Id id = repodata_lookup_id(data, entry, keyname); if (id) - { - if (data->localpool) - id = repodata_globalize_id(data, id); - return id; - } + return data->localpool ? repodata_globalize_id(data, id, 1) : id; } } } diff --git a/src/repo.h b/src/repo.h index 2fdfa63..b5329e9 100644 --- a/src/repo.h +++ b/src/repo.h @@ -71,13 +71,13 @@ static inline Id repo_add_solvable(Repo *repo) } else { - if (repo->rpmdbid) - repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, 1); if (p < repo->start) repo->start = p; if (p + 1 > repo->end) repo->end = p + 1; } + if (repo->rpmdbid) + repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, 1); repo->nsolvables++; repo->pool->solvables[p].repo = repo; return p; @@ -98,13 +98,13 @@ static inline Id repo_add_solvable_block(Repo *repo, int count) } else { - if (repo->rpmdbid) - repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count); if (p < repo->start) repo->start = p; if (p + count > repo->end) repo->end = p + count; } + if (repo->rpmdbid) + repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count); repo->nsolvables += count; for (s = repo->pool->solvables + p; count--; s++) s->repo = repo; diff --git a/src/repodata.c b/src/repodata.c index fdb7e3a..319f9ab 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -10,6 +10,8 @@ * * Manage data coming from one repository * + * a repository can contain multiple repodata entries, consisting of + * different sets of keys and different sets of solvables */ #define _GNU_SOURCE @@ -529,6 +531,14 @@ repodata_lookup_id(Repodata *data, Id solvid, Id keyname) return id; } +Id +repodata_globalize_id(Repodata *data, Id id, int create) +{ + if (!id || !data || !data->localpool) + return id; + return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create); +} + const char * repodata_lookup_str(Repodata *data, Id solvid, Id keyname) { @@ -1434,6 +1444,7 @@ repodata_extend(Repodata *data, Id p) } } +/* extend repodata so that it includes solvables from start to start + num - 1 */ void repodata_extend_block(Repodata *data, Id start, Id num) { @@ -1625,6 +1636,8 @@ repodata_set_str(Repodata *data, Id solvid, Id keyname, const char *str) data->attrdatalen += l; } +/* add an array element consisting of entrysize Ids to the repodata. modifies attriddata + * so that the caller can append the new element there */ static void repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize) { @@ -1721,9 +1734,9 @@ hexstr2bytes(unsigned char *buf, const char *str, int buflen) int i; for (i = 0; i < buflen; i++) { -#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \ - : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \ - : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \ +#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \ + : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \ + : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \ : -1) int v = c2h(*str); str++; @@ -1776,6 +1789,7 @@ repodata_chk2str(Repodata *data, Id type, const unsigned char *buf) return str; } +/* rpm filenames don't contain the epoch, so strip it */ static inline const char * evrid2vrstr(Pool *pool, Id evrid) { @@ -1856,14 +1870,6 @@ repodata_set_location(Repodata *data, Id solvid, int medianr, const char *dir, c repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file); } -Id -repodata_globalize_id(Repodata *data, Id id) -{ - if (!data || !data->localpool) - return id; - return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1); -} - void repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2) { @@ -1939,6 +1945,7 @@ repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle) data->attriddata[data->attriddatalen++] = 0; } +/* add all attrs from src to dest */ void repodata_merge_attrs(Repodata *data, Id dest, Id src) { @@ -2089,7 +2096,7 @@ repodata_serialize_key(Repodata *data, struct extdata *newincore, schemaid = repodata_schema2id(data, schema, 1); else if (schemaid != repodata_schema2id(data, schema, 0)) { - pool_debug(data->repo->pool, SAT_FATAL, "substructs with different schemas\n"); + pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n"); exit(1); } #if 0 diff --git a/src/repodata.h b/src/repodata.h index e425482..74698bf 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -230,7 +230,7 @@ void repodata_merge_attrs(Repodata *data, Id dest, Id src); void repodata_disable_paging(Repodata *data); /* helper functions */ -Id repodata_globalize_id(Repodata *data, Id id); +Id repodata_globalize_id(Repodata *data, Id id, int create); Id repodata_str2dir(Repodata *data, const char *dir, int create); const char *repodata_dir2str(Repodata *data, Id did, const char *suf); const char *repodata_chk2str(Repodata *data, Id type, const unsigned char *buf); diff --git a/src/repopage.c b/src/repopage.c index 6ce3ca8..1ba8f7f 100644 --- a/src/repopage.c +++ b/src/repopage.c @@ -8,8 +8,14 @@ /* * repopage.c * - * Pageing and compression functions for the vertical repository data - * + * Paging and compression functions for the vertical repository data. + * Vertical data is grouped by key, normal data is grouped by solvable. + * This makes searching for a string in vertical data fast as there's + * no need to skip over data if keys we're not interested in. + * + * The vertical data is split into pages, each page is compressed with a fast + * compression algorithm. These pages are read in on demand, not recently used + * pages automatically get dropped. */ #define _XOPEN_SOURCE 500 diff --git a/src/solverdebug.c b/src/solverdebug.c index 6d5af97..f636a98 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -436,7 +436,7 @@ solver_printtransaction(Solver *solv) POOL_DEBUG(SAT_DEBUG_RESULT, "upgraded packages (%d):\n", cnt); break; case SOLVER_TRANSACTION_VENDORCHANGE: - POOL_DEBUG(SAT_DEBUG_RESULT, "vendor change from %s to %s (%d):\n", id2strnone(pool, classes.elements[i + 2]), id2strnone(pool, classes.elements[i + 3]), cnt); + POOL_DEBUG(SAT_DEBUG_RESULT, "vendor change from '%s' to '%s' (%d):\n", id2strnone(pool, classes.elements[i + 2]), id2strnone(pool, classes.elements[i + 3]), cnt); break; case SOLVER_TRANSACTION_ARCHCHANGE: POOL_DEBUG(SAT_DEBUG_RESULT, "arch change from %s to %s (%d):\n", id2str(pool, classes.elements[i + 2]), id2str(pool, classes.elements[i + 3]), cnt); diff --git a/src/transaction.c b/src/transaction.c index 8e8cebf..fe85ff9 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -1267,18 +1267,21 @@ dump_tes(struct orderdata *od) for (i = 1, te = od->tes + i; i < od->ntes; i++, te++) { Solvable *s = pool->solvables + te->p; - POOL_DEBUG(SAT_WARN, "TE %4d: %c%s\n", i, s->repo == pool->installed ? '-' : '+', solvable2str(pool, s)); + POOL_DEBUG(SAT_DEBUG_RESULT, "TE %4d: %c%s\n", i, s->repo == pool->installed ? '-' : '+', solvable2str(pool, s)); if (s->repo != pool->installed) { queue_empty(&obsq); transaction_all_obs_pkgs(od->trans, te->p, &obsq); for (j = 0; j < obsq.count; j++) - POOL_DEBUG(SAT_WARN, " -%s\n", solvid2str(pool, obsq.elements[j])); + POOL_DEBUG(SAT_DEBUG_RESULT, " -%s\n", solvid2str(pool, obsq.elements[j])); } for (j = te->edges; od->edgedata[j]; j += 2) { te2 = od->tes + od->edgedata[j]; - POOL_DEBUG(SAT_WARN, " --%x--> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p)); + if ((od->edgedata[j + 1] & TYPE_BROKEN) == 0) + POOL_DEBUG(SAT_DEBUG_RESULT, " --%x--> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p)); + else + POOL_DEBUG(SAT_DEBUG_RESULT, " ##%x##> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p)); } } } @@ -1608,6 +1611,7 @@ transaction_order(Transaction *trans, int flags) } POOL_DEBUG(SAT_DEBUG_STATS, "cycle edge creation took %d ms\n", sat_timems(now)); + dump_tes(&od); /* all edges are finally set up and there are no cycles, now the easy part. * Create an ordered transaction */ now = sat_timems(0); @@ -1941,7 +1945,7 @@ transaction_check_pkg(Transaction *trans, Id tepkg, Id pkg, Map *ins, Map *seen, } if (!good) { - POOL_DEBUG(SAT_WARN, " %c%s: nothing provides %s needed by %c%s\n", pool->solvables[tepkg].repo == pool->installed ? '-' : '+', solvid2str(pool, tepkg), dep2str(pool, req), s->repo == pool->installed ? '-' : '+', solvable2str(pool, s)); + POOL_DEBUG(SAT_DEBUG_RESULT, " %c%s: nothing provides %s needed by %c%s\n", pool->solvables[tepkg].repo == pool->installed ? '-' : '+', solvid2str(pool, tepkg), dep2str(pool, req), s->repo == pool->installed ? '-' : '+', solvable2str(pool, s)); } } } -- 2.7.4