The taggedfileindex patch. Speeds up database searches, but breaks fingerprint semantics. rh#103204 Index: lib/rpmdb.c =================================================================== --- lib/rpmdb.c.orig +++ lib/rpmdb.c @@ -1107,6 +1107,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 @@ -1169,6 +1179,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 @@ -2172,7 +2187,7 @@ void rpmdbSortIterator(rpmdbMatchIterato } /* LCL: segfault */ -static int rpmdbGrowIterator(rpmdbMatchIterator mi) +static int rpmdbGrowIterator(rpmdbMatchIterator mi, unsigned int tag) { DBC * dbcursor; DBT * key; @@ -2222,6 +2237,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 { @@ -2403,7 +2439,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); } /* @@ -2798,8 +2842,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; @@ -2891,6 +2943,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); @@ -2976,6 +3032,9 @@ cont: if (ret == 0) { headerSetInstance(h, hdrNum); } + + rpmtdFreeData(&dn); + rpmtdFreeData(&di); } exit: Index: lib/rpmdb_internal.h =================================================================== --- lib/rpmdb_internal.h.orig +++ lib/rpmdb_internal.h @@ -540,6 +540,9 @@ unsigned int dbiIndexRecordFileNumber(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. Index: lib/transaction.c =================================================================== --- lib/transaction.c.orig +++ lib/transaction.c @@ -609,9 +609,12 @@ rpmdbMatchIterator rpmFindBaseNamesInDB( rpmdbMatchIterator mi; int i, 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); @@ -629,18 +632,25 @@ rpmdbMatchIterator rpmFindBaseNamesInDB( while ((i = 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) */