improve iterate_filelist, it now calls the callback with a struct filelistinfo
authorMichael Schroeder <mls@suse.de>
Wed, 10 Apr 2013 13:47:18 +0000 (15:47 +0200)
committerMichael Schroeder <mls@suse.de>
Wed, 10 Apr 2013 13:47:18 +0000 (15:47 +0200)
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
ext/repo_rpmdb.c
ext/repo_rpmdb.h

index 27e7ab8..37364ba 100644 (file)
@@ -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++)
index 727fc50..2e39a68 100644 (file)
@@ -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);
index 79e35c7..e513417 100644 (file)
@@ -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);