File taggedfileindex.diff of Package rpm

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
@@ -1215,6 +1215,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
@@ -1294,6 +1304,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
@@ -2411,7 +2426,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 @*/
 {
@@ -2459,10 +2474,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);
@@ -3240,6 +3270,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:
@@ -3414,6 +3449,8 @@ if (key->size == 0) key->size++;	/* XXX
     }
 
 exit:
+    dirIndexes = hfd(dirIndexes, dit);
+    dirNames = hfd(dirNames, dnt);
     (void) unblockSignals(db, &signalMask);
 
     return ret;
@@ -3495,7 +3532,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));
 
     }
 
openSUSE Build Service is sponsored by