The taggedfileindex patch. Speeds up database searches, but breaks fingerprint semantics. Needs findfplistexclude.diff. rh#103204 Index: rpmdb/rpmdb.c =================================================================== --- rpmdb/rpmdb.c.orig +++ rpmdb/rpmdb.c @@ -1223,6 +1223,16 @@ int rpmdbVerify(const char * prefix) return rc; } +static inline unsigned int taghash(const char *s) +{ + int c; + unsigned int r = 0; + while ((c = *(const unsigned char *)s++) != 0) + if (c != '/') + r += (r << 3) + c; + return ((r & 0x7fff) | 0x8000) << 16; +} + /** * Find file matches in database. * @param db rpm database @@ -1302,6 +1312,11 @@ if (key->size == 0) key->size++; /* XXX if (rc == 0) (void) dbt2set(dbi, data, &allMatches); + /* strip off directory tags */ + if (allMatches != NULL) + for (i = 0; i < allMatches->count; i++) + if (allMatches->recs[i].tagNum & 0x80000000) + allMatches->recs[i].tagNum &= 0x0000ffff; xx = dbiCclose(dbi, dbcursor, 0); dbcursor = NULL; } else @@ -2408,7 +2423,7 @@ static void rpmdbSortIterator(/*@null@*/ } /*@-bounds@*/ /* LCL: segfault */ -static int rpmdbGrowIterator(/*@null@*/ rpmdbMatchIterator mi, int fpNum, unsigned int exclude) +static int rpmdbGrowIterator(/*@null@*/ rpmdbMatchIterator mi, int fpNum, unsigned int exclude, unsigned int tag) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies mi, rpmGlobalMacroContext, fileSystem, internalState @*/ { @@ -2456,10 +2471,16 @@ static int rpmdbGrowIterator(/*@null@*/ set = NULL; (void) dbt2set(dbi, data, &set); - /* prune the set against exclude */ + /* prune the set against exclude and tag */ for (i = j = 0; i < set->count; i++) { if (exclude && set->recs[i].hdrNum == exclude) continue; + if (set->recs[i].tagNum & 0x80000000) { + /* tagged entry */ + if ((set->recs[i].tagNum & 0xffff0000) != tag) + continue; + set->recs[i].tagNum &= 0x0000ffff; + } if (i != j) set->recs[j] = set->recs[i]; j++; @@ -2987,7 +3008,9 @@ DBT * data = alloca(sizeof(*data)); HFD_t hfd = headerFreeData; sigset_t signalMask; const char ** baseNames; - rpmTagType bnt; + const char ** dirNames; + int_32 * dirIndexes, *dirs; + rpmTagType bnt, dit, dnt; int count = 0; dbiIndex dbi; int dbix; @@ -3027,6 +3050,13 @@ memset(data, 0, sizeof(*data)); */ xx = hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &count); + xx = hge(h, RPMTAG_DIRINDEXES, &dit, (void **) &dirIndexes, NULL); + xx = hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL); + + /* save dirIndexes, because expandFilelist may free it */ + dirs = alloca(count * sizeof(*dirs)); + for (xx = 0; xx < count; xx++) + dirs[xx] = dirIndexes[xx]; if (_noDirTokens) expandFilelist(h); @@ -3243,6 +3273,11 @@ data->size = 0; */ rec->tagNum = i; switch (dbi->dbi_rpmtag) { + case RPMTAG_BASENAMES: + /* tag index entry with directory hash */ + if (i < 0x010000) + rec->tagNum |= taghash(dirNames[dirs[i]]); + /*@switchbreak@*/ break; case RPMTAG_PUBKEYS: /*@switchbreak@*/ break; case RPMTAG_FILEMD5S: @@ -3417,6 +3452,8 @@ if (key->size == 0) key->size++; /* XXX } exit: + dirIndexes = hfd(dirIndexes, dit); + dirNames = hfd(dirNames, dnt); (void) unblockSignals(db, &signalMask); return ret; @@ -3505,7 +3542,7 @@ if (key->size == 0) key->size++; /* XXX if (!exclude && skipDir(fpList[i].entry->dirName)) continue; - xx = rpmdbGrowIterator(mi, i, exclude); + xx = rpmdbGrowIterator(mi, i, exclude, taghash(fpList[i].entry->dirName)); }