The taggedfileindex patch. Speeds up database searches, but breaks fingerprint semantics. rh#103204 --- ./lib/rpmdb.c.orig 2010-03-25 14:43:41.000000000 +0000 +++ ./lib/rpmdb.c 2010-03-25 15:15:14.000000000 +0000 @@ -1122,6 +1122,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 @@ -1181,6 +1191,11 @@ static int rpmdbFindByFile(rpmdb db, con 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 @@ -2182,7 +2197,7 @@ void rpmdbSortIterator(rpmdbMatchIterato } } -static int rpmdbGrowIterator(rpmdbMatchIterator mi) +static int rpmdbGrowIterator(rpmdbMatchIterator mi, unsigned int tag) { DBC * dbcursor; DBT * key; @@ -2232,6 +2247,27 @@ static int rpmdbGrowIterator(rpmdbMatchI dbcursor = NULL; #endif + if (tag) { + int i, j; + /* prune the set against the tag */ + for (i = j = 0; i < set->count; i++) { + 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++; + } + set->count = j; + if (j == 0) { + set = dbiFreeIndexSet(set); + return DB_NOTFOUND; + } + } + if (mi->mi_set == NULL) { mi->mi_set = set; } else { @@ -2413,7 +2449,15 @@ int rpmdbExtendIterator(rpmdbMatchIterat { mi->mi_key.data = (void *) keyp; mi->mi_key.size = keylen ? keylen : strlen(keyp); - return rpmdbGrowIterator(mi); + return rpmdbGrowIterator(mi, 0); +} + +int rpmdbExtendIteratorDirtag(rpmdbMatchIterator mi, + const void * keyp, size_t keylen, const char *dirname) +{ + mi->mi_key.data = (void *) keyp; + mi->mi_key.size = keylen ? keylen : strlen(keyp); + return rpmdbGrowIterator(mi, dirname ? taghash(dirname) : 0); } /* @@ -2808,8 +2852,16 @@ int rpmdbAdd(rpmdb db, int iid, Header h if (hdrNum) { + struct rpmtd_s dn, di; + const char ** dirNames; + uint32_t * dirIndexes; dbiIndexItem rec = dbiIndexNewItem(hdrNum, 0); + headerGet(h, RPMTAG_DIRNAMES, &dn, HEADERGET_MINMEM); + headerGet(h, RPMTAG_DIRINDEXES, &di, HEADERGET_MINMEM); + dirNames = dn.data; + dirIndexes = di.data; + if (dbiTags.tags != NULL) for (dbix = 0; dbix < dbiTags.max; dbix++) { rpmTag rpmtag; @@ -2901,6 +2953,10 @@ int rpmdbAdd(rpmdb db, int iid, Header h */ i = rec->tagNum = rpmtdGetIndex(&tagdata); switch (rpmtag) { + case RPMTAG_BASENAMES: + if (i < 0x010000) + rec->tagNum |= taghash(dirNames[dirIndexes[i]]); + break; case RPMTAG_REQUIRENAME: { /* Filter out install prerequisites. */ rpm_flag_t *rflag = rpmtdNextUint32(&reqflags); @@ -2986,6 +3042,9 @@ cont: if (ret == 0) { headerSetInstance(h, hdrNum); } + + rpmtdFreeData(&dn); + rpmtdFreeData(&di); } exit: --- ./lib/rpmdb_internal.h.orig 2009-12-07 14:36:49.000000000 +0000 +++ ./lib/rpmdb_internal.h 2010-03-25 15:14:38.000000000 +0000 @@ -542,6 +542,9 @@ const char *rpmdbHome(rpmdb db); int rpmdbExtendIterator(rpmdbMatchIterator mi, const void * keyp, size_t keylen); +int rpmdbExtendIteratorDirtag(rpmdbMatchIterator mi, + const void * keyp, size_t keylen, const char *); + /** \ingroup rpmdb * sort the iterator by (recnum, filenum) * Return database iterator. --- ./lib/transaction.c.orig 2010-03-25 14:38:27.000000000 +0000 +++ ./lib/transaction.c 2010-03-25 15:14:38.000000000 +0000 @@ -848,9 +848,12 @@ rpmdbMatchIterator rpmFindBaseNamesInDB( rpmdbMatchIterator mi; int xx; const char * baseName; + const char * dirName; +#if 0 rpmStringSet baseNames = rpmStringSetCreate(fileCount, hashFunctionString, strcmp, NULL); +#endif mi = rpmdbInitIterator(rpmtsGetRdb(ts), RPMTAG_BASENAMES, NULL, 0); @@ -868,18 +871,25 @@ rpmdbMatchIterator rpmFindBaseNamesInDB( while (rpmfiNext(fi) >= 0) { size_t keylen; baseName = rpmfiBN(fi); + dirName = rpmfiDN(fi); +#if 0 if (rpmStringSetHasEntry(baseNames, baseName)) continue; +#endif keylen = strlen(baseName); if (keylen == 0) keylen++; /* XXX "/" fixup. */ - xx = rpmdbExtendIterator(mi, baseName, keylen); + xx = rpmdbExtendIteratorDirtag(mi, baseName, keylen, dirName); +#if 0 rpmStringSetAddEntry(baseNames, baseName); +#endif } } pi = rpmtsiFree(pi); +#if 0 rpmStringSetFree(baseNames); +#endif rpmdbSortIterator(mi); /* iterator is now sorted by (recnum, filenum) */