From 261b19e87a1b5bdea9dfca450512ba2630ca0aa5 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Wed, 10 Apr 2013 15:47:18 +0200 Subject: [PATCH] improve iterate_filelist, it now calls the callback with a struct filelistinfo This makes the code extensible, plus we can now pass things like the diridx and the dirlen which can be used to speed up the fileconflict code. --- ext/pool_fileconflicts.c | 53 ++++++++++++++++++++++++++++++++++-------------- ext/repo_rpmdb.c | 35 +++++++++++++++++--------------- ext/repo_rpmdb.h | 11 +++++++++- 3 files changed, 67 insertions(+), 32 deletions(-) diff --git a/ext/pool_fileconflicts.c b/ext/pool_fileconflicts.c index 27e7ab8..37364ba 100644 --- a/ext/pool_fileconflicts.c +++ b/ext/pool_fileconflicts.c @@ -32,6 +32,9 @@ struct cbdata { Map idxmap; + unsigned int lastdiridx; /* last diridx we have seen */ + unsigned int lastdirhash; /* strhash of last dir we have seen */ + Id idx; /* index of package we're looking at */ Id hx; /* used in findfileconflicts2_cb, limit to files matching hx */ @@ -75,7 +78,7 @@ growhash(Hashtable map, Hashval *mapnp) } static void -finddirs_cb(void *cbdatav, const char *fn, int fmode, const char *md5) +finddirs_cb(void *cbdatav, const char *fn, struct filelistinfo *info) { struct cbdata *cbdata = cbdatav; Hashval h, hh; @@ -141,27 +144,32 @@ isindirmap(struct cbdata *cbdata, Id hx) } static void -findfileconflicts_cb(void *cbdatav, const char *fn, int fmode, const char *md5) +findfileconflicts_cb(void *cbdatav, const char *fn, struct filelistinfo *info) { struct cbdata *cbdata = cbdatav; - int isdir = S_ISDIR(fmode); - char *dp; + int isdir = S_ISDIR(info->mode); + const char *dp; Id idx, oidx; Id hx, qx; Hashval h, hh, dhx; idx = cbdata->idx; - dp = strrchr(fn, '/'); - if (!dp) + if (!info->dirlen) return; - dhx = strnhash(fn, dp + 1 - fn); + dp = fn + info->dirlen; + if (info->diridx != cbdata->lastdiridx) + { + cbdata->lastdiridx = info->diridx; + cbdata->lastdirhash = strnhash(fn, dp - fn); + } + dhx = cbdata->lastdirhash; #if 1 /* this mirrors the "if (!hx) hx = strlen(fn) + 1" in finddirs_cb */ - if (!isindirmap(cbdata, dhx ? dhx : dp + 1 - fn + 1)) + if (!isindirmap(cbdata, dhx ? dhx : dp - fn + 1)) return; #endif - hx = strhash_cont(dp + 1, dhx); + hx = strhash_cont(dp, dhx); if (!hx) hx = strlen(fn) + 1; @@ -221,19 +229,30 @@ addfilesspace(struct cbdata *cbdata, unsigned char *data, int len) } static void -findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5) +findfileconflicts2_cb(void *cbdatav, const char *fn, struct filelistinfo *info) { struct cbdata *cbdata = cbdatav; - Hashval hx = strhash(fn); + Hashval hx; + const char *dp; char md5padded[34]; + if (!info->dirlen) + return; + dp = fn + info->dirlen; + if (info->diridx != cbdata->lastdiridx) + { + cbdata->lastdiridx = info->diridx; + cbdata->lastdirhash = strnhash(fn, dp - fn); + } + hx = cbdata->lastdirhash; + hx = strhash_cont(dp, hx); if (!hx) hx = strlen(fn) + 1; if ((Id)hx != cbdata->hx) return; - strncpy(md5padded, md5, 32); + strncpy(md5padded, info->digest, 32); md5padded[32] = 0; - md5padded[33] = fmode >> 24; + md5padded[33] = info->color; /* printf("%d, hx %x -> %s %d %s\n", cbdata->idx, hx, fn, fmode, md5); */ queue_push(&cbdata->files, cbdata->filesspacen); addfilesspace(cbdata, (unsigned char *)md5padded, 34); @@ -341,8 +360,10 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo if (i == cutoff) cbdata.create = 0; handle = (*handle_cb)(pool, p, handle_cbdata); - if (handle) - rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, findfileconflicts_cb, &cbdata); + if (!handle) + continue; + cbdata.lastdiridx = -1; + rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, findfileconflicts_cb, &cbdata); } POOL_DEBUG(SOLV_DEBUG_STATS, "filemap size: %d, used %d\n", cbdata.cflmapn + 1, cbdata.cflmapused); @@ -398,6 +419,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo handle = (*handle_cb)(pool, p, handle_cbdata); if (!handle) continue; + cbdata.lastdiridx = -1; rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata); pend = cbdata.files.count; @@ -411,6 +433,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo handle = (*handle_cb)(pool, q, handle_cbdata); if (!handle) continue; + cbdata.lastdiridx = -1; rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata); for (ii = 0; ii < pend; ii++) for (jj = pend; jj < cbdata.files.count; jj++) diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index 727fc50..2e39a68 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -2056,14 +2056,11 @@ linkhash(const char *lt, char *hash) l = strlen(lt); while ((c = *str++) != 0) r += (r << 3) + c; - sprintf(hash, "%08x", r); - sprintf(hash + 8, "%08x", l); - sprintf(hash + 16, "%08x", 0); - sprintf(hash + 24, "%08x", 0); + sprintf(hash, "%08x%08x%08x%08x", r, l, 0, 0); } void -rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata) +rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, struct filelistinfo *), void *cbdata) { RpmHead *rpmhead = rpmhandle; char **bn; @@ -2080,7 +2077,8 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * int i, l1, l; char *space = 0; int spacen = 0; - char md5[33], *md5p = 0; + char md5[33]; + struct filelistinfo info; dn = headstringarray(rpmhead, TAG_DIRNAMES, &dcnt); if (!dn) @@ -2088,7 +2086,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * if ((flags & RPM_ITERATE_FILELIST_ONLYDIRS) != 0) { for (i = 0; i < dcnt; i++) - (*cb)(cbdata, dn[i], 0, (char *)0); + (*cb)(cbdata, dn[i], 0); solv_free(dn); return; } @@ -2159,6 +2157,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * } lastdir = dcnt; lastdirl = 0; + memset(&info, 0, sizeof(info)); for (i = 0; i < cnt; i++) { if (ff && (ff[i] & FILEFLAG_GHOST) != 0) @@ -2167,8 +2166,6 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * if (diidx >= dcnt) continue; l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]); - if (l1 == 0) - continue; l = l1 + strlen(bn[i]) + 1; if (l > spacen) { @@ -2182,12 +2179,16 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * lastdirl = l1; } strcpy(space + l1, bn[i]); + info.diridx = diidx; + info.dirlen = l1; + if (fm) + info.mode = fm[i]; if (md) { - md5p = md[i]; - if (S_ISLNK(fm[i])) + info.digest = md[i]; + if (fm && S_ISLNK(fm[i])) { - md5p = 0; + info.digest = 0; if (!lt) { lt = headstringarray(rpmhead, TAG_FILELINKTOS, &cnt2); @@ -2197,16 +2198,18 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char * if (lt) { linkhash(lt[i], md5); - md5p = md5; + info.digest = md5; } } - if (!md5p) + if (!info.digest) { sprintf(md5, "%08x%08x%08x%08x", (fm[i] >> 12) & 65535, 0, 0, 0); - md5p = md5; + info.digest = md5; } } - (*cb)(cbdata, space, co ? (fm[i] | co[i] << 24) : fm[i], md5p); + if (co) + info.color = co[i]; + (*cb)(cbdata, space, &info); } solv_free(space); solv_free(lt); diff --git a/ext/repo_rpmdb.h b/ext/repo_rpmdb.h index 79e35c7..e513417 100644 --- a/ext/repo_rpmdb.h +++ b/ext/repo_rpmdb.h @@ -44,6 +44,15 @@ extern void *rpm_byfp(void *rpmstate, FILE *fp, const char *name); extern void *rpm_byrpmh(void *rpmstate, struct headerToken_s *h); /* operations on a rpm header handle */ + +struct filelistinfo { + unsigned int dirlen; + unsigned int diridx; + const char *digest; + unsigned int mode; + unsigned int color; +}; + extern char *rpm_query(void *rpmhandle, Id what); -extern void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata); +extern void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, struct filelistinfo *), void *cbdata); extern Id repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags); -- 2.7.4