summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2013-04-10 15:47:18 +0200
committerMichael Schroeder <mls@suse.de>2013-04-10 15:47:18 +0200
commit261b19e87a1b5bdea9dfca450512ba2630ca0aa5 (patch)
tree69ee1e09b72d98c8f5d737cf7cdd78981236d593 /ext
parentb309e4bde9b3ab0bfb29d38a4b4a81bbd31dc3d5 (diff)
downloadlibsolv-261b19e87a1b5bdea9dfca450512ba2630ca0aa5.tar.gz
libsolv-261b19e87a1b5bdea9dfca450512ba2630ca0aa5.tar.bz2
libsolv-261b19e87a1b5bdea9dfca450512ba2630ca0aa5.zip
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.
Diffstat (limited to 'ext')
-rw-r--r--ext/pool_fileconflicts.c53
-rw-r--r--ext/repo_rpmdb.c35
-rw-r--r--ext/repo_rpmdb.h11
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);