Hi!

This is a revisited patch to finally add a set of unresolved transaction members to tsInfo that is maintained by the tsInfo object itself. That way it cannot get outdated when plugins or other code pieces add or remove pkgs form the transaction behind the back of the depsolver.

This allows to avoid restarting the depsolving from scratch after running the plugins or the skip-broken code.

For my F8 Everything install this reduces depsolving time from 2m20.689s to 1m18.402s. This is more or less the time for the first depsolving run.

To be able to handle the txmbrs sanely I had to change the implementation of __hash__ and __cmp__. __cmp__ still sorts alfabetically but returns 0 only on identity. For __hash__ the object.__hash__ is used.

May be this should be tested a bit more with the reinstall command.

With this patch testAddTheSameTwice from transactiontests fails. This is intended as long as addInstall and friends do not return the right txmbr object.


Thoughts?

Florian
>From 5625464786cd8f8d849be423b86417b219abb952 Mon Sep 17 00:00:00 2001
From: Florian Festi <[EMAIL PROTECTED]>
Date: Wed, 28 Nov 2007 17:33:25 +0100
Subject: [PATCH] Add tsInfo.getUnresolvedMembers() and use if for depsolving
 Drop tsInfo.removedmembers and DepCheck.already_seen*

---
 yum/depsolve.py        |   25 +++++--------------------
 yum/transactioninfo.py |   45 ++++++++++++++++++++++-----------------------
 2 files changed, 27 insertions(+), 43 deletions(-)

diff --git a/yum/depsolve.py b/yum/depsolve.py
index 8c784eb..51d3dfb 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -683,13 +683,9 @@ class Depsolve(object):
         # holder object for things from the check
         if not hasattr(self, '_dcobj'):
             self._dcobj = DepCheck()
-        else:
-            # reset what we've seen as things may have changed between calls
-            # to resolveDeps (rh#242368, rh#308321)
-            self._dcobj.reset()
         self.po_with_problems = set()
         self._working_po = None
-        self.tsInfo.removedmembers.clear()
+        self.tsInfo.resetResolved(hard=False)
 
         CheckDeps = True
         CheckRemoves = False
@@ -774,10 +770,7 @@ class Depsolve(object):
         CheckRemoves = False
         # we need to check the opposite of install and remove for regular
         # tsInfo members vs removed members
-        for (txmbr, inst, rem) in map(lambda x: (x, TS_INSTALL_STATES, TS_REMOVE_STATES), self.tsInfo.getMembers()) + map(lambda x: (x, TS_REMOVE_STATES, TS_INSTALL_STATES), self.tsInfo.getRemovedMembers()):
-            if (self._dcobj.already_seen_removed.has_key(txmbr) or
-                (txmbr.ts_state is not None and self._dcobj.already_seen.has_key(txmbr))):
-                continue
+        for txmbr in self.tsInfo.getUnresolvedMembers():
 
             if self.dsCallback and txmbr.ts_state:
                 self.dsCallback.pkgAdded(txmbr.pkgtup, txmbr.ts_state)
@@ -793,10 +786,10 @@ class Depsolve(object):
             else:
                 self._working_po = txmbr.po
            
-            if txmbr.output_state in inst:
+            if (txmbr.output_state in TS_INSTALL_STATES) == (txmbr.po.state != None):
                 thisneeds = self._checkInstall(txmbr)
                 CheckInstalls = True
-            elif txmbr.output_state in rem:
+            else:
                 thisneeds = self._checkRemove(txmbr)
                 CheckRemoves = True
 
@@ -808,10 +801,7 @@ class Depsolve(object):
                 missing_in_pkg |= missing
 
             if not missing_in_pkg:
-                if txmbr.ts_state is None:
-                    self._dcobj.already_seen_removed[txmbr] = 1
-                else:
-                    self._dcobj.already_seen[txmbr] = 1
+                self.tsInfo.markAsResolved(txmbr)
 
             any_missing |= missing_in_pkg
 
@@ -985,11 +975,6 @@ class DepCheck(object):
     def __init__(self):
         self.requires = []
         self.conflicts = []
-        self.reset()
-
-    def reset(self):
-        self.already_seen = {}
-        self.already_seen_removed = {}
 
     def addRequires(self, po, req_tuple_list):
         # fixme - do checking for duplicates or additions in here to zip things along
diff --git a/yum/transactioninfo.py b/yum/transactioninfo.py
index c899abc..58a5e5e 100644
--- a/yum/transactioninfo.py
+++ b/yum/transactioninfo.py
@@ -41,7 +41,7 @@ class TransactionData:
         self.root = '/'
         self.pkgdict = {} # key = pkgtup, val = list of TransactionMember obj
         self._namedict = {} # name -> list of TransactionMember obj
-        self.removedmembers = {}
+        self._unresolvedMembers = set()
         self.debug = 0
         self.changed = False
         self.installonlypkgs = []
@@ -94,20 +94,18 @@ class TransactionData:
             returnlist.extend(self.pkgdict[pkgtup])
         return returnlist
             
-    def getRemovedMembers(self, pkgtup=None):
-        """takes an optional package tuple and returns all transaction members
-           matching, no pkgtup means it returns all transaction members"""
-
-        returnlist = []
+    def getUnresolvedMembers(self):
+        return list(self._unresolvedMembers)
 
-        if pkgtup is None:
-            for members in self.removedmembers.itervalues():
-                returnlist.extend(members)
-        elif self.removedmembers.has_key(pkgtup):
-            returnlist.extend(self.removedmembers[pkgtup])
-
-        return returnlist
+    def markAsResolved(self, txmbr):
+        self._unresolvedMembers.discard(txmbr)
 
+    def resetResolved(self, hard=False):
+        if hard or len(self) < len(self._unresolvedMembers):
+            self._unresolvedMembers.clear()
+            self._unresolvedMembers.update(self.getMembers())
+            return True
+        return False
 
     def getMode(self, name=None, arch=None, epoch=None, ver=None, rel=None):
         """returns the mode of the first match from the transaction set, 
@@ -198,7 +196,7 @@ class TransactionData:
             for po in self.conditionals[txmember.name]:
                 condtxmbr = self.addInstall(po)
                 condtxmbr.setAsDep(po=txmember.po)
-        
+        self._unresolvedMembers.add(txmember)
 
     def remove(self, pkgtup):
         """remove a package from the transaction"""
@@ -212,8 +210,8 @@ class TransactionData:
             elif isinstance(txmbr.po, YumAvailablePackageSqlite):
                 self.pkgSackPackages -= 1
             self._namedict[txmbr.name].remove(txmbr)
+            self._unresolvedMembers.add(txmbr)
         
-        self.removedmembers.setdefault(pkgtup, []).extend(self.pkgdict[pkgtup])
         del self.pkgdict[pkgtup]
         if not self._namedict[pkgtup[0]]:
             del self._namedict[pkgtup[0]]
@@ -552,15 +550,17 @@ class TransactionMember:
             self.depends_on.append(po)
 
     def __cmp__(self, other):
-        if self.name > other.name:
-            return 1
-        if self.name < other.name:
-            return -1
-        if self.name == other.name:
-            return 0
+        result = cmp(self.name, other.name)
+        if result == 0:
+            result = cmp(hash(self), hash(other))
+            if self is other:
+                return 0
+            if result == 0:
+                return 1
+        return result
 
     def __hash__(self):
-        return hash(self.po.pkgtup)
+        return object.__hash__(self)
             
     def __str__(self):
         return "%s.%s %s-%s-%s - %s" % (self.name, self.arch, self.epoch,
@@ -579,4 +579,3 @@ class TransactionMember:
     # current and output states are defined in constants
     # relationships are defined in constants
     # ts states are: u, i, e
-    
-- 
1.5.3.8

_______________________________________________
Yum-devel mailing list
[email protected]
https://lists.dulug.duke.edu/mailman/listinfo/yum-devel

Reply via email to