Hi,

Trying to debug my package installation 'LOOP:' problems I have
instrumented the RPM source code with many 'rpmlog(RPMLOG_DEBUG, ...)',
so I could understand what is happening there.

After hours of such debugging I found out what is going on: for each
dependency rpmalSatisfiesDepend() is called from order.c to build the
dependency graph. There, for every file dependency (package requires
'/something') rpmalAllFileSatisfiesDepend() is called which finds out
what packages provide the required file. And here is the problem:
rpmalAllFileSatisfiesDepend() uses a Bloom filter look-up to find out
if a package contain a file. But Bloom filter, to its very nature, gives
false positives, which are not verified further. So, it can happen that
rpmalSatisfiesDepend() returns wrong package for a required file or
directory, which adds an extra edge to the dependency graph. RPM reports
this as a 'LOOP' problem and tries to work-around it by changing the
installation order, which totally breaks the order for me.

The attached patch is a quick fix to the problem: after rpmbfChk()
states a file is provided by a package, its answer is additionally
verified by scanning the file index of the package.

I am sure this can be implemented in a more elegant way, but I don't
know the internal RPM architecture well enough and I cannot spend much
more time on fixing this problem.

Greets,
        Jacek
diff -dur rpm-5.4.12.orig/lib/rpmal.c rpm-5.4.12/lib/rpmal.c
--- rpm-5.4.12.orig/lib/rpmal.c	2012-04-15 23:20:57.000000000 +0200
+++ rpm-5.4.12/lib/rpmal.c	2013-08-13 13:46:28.000000000 +0200
@@ -7,6 +7,10 @@
 #include <rpmio.h>
 #include <rpmiotypes.h>		/* XXX fnpyKey */
 #include <rpmbf.h>
+#include <rpmlog.h>
+
+#define _RPMFI_INTERNAL
+#include <rpmfi.h>
 
 #include <rpmtag.h>
 #include <rpmtypes.h>
@@ -38,6 +42,7 @@
     rpmds provides;		/*!< Provides: dependencies. */
 /*@refcounted@*/ /*@null@*/
     rpmbf bf;			/*!< File name Bloom filter. */
+    rpmfi fi;			/*!< File name Bloom filter. */
 
     rpmuint32_t tscolor;	/*!< Transaction color bits. */
 
@@ -149,6 +154,8 @@
 	alp->provides = NULL;
 	(void)rpmbfFree(alp->bf);
 	alp->bf = NULL;
+	(void)rpmbfFree(alp->fi);
+	alp->fi = NULL;
     }
 
     al->list = _free(al->list);
@@ -205,6 +212,8 @@
     alp->provides = NULL;
     (void)rpmbfFree(alp->bf);
     alp->bf = NULL;
+    (void)rpmbfFree(alp->fi);
+    alp->fi = NULL;
 
     memset(alp, 0, sizeof(*alp));	/* XXX trash and burn */
     return;
@@ -244,6 +253,7 @@
 /*@-assignexpose -castexpose @*/
     alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
     alp->bf = rpmbfLink(rpmfiFNBF(fi));
+    alp->fi = rpmfiLink(fi, "file list (rpmalAdd)");
 /*@=assignexpose =castexpose @*/
 
     rpmalFreeIndex(al);
@@ -350,17 +360,17 @@
 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
 {
     fnpyKey * ret = NULL;
-    int found = 0;
+    int found = 0, verified = 0;
     const char * fn;
     size_t nfn;
-    int i;
+    int i, j;
 
     if (keyp) *keyp = RPMAL_NOMATCH;
 
     if (al == NULL || (fn = rpmdsN(ds)) == NULL || *fn != '/')
 	goto exit;
     nfn = strlen(fn);
-
+    
     if (al->list != NULL)	/* XXX always true */
     for (i = 0; i < al->size; i++) {
 	availablePackage alp = al->list + i;
@@ -368,6 +378,24 @@
 	if (!rpmbfChk(alp->bf, fn, nfn))
 	    continue;
 
+	verified = 0;
+    	char * fifn = (char *) malloc(alp->fi->fnlen + 1);
+	for(j=0; j<(int)alp->fi->fc; j++) {
+		const char * dn = NULL;
+		(void) urlPath(alp->fi->dnl[alp->fi->dil[j]], &dn);
+		strcpy(stpcpy(fifn, dn), alp->fi->bnl[j]);
+		if (!strcmp(fn, fifn)) {
+			verified = 1;
+			break;
+		}
+	}
+	free(fifn);
+	
+	if (!verified) {
+    		rpmlog(RPMLOG_DEBUG, "   False positive: '%s'\n", fn);
+		continue;
+	}
+        
 	rpmdsNotify(ds, _("(added files)"), 0);
 
 	ret = (fnpyKey *) xrealloc(ret, (found + 2) * sizeof(*ret));
_______________________________________________
pld-devel-en mailing list
pld-devel-en@lists.pld-linux.org
http://lists.pld-linux.org/mailman/listinfo/pld-devel-en

Reply via email to