Hi Panu et al,

attached are two patches to make dependency solving faster/more correct.
The first one switches the "installed file conflicts" cache from
complete file names to base names, to make fingerprinting work for them.

The second one is the more interesing one, it adds a "installed file
requires" cache. This cache is only created at the start of 
rpmtsCheck(), so it is most useful for big transactions. It is used
to prune the filelist of the erased packages.

Some numbers from my system:

$ rpm -ql ddd | wc -l
51
$ rpm -ql kernel-source | wc -l
31128

With cold caches:
  - erase ddd
    complete dependency check: 27ms
  - erase ddd with requires cache
    cache creation: 16ms, complete dependency check: 30ms

  - erase kernel-source
    complete dependency check: 72ms
  - erase kernel-source with requires cache
    cache creation: 16ms, complete dependency check: 33ms

With hot caches:
  - erase ddd
    complete dependency check: 0ms
  - erase ddd with requires cache
    cache creation: 2ms, complete dependency check: 2ms

  - erase kernel-source
    complete dependency check: 44ms
  - erase kernel-source with requires cache
    cache creation: 2ms, complete dependency check: 8ms

So it's a very little bit slower for small packages, but helps a
lot for big packages or big transactions.

Cheers,
  Michael.

-- 
Michael Schroeder                                   m...@suse.de
SUSE LINUX Products GmbH,  GF Jeff Hawn, HRB 16746 AG Nuernberg
main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}
>From 68a2868e53a94147aa95bcd8796c310663cd16fc Mon Sep 17 00:00:00 2001
From: Michael Schroeder <m...@suse.de>
Date: Wed, 6 Aug 2014 13:21:08 +0200
Subject: [PATCH 1/2] Put basenames in the conflict dependency cache

This makes the fingerprinting code work for file conflicts of
installed packages.
---
 lib/depends.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/lib/depends.c b/lib/depends.c
index 7fd3986..3017cd2 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -754,6 +754,7 @@ int rpmtsCheck(rpmts ts)
     dcache = depCacheCreate(5001, rstrhash, strcmp,
 				     (depCacheFreeKey)rfree, NULL);
 
+    /* build cache of all file conflicts dependencies */
     confcache = conflictsCacheCreate(257, rstrhash, strcmp,
 				     (depCacheFreeKey)rfree);
     if (confcache) {
@@ -765,9 +766,15 @@ int rpmtsCheck(rpmts ts)
 		char *k;
 		if (!key || keylen == 0 || key[0] != '/')
 		    continue;
-		k = rmalloc(keylen + 1);
-		memcpy(k, key, keylen);
-		k[keylen] = 0;
+		while (keylen > 1 && (k = memchr(key + 1, '/', keylen - 1))) {
+		    keylen -= k - key;
+		    key += k - key;
+		}
+		if (keylen <= 1)
+		    continue;
+		k = rmalloc(keylen);
+		memcpy(k, key + 1, keylen - 1);
+		k[keylen - 1] = 0;
 		conflictsCacheAddEntry(confcache, k);
 	    }
 	    rpmdbIndexIteratorFree(ii);
@@ -810,10 +817,9 @@ int rpmtsCheck(rpmts ts)
 	    rpmfiles files = rpmteFiles(p);
 	    rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD);
 	    while (rpmfiNext(fi) >= 0) {
-		const char *fn = rpmfiFN(fi);
-		if (!conflictsCacheHasEntry(confcache, fn))
+		if (!conflictsCacheHasEntry(confcache, rpmfiBN(fi)))
 		    continue;
-		checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fn);
+		checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, rpmfiFN(fi));
 	    }
 	    rpmfiFree(fi);
 	    rpmfilesFree(files);
-- 
1.8.1.4

>From 8eb6ed8b8f09c86917005041b4203d615db69b4b Mon Sep 17 00:00:00 2001
From: Michael Schroeder <m...@suse.de>
Date: Wed, 6 Aug 2014 13:27:56 +0200
Subject: [PATCH 2/2] Also build cache file requires of installed packages

This speeds up erasure/update of packages with a large amount of files
quite a bit. The cost of building the cache seems to be just a couple
of msecs, and it just needs to be done once for the complete transaction
set.
---
 lib/depends.c | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/lib/depends.c b/lib/depends.c
index 3017cd2..e871018 100644
--- a/lib/depends.c
+++ b/lib/depends.c
@@ -55,6 +55,13 @@ const int rpmFLAGS = RPMSENSE_EQUAL;
 #undef HASHTYPE
 #undef HTKEYTYPE
 
+#define HASHTYPE requiresCache
+#define HTKEYTYPE const char *
+#include "rpmhash.H"
+#include "rpmhash.C"
+#undef HASHTYPE
+#undef HTKEYTYPE
+
 enum addOp_e {
     RPMTE_INSTALL	= 0,
     RPMTE_UPGRADE	= 1,
@@ -740,6 +747,7 @@ int rpmtsCheck(rpmts ts)
     int rc = 0;
     depCache dcache = NULL;
     conflictsCache confcache = NULL;
+    requiresCache reqcache = NULL;
     
     (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
 
@@ -781,6 +789,33 @@ int rpmtsCheck(rpmts ts)
 	}
     }
 
+    /* build cache of all file requires dependencies */
+    reqcache = requiresCacheCreate(65537, rstrhash, strcmp,
+				     (depCacheFreeKey)rfree);
+    if (reqcache) {
+	rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMTAG_REQUIRENAME);
+	if (ii) {
+	    char *key;
+	    size_t keylen;
+	    while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) {
+		char *k;
+		if (!key || keylen == 0 || key[0] != '/')
+		    continue;
+		while (keylen > 1 && (k = memchr(key + 1, '/', keylen - 1))) {
+		    keylen -= k - key;
+		    key += k - key;
+		}
+		if (keylen <= 1)
+		    continue;
+		k = rmalloc(keylen);
+		memcpy(k, key + 1, keylen - 1);
+		k[keylen - 1] = 0;
+		requiresCacheAddEntry(reqcache, k);
+	    }
+	    rpmdbIndexIteratorFree(ii);
+	}
+    }
+
     
     /*
      * Look at all of the added packages and make sure their dependencies
@@ -845,8 +880,11 @@ int rpmtsCheck(rpmts ts)
 	}
 
 	while (rpmfiNext(fi) >= 0) {
-	    if (RPMFILE_IS_INSTALLED(rpmfiFState(fi)))
+	    if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) {
+		if (!requiresCacheHasEntry(reqcache, rpmfiBN(fi)))
+		    continue;
 		checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmfiFN(fi));
+	    }
 	}
 	rpmfiFree(fi);
 	rpmfilesFree(files);
@@ -856,6 +894,7 @@ int rpmtsCheck(rpmts ts)
 exit:
     depCacheFree(dcache);
     conflictsCacheFree(confcache);
+    requiresCacheFree(reqcache);
 
     (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
 
-- 
1.8.1.4

_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to