From: Michael Schroeder Date: Mon, 22 Jun 2009 09:25:45 +0000 (+0200) Subject: - add rpm_installedrpmdbids X-Git-Tag: BASE-SuSE-Code-12_1-Branch~242 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=87bfd053490e20b82f0685a55efa30f148554c63;p=thirdparty%2Flibsolv.git - add rpm_installedrpmdbids - fix memleaks --- diff --git a/tools/pool_fileconflicts.c b/tools/pool_fileconflicts.c index e14d5c4b..1858df4c 100644 --- a/tools/pool_fileconflicts.c +++ b/tools/pool_fileconflicts.c @@ -21,6 +21,9 @@ struct cbdata { Hashval *dirmap; Hashmask dirmapn; unsigned int dirmapused; + int dirconflicts; + + Map idxmap; Hashval idx; unsigned int hx; @@ -64,7 +67,7 @@ doublehash(Hashval *map, Hashmask *mapnp) } static void -finddirs_cb(void *cbdatav, char *fn, int fmode, char *md5) +finddirs_cb(void *cbdatav, const char *fn, int fmode, const char *md5) { struct cbdata *cbdata = cbdatav; Hashmask h, hh, hx, qx; @@ -99,7 +102,12 @@ finddirs_cb(void *cbdatav, char *fn, int fmode, char *md5) if (cbdata->dirmap[2 * h + 1] == idx) return; /* found a conflict, this dir is used in multiple packages */ - cbdata->dirmap[2 * h + 1] = -1; + if (cbdata->dirmap[2 * h + 1] != -1) + { + cbdata->dirmap[2 * h + 1] = -1; + cbdata->dirconflicts++; + } + MAPSET(&cbdata->idxmap, idx); } static inline int @@ -121,7 +129,7 @@ isindirmap(struct cbdata *cbdata, Hashmask hx) } static void -findfileconflicts_cb(void *cbdatav, char *fn, int fmode, char *md5) +findfileconflicts_cb(void *cbdatav, const char *fn, int fmode, const char *md5) { struct cbdata *cbdata = cbdatav; int isdir = S_ISDIR(fmode); @@ -201,7 +209,7 @@ addfilesspace(struct cbdata *cbdata, unsigned char *data, int len) } static void -findfileconflicts2_cb(void *cbdatav, char *fn, int fmode, char *md5) +findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5) { struct cbdata *cbdata = cbdatav; unsigned int hx = strhash(fn); @@ -250,11 +258,12 @@ static int conflicts_cmp(const void *ap, const void *bp, void *dp) int pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata) { - int i, j, cflmapn; + int i, j, cflmapn, idxmapset; unsigned int hx; struct cbdata cbdata; unsigned int now, start; void *handle; + Id p; queue_empty(conflicts); if (!pkgs->count) @@ -269,6 +278,8 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo queue_init(&cbdata.lookat); queue_init(&cbdata.lookat_dir); queue_init(&cbdata.files); + map_init(&cbdata.idxmap, pkgs->count); + if (cutoff <= 0) cutoff = pkgs->count; @@ -282,20 +293,24 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo cbdata.dirmap = sat_calloc(cflmapn, 2 * sizeof(Id)); cbdata.dirmapn = cflmapn - 1; /* make it a mask */ cbdata.create = 1; + idxmapset = 0; for (i = 0; i < pkgs->count; i++) { - Id p = pkgs->elements[i]; + p = pkgs->elements[i]; cbdata.idx = i; if (i == cutoff) cbdata.create = 0; handle = (*handle_cb)(pool, p, handle_cbdata); if (handle) rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata); + if (MAPTST(&cbdata.idxmap, i)) + idxmapset++; } POOL_DEBUG(SAT_DEBUG_STATS, "dirmap size: %d used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused); POOL_DEBUG(SAT_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024); POOL_DEBUG(SAT_DEBUG_STATS, "dirmap creation took %d ms\n", sat_timems(now)); + POOL_DEBUG(SAT_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count); /* second pass: scan files */ now = sat_timems(0); @@ -307,7 +322,9 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo cbdata.create = 1; for (i = 0; i < pkgs->count; i++) { - Id p = pkgs->elements[i]; + if (!MAPTST(&cbdata.idxmap, i)) + continue; + p = pkgs->elements[i]; cbdata.idx = i; if (i == cutoff) cbdata.create = 0; @@ -326,6 +343,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo cbdata.cflmap = sat_free(cbdata.cflmap); cbdata.cflmapn = 0; cbdata.cflmapused = 0; + map_free(&cbdata.idxmap); now = sat_timems(0); POOL_DEBUG(SAT_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count); @@ -348,8 +366,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo { int pend, ii, jj; int pidx = cbdata.lookat.elements[i + 1]; - Id p = pkgs->elements[pidx]; - + p = pkgs->elements[pidx]; hx = cbdata.lookat.elements[i]; if (cbdata.lookat.elements[i + 2] != hx) continue; /* no package left */ @@ -393,6 +410,8 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo } cbdata.filesspace = sat_free(cbdata.filesspace); cbdata.filesspacen = 0; + queue_free(&cbdata.lookat); + queue_free(&cbdata.files); POOL_DEBUG(SAT_DEBUG_STATS, "candidate check took %d ms\n", sat_timems(now)); if (conflicts->count > 5) sat_sort(conflicts->elements, conflicts->count / 5, 5 * sizeof(Id), conflicts_cmp, pool); diff --git a/tools/repo_rpmdb.c b/tools/repo_rpmdb.c index ddb6b68e..826fa13f 100644 --- a/tools/repo_rpmdb.c +++ b/tools/repo_rpmdb.c @@ -32,6 +32,7 @@ #include "repo.h" #include "hash.h" #include "util.h" +#include "queue.h" #include "repo_rpmdb.h" #define RPMDB_COOKIE_VERSION 2 @@ -977,6 +978,8 @@ copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) return ido; } +#define COPYDIR_DIRCACHE_SIZE 512 + static Id copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache); static inline Id @@ -1201,7 +1204,7 @@ count_headers(const char *rootdir, DB_ENV *dbenv) } if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) { - perror("db->open var/lib/rpm/Name"); + perror("db->open Name index"); exit(1); } if (db->get_byteswapped(db, &byteswapped)) @@ -1287,11 +1290,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) perror("dbenv open"); exit(1); } - if (db_create(&db, dbenv, 0)) - { - perror("db_create"); - exit(1); - } /* XXX: should get ro lock of Packages database! */ snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir); @@ -1311,9 +1309,14 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) if ((flags & RPMDB_REPORT_PROGRESS) != 0) count = count_headers(rootdir, dbenv); + if (db_create(&db, dbenv, 0)) + { + perror("db_create"); + exit(1); + } if (db->open(db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664)) { - perror("db->open var/lib/rpm/Packages"); + perror("db->open Packages index"); exit(1); } if (db->get_byteswapped(db, &byteswapped)) @@ -1425,12 +1428,17 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) } else { - Id dircache[512]; + Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */ memset(dircache, 0, sizeof(dircache)); + if (db_create(&db, dbenv, 0)) + { + perror("db_create"); + exit(1); + } if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) { - perror("db->open var/lib/rpm/Name"); + perror("db->open Name index"); exit(1); } if (db->get_byteswapped(db, &byteswapped)) @@ -1804,14 +1812,16 @@ linkhash(const char *lt, char *hash) } void -rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, char *), void *cbdata) +rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata) { RpmHead *rpmhead = rpmhandle; char **bn; char **dn; char **md = 0; char **lt = 0; - unsigned int *di; + unsigned int *di, diidx; + unsigned int lastdir; + int lastdirl; unsigned int *fm; int cnt, dcnt, cnt2; int i, l1, l; @@ -1865,11 +1875,14 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, return; } } + lastdir = dcnt; + lastdirl = 0; for (i = 0; i < cnt; i++) { - if (di[i] >= dcnt) + diidx = di[i]; + if (diidx >= dcnt) continue; - l1 = strlen(dn[di[i]]); + l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]); if (l1 == 0) continue; l = l1 + strlen(bn[i]) + 1; @@ -1878,7 +1891,12 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, spacen = l + 16; space = sat_realloc(space, spacen); } - strcpy(space, dn[di[i]]); + if (lastdir != diidx) + { + strcpy(space, dn[diidx]); + lastdir = diidx; + lastdirl = l1; + } strcpy(space + l1, bn[i]); if (md) { @@ -1903,6 +1921,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, } (*cb)(cbdata, space, fm[i], md5p); } + sat_free(space); sat_free(lt); sat_free(md); sat_free(fm); @@ -1922,6 +1941,99 @@ struct rpm_by_state { int byteswapped; }; +int +rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq) +{ + char dbpath[PATH_MAX]; + DB_ENV *dbenv = 0; + DB *db = 0; + DBC *dbc = 0; + int byteswapped; + DBT dbkey; + DBT dbdata; + Id rpmdbid; + unsigned char *dp; + int dl, cnt; + + if (rpmdbidq) + queue_empty(rpmdbidq); + cnt = 0; + + if (db_env_create(&dbenv, 0)) + { + perror("db_env_create"); + return 0; + } + snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir ? rootdir : ""); +#ifdef FEDORA + if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0)) +#else + if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0)) +#endif + { + perror("dbenv open"); + dbenv->close(dbenv, 0); + return 0; + } + if (db_create(&db, dbenv, 0)) + { + perror("db_create"); + dbenv->close(dbenv, 0); + return 0; + } + if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664)) + { + perror("db->open Name index"); + db->close(db, 0); + dbenv->close(dbenv, 0); + return 0; + } + if (db->get_byteswapped(db, &byteswapped)) + { + perror("db->get_byteswapped"); + db->close(db, 0); + dbenv->close(dbenv, 0); + return 0; + } + if (db->cursor(db, NULL, &dbc, 0)) + { + perror("db->cursor"); + db->close(db, 0); + dbenv->close(dbenv, 0); + return 0; + } + memset(&dbkey, 0, sizeof(dbkey)); + memset(&dbdata, 0, sizeof(dbdata)); + while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0) + { + if (dbkey.size == 10 && !memcmp(dbkey.data, "gpg-pubkey", 10)) + continue; + dl = dbdata.size; + dp = dbdata.data; + while(dl >= 8) + { + if (byteswapped) + { + ((char *)&rpmdbid)[0] = dp[3]; + ((char *)&rpmdbid)[1] = dp[2]; + ((char *)&rpmdbid)[2] = dp[1]; + ((char *)&rpmdbid)[3] = dp[0]; + } + else + memcpy((char *)&rpmdbid, dp, 4); + if (rpmdbidq) + queue_push(rpmdbidq, rpmdbid); + cnt++; + dp += 8; + dl -= 8; + } + } + dbc->c_close(dbc); + db->close(db, 0); + dbenv->close(dbenv, 0); + return cnt; +} + void * rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep) { diff --git a/tools/repo_rpmdb.h b/tools/repo_rpmdb.h index 6c907c7d..3e80302f 100644 --- a/tools/repo_rpmdb.h +++ b/tools/repo_rpmdb.h @@ -5,6 +5,8 @@ * for further information */ +#include "queue.h" + 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); @@ -15,4 +17,5 @@ extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags); void *rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep); void *rpm_byfp(FILE *fp, const char *name, void **statep); -void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, char *), void *cbdata); +void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata); +int rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq);