Sophie

Sophie

distrib > Mandriva > 2009.0 > i586 > by-pkgid > 07e56ec36f5b6db53acae40086fcf8ad > files > 24

rpm-4.4.2.3-20mnb2.src.rpm

without this patch, "rpm -e" or "rpm -U" will need to stat(2) every dirnames
of files from the package (eg COPYING) in the db. It will also need to access
all the packages in "Packages" db that have the same basename.
This is quite costly when not in cache 
(eg on a test here: >300 stats, and so 3 seconds after a "echo 3 > /proc/sys/vm/drop_caches")
this breaks urpmi test case test_rpm_i_fail('gd') in superuser--file-conflicts.t,
but this is bad design anyway


- Dirnames db can't be used together with Basenames to construct the full
filename since dirindexes are only available in Packages db. So Dirnames db is
only used to know if the directory exists in the package. It's quite effective
anyway since for cases like basename "COPYING" or "README", the dirname is
specific to one package.

- rpmdbGet_dbiIndexSet() is created out of rpmdbGrowIterator()

- dbiIntersectSet() is mostly a copy/paste of dbiPruneSet()

- set_mi_string_key() is a small helper function to keep code clean

diff -p -up rpm-4.4.2.3/rpmdb/rpmdb.c.speedup rpm-4.4.2.3/rpmdb/rpmdb.c
--- rpm-4.4.2.3/rpmdb/rpmdb.c.speedup	2008-06-23 15:25:33.000000000 +0200
+++ rpm-4.4.2.3/rpmdb/rpmdb.c	2008-07-04 14:29:00.000000000 +0200
@@ -624,6 +624,43 @@ assert(set->count > 0);
     return (numCopied == num);
 }
 
+
+/**
+ * Remove element(s) not in set of index database items.
+ * @param set		set of index database items
+ * @param set2		set of items that we must have
+ * @param sorted	set is already sorted?
+ * @return		0 success, 1 failure (no items found)
+ */
+static int dbiIntersectSet(dbiIndexSet set, dbiIndexSet set2, int sorted)
+	/*@modifies set, recs @*/
+{
+    int from;
+    int to = 0;
+    int num = set->count;
+    int numCopied = 0;
+
+     void * recs = set2->recs;
+     int nrecs = set2->count;
+     size_t recsize = sizeof(*set2->recs);
+
+assert(set->count > 0);
+    if (nrecs > 1 && !sorted)
+	qsort(recs, nrecs, recsize, hdrNumCmp);
+
+    for (from = 0; from < num; from++) {
+	if (!bsearch(&set->recs[from], recs, nrecs, recsize, hdrNumCmp)) {
+	    set->count--;
+	    continue;
+	}
+	if (from != to)
+	    set->recs[to] = set->recs[from]; /* structure assignment */
+	to++;
+	numCopied++;
+    }
+    return (numCopied == num);
+}
+
 /* XXX transaction.c */
 unsigned int dbiIndexSetCount(dbiIndexSet set) {
     return set->count;
@@ -2390,18 +2427,16 @@ static void rpmdbSortIterator(/*@null@*/
 }
 
 /*@-bounds@*/ /* LCL: segfault */
-static int rpmdbGrowIterator(/*@null@*/ rpmdbMatchIterator mi, int fpNum)
+static int rpmdbGet_dbiIndexSet(/*@null@*/ rpmdbMatchIterator mi, dbiIndexSet *set)
 	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
-	/*@modifies mi, rpmGlobalMacroContext, fileSystem, internalState @*/
+	/*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
 {
     DBC * dbcursor;
     DBT * key;
     DBT * data;
     dbiIndex dbi = NULL;
-    dbiIndexSet set;
     int rc;
     int xx;
-    int i;
 
     if (mi == NULL)
 	return 1;
@@ -2435,16 +2470,26 @@ static int rpmdbGrowIterator(/*@null@*/ 
 	return rc;
     }
 
-    set = NULL;
-    (void) dbt2set(dbi, data, &set);
-    for (i = 0; i < set->count; i++)
-	set->recs[i].fpNum = fpNum;
+    *set = NULL;
+    (void) dbt2set(dbi, data, set);
 
 #ifdef	SQLITE_HACK
     xx = dbiCclose(dbi, dbcursor, 0);
     dbcursor = NULL;
 #endif
 
+    return rc;
+}
+
+/*@-bounds@*/ /* LCL: segfault */
+static void rpmdbGrowIterator(/*@null@*/ rpmdbMatchIterator mi, dbiIndexSet set, int fpNum)
+	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
+	/*@modifies mi, rpmGlobalMacroContext, fileSystem, internalState @*/
+{
+    int i;
+    for (i = 0; i < set->count; i++)
+	set->recs[i].fpNum = fpNum;
+
 /*@-branchstate@*/
     if (mi->mi_set == NULL) {
 	mi->mi_set = set;
@@ -2460,8 +2505,6 @@ fprintf(stderr, "+++ %d = %d + %d\t\"%s\
 	set = dbiFreeIndexSet(set);
     }
 /*@=branchstate@*/
-
-    return rc;
 }
 /*@=bounds@*/
 
@@ -3379,16 +3422,27 @@ exit:
     return ret;
 }
 
+/* XXX "/" fixup. */
+static int at_least_one(int n)
+{
+     return n == 0 ? 1 : n;
+}
+
+static void set_mi_string_key(rpmdbMatchIterator mi, char *key)
+{
+     mi->mi_key.data = (void *) key;
+     mi->mi_key.size = at_least_one(strlen(key));
+}
+
 /* XXX transaction.c */
 /*@-compmempass@*/
