File taggedfileindex.diff of Package rpm

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) */