#include <stdio.h>
#include <sys/stat.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <unistd.h>
#include "pool.h"
dirl--;
if (!dirl)
return diroff;
+
/* find dirname */
for (i = dirl - 1; i > 0; i--)
if (cbdata->filesspace[diroff + i] == '/')
printf("stat()ing %s\n", cbdata->canonspace);
#endif
cbdata->statsmade++;
- if (lstat(cbdata->canonspace, &stb))
- return diroff; /* hmm */
- if (!S_ISLNK(stb.st_mode))
+ if (lstat(cbdata->canonspace, &stb) != 0 || !S_ISLNK(stb.st_mode))
{
- /* not a symlink, have new canon entry */
+ /* not a symlink or stat failed, have new canon entry */
diroff = addfilesspace(cbdata, l + dirl - i + 2);
strcpy((char *)cbdata->filesspace + diroff, cbdata->canonspace + cbdata->rootdirl);
l += dirl - i;
strncpy(md5padded, info->digest, 32);
md5padded[32] = 0;
md5padded[33] = info->color;
- /* printf("%d, hx %x -> %s %d %s\n", cbdata->idx, hx, fn, info->mode, info->digest); */
+ /* printf("%d, hx %x -> %s %d %s %d\n", cbdata->idx, hx, fn, info->mode, info->digest, info->color); */
off = addfilesspace(cbdata, strlen(fn) + (34 + 1));
memcpy(cbdata->filesspace + off, (unsigned char *)md5padded, 34);
strcpy((char *)cbdata->filesspace + off + 34, fn);
dataiterator_free(&di);
}
-/* before calling the expensive findfileconflicts_basename_cb we check if any of
- * the basenames match. This only makes sense when cbdata->create is off.
+/* before calling the expensive findfileconflicts_cb we check if any of
+ * the files match. This only makes sense when cbdata->create is off.
*/
static int
precheck_solvable_files(struct cbdata *cbdata, Pool *pool, Id p)
Id hx, qx;
Hashval h, hh;
int found = 0;
+ int aliases = cbdata->aliases;
+ unsigned int lastdirid = -1;
+ Hashval lastdirhash = 0;
+ int lastdirlen = 0;
+ int checkthisdir = 0;
+ Repodata *lastrepodata = 0;
dataiterator_init(&di, pool, 0, p, SOLVABLE_FILELIST, 0, SEARCH_COMPLETE_FILELIST);
while (dataiterator_step(&di))
{
- hx = strhash(di.kv.str);
- if (!hx)
- hx = strlen(di.kv.str) + 1;
+ if (aliases)
+ {
+ /* hash just the basename */
+ hx = strhash(di.kv.str);
+ if (!hx)
+ hx = strlen(di.kv.str) + 1;
+ }
+ else
+ {
+ /* hash the full path */
+ if (di.data != lastrepodata || di.kv.id != lastdirid)
+ {
+ const char *dir;
+ lastrepodata = di.data;
+ lastdirid = di.kv.id;
+ dir = repodata_dir2str(lastrepodata, lastdirid, "");
+ lastdirlen = strlen(dir);
+ lastdirhash = strhash(dir);
+ checkthisdir = isindirmap(cbdata, lastdirhash ? lastdirhash : lastdirlen + 1);
+ }
+ if (!checkthisdir)
+ continue;
+ hx = strhash_cont(di.kv.str, lastdirhash);
+ if (!hx)
+ hx = lastdirlen + strlen(di.kv.str) + 1;
+ }
h = hx & cbdata->cflmapn;
hh = HASHCHAIN_START;
for (;;)
void *handle;
Repo *installed = pool->installed;
Id p;
- int obsoleteusescolors = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESCOLORS);
+ int usefilecolors;
+ int hdrfetches;
queue_empty(conflicts);
if (!pkgs->count)
return 0;
now = start = solv_timems(0);
+ /* Hmm, should we have a different flag for this? */
+ usefilecolors = pool_get_flag(pool, POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS);
POOL_DEBUG(SOLV_DEBUG_STATS, "searching for file conflicts\n");
- POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d\n", pkgs->count, cutoff);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d, usefilecolors %d\n", pkgs->count, cutoff, usefilecolors);
memset(&cbdata, 0, sizeof(cbdata));
cbdata.aliases = flags & FINDFILECONFLICTS_CHECK_DIRALIASING;
/* first pass: scan dirs */
if (!cbdata.aliases)
{
+ hdrfetches = 0;
cflmapn = (cutoff + 3) * 64;
while ((cflmapn & (cflmapn - 1)) != 0)
cflmapn = cflmapn & (cflmapn - 1);
idxmapset = 0;
for (i = 0; i < pkgs->count; i++)
{
- p = pkgs->elements[i];
- cbdata.idx = i;
if (i == cutoff)
cbdata.create = 0;
+ cbdata.idx = i;
+ p = pkgs->elements[i];
if ((flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed)
{
if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed)
handle = (*handle_cb)(pool, p, handle_cbdata);
if (!handle)
continue;
+ hdrfetches++;
rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata);
if (MAPTST(&cbdata.idxmap, i))
idxmapset++;
}
POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap size: %d, used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused);
POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap creation took %d ms\n", solv_timems(now));
POOL_DEBUG(SOLV_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count);
}
cbdata.cflmap = solv_calloc(cflmapn, 2 * sizeof(Id));
cbdata.cflmapn = cflmapn - 1; /* make it a mask */
cbdata.create = 1;
+ hdrfetches = 0;
for (i = 0; i < pkgs->count; i++)
{
+ if (i == cutoff)
+ cbdata.create = 0;
if (!cbdata.aliases && !MAPTST(&cbdata.idxmap, i))
continue;
- p = pkgs->elements[i];
cbdata.idx = i;
- if (i == cutoff)
- cbdata.create = 0;
- if (cbdata.aliases && !cbdata.create && FINDFILECONFLICTS_USE_SOLVABLEFILELIST)
+ p = pkgs->elements[i];
+ if (!cbdata.create && (flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed)
{
if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed)
if (!precheck_solvable_files(&cbdata, pool, p))
handle = (*handle_cb)(pool, p, handle_cbdata);
if (!handle)
continue;
+ hdrfetches++;
cbdata.lastdiridx = -1;
rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, cbdata.aliases ? findfileconflicts_basename_cb : findfileconflicts_cb, &cbdata);
}
POOL_DEBUG(SOLV_DEBUG_STATS, "filemap size: %d, used %d\n", cbdata.cflmapn + 1, cbdata.cflmapused);
POOL_DEBUG(SOLV_DEBUG_STATS, "filemap memory usage: %d K\n", (cbdata.cflmapn + 1) * 2 * (int)sizeof(Id) / 1024);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
POOL_DEBUG(SOLV_DEBUG_STATS, "filemap creation took %d ms\n", solv_timems(now));
POOL_DEBUG(SOLV_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count);
queue_free(&cbdata.lookat_dir);
cbdata.statmapn = cflmapn - 1; /* make it a mask */
}
cbdata.create = 0;
+ hdrfetches = 0;
for (i = 0; i < pkgs->count; i++)
{
if (!MAPTST(&cbdata.idxmap, i))
handle = (*handle_cb)(pool, p, handle_cbdata);
if (!handle)
continue;
+ hdrfetches++;
cbdata.lastdiridx = -1;
rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, findfileconflicts_alias_cb, &cbdata);
}
POOL_DEBUG(SOLV_DEBUG_STATS, "normap size: %d, used %d\n", cbdata.normapn + 1, cbdata.normapused);
POOL_DEBUG(SOLV_DEBUG_STATS, "normap memory usage: %d K\n", (cbdata.normapn + 1) * 2 * (int)sizeof(Id) / 1024);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
POOL_DEBUG(SOLV_DEBUG_STATS, "stats made: %d\n", cbdata.statsmade);
if (cbdata.usestat)
{
cbdata.cflmapn = 0;
cbdata.cflmapused = 0;
- now = solv_timems(0);
-
map_free(&cbdata.idxmap);
/* sort and unify/prune */
+ now = solv_timems(0);
POOL_DEBUG(SOLV_DEBUG_STATS, "raw candidates: %d, pruning\n", cbdata.lookat.count / 4);
solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool);
for (i = j = 0; i < cbdata.lookat.count; )
}
queue_truncate(&cbdata.lookat, j);
POOL_DEBUG(SOLV_DEBUG_STATS, "candidates now: %d\n", cbdata.lookat.count / 4);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "pruning took %d ms\n", solv_timems(now));
/* third pass: collect file info for all files that match a hx */
+ now = solv_timems(0);
solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_idx_cmp, pool);
queue_init(&cbdata.files);
+ hdrfetches = 0;
for (i = 0; i < cbdata.lookat.count; i += 4)
{
Id idx = cbdata.lookat.elements[i + 1];
int iterflags = RPM_ITERATE_FILELIST_WITHMD5 | RPM_ITERATE_FILELIST_NOGHOSTS;
- if (obsoleteusescolors)
+ if (usefilecolors)
iterflags |= RPM_ITERATE_FILELIST_WITHCOL;
p = pkgs->elements[idx];
handle = (*handle_cb)(pool, p, handle_cbdata);
+ if (handle)
+ hdrfetches++;
for (;; i += 4)
{
int fstart = cbdata.files.count;
break;
}
}
+ POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
+ POOL_DEBUG(SOLV_DEBUG_STATS, "file info fetching took %d ms\n", solv_timems(now));
cbdata.normap = solv_free(cbdata.normap);
cbdata.normapn = 0;
/* forth pass: for each hx we have, compare all matching files against all other matching files */
+ now = solv_timems(0);
solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool);
for (i = 0; i < cbdata.lookat.count - 4; i += 4)
{
char *fsj = (char *)cbdata.filesspace + cbdata.files.elements[jj];
if (cbdata.aliases)
{
- /* compare just the basenames, the dirs match */
+ /* compare just the basenames, the dirs match because of the dirid */
char *bsi = strrchr(fsi + 34, '/');
char *bsj = strrchr(fsj + 34, '/');
- if ((!bsi || !bsj) && bsi != bsj)
+ if (!bsi || !bsj)
continue;
if (strcmp(bsi, bsj))
- continue; /* different file names */
+ continue; /* different base names */
}
else
{
continue; /* different file names */
}
if (!strcmp(fsi, fsj))
- continue; /* md5 sum matches */
- if (obsoleteusescolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
+ continue; /* file digests match, no conflict */
+ if (usefilecolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
continue; /* colors do not conflict */
queue_push(conflicts, pool_str2id(pool, fsi + 34, 1));
queue_push(conflicts, pkgs->elements[pidx]);
POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file conflicts\n", conflicts->count / 6);
POOL_DEBUG(SOLV_DEBUG_STATS, "file conflict detection took %d ms\n", solv_timems(start));
- return conflicts->count;
+ return conflicts->count / 6;
}