-int rpmdbFindFpList(rpmdb db, fingerPrint * fpList, dbiIndexSet * matchList, 
+int rpmdbFindList(rpmdb db, const char ** search_dirNames,
+		    const char ** search_baseNames, const uint_32 * search_dirIndexes, dbiIndexSet * matchList, 
 		    int numItems)
 {
-DBT * key;
-DBT * data;
     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
     HFD_t hfd = headerFreeData;
-    rpmdbMatchIterator mi;
+    rpmdbMatchIterator mi, mi_dirs = NULL;
     fingerPrintCache fpc;
     Header h;
     int i, xx;
@@ -3399,26 +3453,50 @@ DBT * data;
     if (mi == NULL)	/* XXX should  never happen */
 	return 1;
 
-key = &mi->mi_key;
-data = &mi->mi_data;
-
-    /* Gather all installed headers with matching basename's. */
     for (i = 0; i < numItems; i++) {
 
 /*@-boundswrite@*/
 	matchList[i] = xcalloc(1, sizeof(*(matchList[i])));
 /*@=boundswrite@*/
+    }
 
-/*@-boundsread -dependenttrans@*/
-key->data = (void *) fpList[i].baseName;
-/*@=boundsread =dependenttrans@*/
-key->size = strlen((char *)key->data);
-if (key->size == 0) key->size++;	/* XXX "/" fixup. */
+    /* Gather all installed headers with matching basename's. */
+    for (i = 0; i < numItems; i++) {
+	 set_mi_string_key(mi, (char *) search_baseNames[i]);
+
+	 dbiIndexSet set;
+	 if (rpmdbGet_dbiIndexSet(mi, &set) != 0) 
+	      continue; /* no match */
+
+	 if (set->count > 0) {
+	      if (!mi_dirs) mi_dirs = rpmdbInitIterator(db, RPMTAG_DIRNAMES, NULL, 0);
+
+	      if (mi_dirs == NULL) {	/* XXX should  never happen */
+		   set = dbiFreeIndexSet(set);
+		   return 1;
+	      }
 
-	xx = rpmdbGrowIterator(mi, i);
+	      set_mi_string_key(mi_dirs, (char *) search_dirNames[search_dirIndexes[i]]);
 
+	      dbiIndexSet set2;
+	      if (rpmdbGet_dbiIndexSet(mi_dirs, &set2) != 0) {
+		   set = dbiFreeIndexSet(set);
+		   continue; /* no match */
+	      }
+
+	      dbiIntersectSet(set, set2, 0);
+
+	      dbiFreeIndexSet(set2);
+	 }
+
+	 if (set->count > 0)
+	      rpmdbGrowIterator(mi, set, i);
+	 else
+	      set = dbiFreeIndexSet(set);
     }
 
+    if (mi_dirs) mi_dirs = rpmdbFreeIterator(mi_dirs);
+
     if ((i = rpmdbGetIteratorCount(mi)) == 0) {
 	mi = rpmdbFreeIterator(mi);
 	return 0;
@@ -3437,7 +3515,6 @@ if (key->size == 0) key->size++;	/* XXX 
 	rpmTagType bnt, dnt;
 	int_32 * dirIndexes;
 	int_32 * fullDirIndexes;
-	fingerPrint * fps;
 	dbiIndexItem im;
 	int start;
 	int num;
@@ -3469,21 +3546,18 @@ if (key->size == 0) key->size++;	/* XXX 
 	}
 /*@=bounds@*/
 
-	fps = xcalloc(num, sizeof(*fps));
-	fpLookupList(fpc, dirNames, baseNames, dirIndexes, num, fps);
-
 	/* Add db (recnum,filenum) to list for fingerprint matches. */
 /*@-boundsread@*/
 	for (i = 0; i < num; i++, im++) {
-	    /*@-nullpass@*/ /* FIX: fpList[].subDir may be NULL */
-	    if (!FP_EQUAL(fps[i], fpList[im->fpNum]))
+	    char *subDir = dirNames[dirIndexes[i]];
+
+	    if (strcmp(subDir, search_dirNames[search_dirIndexes[im->fpNum]]) != 0)
 		/*@innercontinue@*/ continue;
 	    /*@=nullpass@*/
 	    xx = dbiAppendSet(matchList[im->fpNum], im, 1, sizeof(*im), 0);
 	}
 /*@=boundsread@*/
 
-	fps = _free(fps);
 	dirNames = hfd(dirNames, dnt);
 	fullBaseNames = hfd(fullBaseNames, bnt);
 	baseNames = _free(baseNames);
diff -up rpm-4.4.2.2/rpmdb/fprint.h.pix rpm-4.4.2.2/rpmdb/fprint.h
--- rpm-4.4.2.2/rpmdb/fprint.h.pix	2007-09-11 08:28:15.000000000 +0200
+++ rpm-4.4.2.2/rpmdb/fprint.h	2007-10-23 16:36:45.000000000 +0200
@@ -73,7 +73,8 @@ extern "C" {
  * @param numItems	number of fingerprint items
  * @return		0 always
  */
-int rpmdbFindFpList(/*@null@*/ rpmdb db, fingerPrint  * fpList,
+int rpmdbFindList(/*@null@*/ rpmdb db, const char ** dirNames, 
+		  const char ** baseNames, const uint_32 * dirIndexes, 
 		/*@out@*/ dbiIndexSet * matchList, int numItems)
 	/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
 	/*@modifies db, *matchList, rpmGlobalMacroContext,
diff -up rpm-4.4.2.2/lib/transaction.c.pix rpm-4.4.2.2/lib/transaction.c
--- rpm-4.4.2.2/lib/transaction.c.pix	2007-10-23 16:36:45.000000000 +0200
+++ rpm-4.4.2.2/lib/transaction.c	2007-10-23 16:36:45.000000000 +0200
@@ -1778,7 +1778,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing f
 	(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
 	/* Extract file info for all files in this package from the database. */
 	matches = xcalloc(fc, sizeof(*matches));
-	if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) {
+	if (rpmdbFindList(rpmtsGetRdb(ts), fi->dnl, fi->bnl, fi->dil, matches, fc)) {
 	    ps = rpmpsFree(ps);
 	    rpmtsFreeLock(lock);
 	    return 1;	/* XXX WTFO? */