Hi!
This patch keeps the indexes of the PackageSack in sync with the packages in
the sack. This solves a corruption of the indexes when adding packages
between searches.
The patch dramatically increases the performance for
Add packages - Search - Add package - Search scenarios
It dramatically reduces performance for
Add packages - Search - Remove most packages - Search scenarios
This can be avoided using the new .clearIndexes() method if the situation is
known in advance.
Patch will be needed for searching in localinstall packages. As the code
handling them will move away from cli.py and call patterns of 3rd party code
is unknown this patch is needed to avoid difficult to spot bugs related to
the outdated indexes.
Florian Festi
Index: yum/packageSack.py
===================================================================
RCS file: /cvsroot/yum/cvs/yum/yum/packageSack.py,v
retrieving revision 1.29
diff -u -r1.29 packageSack.py
--- yum/packageSack.py 4 Mar 2007 21:45:16 -0000 1.29
+++ yum/packageSack.py 13 Jun 2007 07:33:38 -0000
@@ -504,7 +504,7 @@
def _delFromListOfDict(self, dict, key, data):
if not dict.has_key(key):
- dict[key] = []
+ return
try:
dict[key].remove(data)
except ValueError:
@@ -525,13 +525,23 @@
self._addToDictAsList(self.pkgsByRepo, repoid, obj)
else:
self._addToDictAsList(self.pkgsByRepo, repoid, obj)
-
+ if self.indexesBuilt:
+ self._addPackageToIndex(obj)
def buildIndexes(self):
"""builds the useful indexes for searching/querying the packageSack
This should be called after all the necessary packages have been
added/deleted"""
+
+ self.clearIndexes()
+ for repoid in self.pkgsByRepo.keys():
+ for obj in self.pkgsByRepo[repoid]:
+ self._addPackageToIndex(obj)
+ self.indexesBuilt = 1
+
+
+ def clearIndexes(self):
# blank out the indexes
self.obsoletes = {}
self.requires = {}
@@ -540,36 +550,50 @@
self.filenames = {}
self.nevra = {}
self.pkgsByID = {}
+
+ self.indexesBuilt = 0
- for repoid in self.pkgsByRepo.keys():
- for obj in self.pkgsByRepo[repoid]:
- # store the things provided just on name, not the whole require+version
- # this lets us reduce the set of pkgs to search when we're trying to depSolve
- for (n, fl, (e,v,r)) in obj.returnPrco('obsoletes'):
- self._addToDictAsList(self.obsoletes, n, obj)
- for (n, fl, (e,v,r)) in obj.returnPrco('requires'):
- self._addToDictAsList(self.requires, n, obj)
- for (n, fl, (e,v,r)) in obj.returnPrco('provides'):
- self._addToDictAsList(self.provides, n, obj)
- for (n, fl, (e,v,r)) in obj.returnPrco('conflicts'):
- self._addToDictAsList(self.conflicts, n, obj)
- for ftype in obj.returnFileTypes():
- for file in obj.returnFileEntries(ftype):
- self._addToDictAsList(self.filenames, file, obj)
- self._addToDictAsList(self.pkgsByID, obj.id, obj)
- (name, arch, epoch, ver, rel) = obj.pkgtup
- self._addToDictAsList(self.nevra, (name, epoch, ver, rel, arch), obj)
- self._addToDictAsList(self.nevra, (name, None, None, None, None), obj)
-
- self.indexesBuilt = 1
-
+ def _addPackageToIndex(self, obj):
+ # store the things provided just on name, not the whole require+version
+ # this lets us reduce the set of pkgs to search when we're trying to depSolve
+ for (n, fl, (e,v,r)) in obj.returnPrco('obsoletes'):
+ self._addToDictAsList(self.obsoletes, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('requires'):
+ self._addToDictAsList(self.requires, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('provides'):
+ self._addToDictAsList(self.provides, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('conflicts'):
+ self._addToDictAsList(self.conflicts, n, obj)
+ for ftype in obj.returnFileTypes():
+ for file in obj.returnFileEntries(ftype):
+ self._addToDictAsList(self.filenames, file, obj)
+ self._addToDictAsList(self.pkgsByID, obj.id, obj)
+ (name, arch, epoch, ver, rel) = obj.pkgtup
+ self._addToDictAsList(self.nevra, (name, epoch, ver, rel, arch), obj)
+ self._addToDictAsList(self.nevra, (name, None, None, None, None), obj)
+ def _delPackageFromIndex(self, obj):
+ for (n, fl, (e,v,r)) in obj.returnPrco('obsoletes'):
+ self._delFromListOfDict(self.obsoletes, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('requires'):
+ self._delFromListOfDict(self.requires, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('provides'):
+ self._delFromListOfDict(self.provides, n, obj)
+ for (n, fl, (e,v,r)) in obj.returnPrco('conflicts'):
+ self._delFromListOfDict(self.conflicts, n, obj)
+ for ftype in obj.returnFileTypes():
+ for file in obj.returnFileEntries(ftype):
+ self._delFromListOfDict(self.filenames, file, obj)
+ self._delFromListOfDict(self.pkgsByID, obj.id, obj)
+ (name, arch, epoch, ver, rel) = obj.pkgtup
+ self._delFromListOfDict(self.nevra, (name, epoch, ver, rel, arch), obj)
+ self._delFromListOfDict(self.nevra, (name, None, None, None, None), obj)
def delPackage(self, obj):
"""delete a pkgobject"""
self._delFromListOfDict(self.pkgsByRepo, obj.repoid, obj)
- if self.indexesBuilt: # if we've built indexes, delete it b/c we've just deleted something
- self.indexesBuilt = 0
+ if self.indexesBuilt:
+ self._delPackageFromIndex(obj)
def returnPackages(self, repoid=None):
"""return list of all packages, takes optional repoid"""
_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel