[yum-commits] Branch 'yum-3_2_X' - 6 commits - cli.py yum/depsolve.py yum/rpmtrans.py

Panu Matilainen pmatilai at osuosl.org
Fri Feb 25 09:40:16 UTC 2011


 cli.py          |    1 
 yum/depsolve.py |    9 ++
 yum/rpmtrans.py |  173 +++++++++++++++++++++++++-------------------------------
 3 files changed, 89 insertions(+), 94 deletions(-)

New commits:
commit bfb557ad7224c8ead41121d9ef60850d0cf2db02
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Fri Feb 25 11:38:25 2011 +0200

    Enable the new callback mode for yum itself
    
    API users should be converted one-by-one to the new mode...

diff --git a/cli.py b/cli.py
index 0441c02..a4c7c79 100644
--- a/cli.py
+++ b/cli.py
@@ -73,6 +73,7 @@ class YumBaseCli(yum.YumBase, output.YumOutput):
         self.logger = logging.getLogger("yum.cli")
         self.verbose_logger = logging.getLogger("yum.verbose.cli")
         self.yum_cli_commands = {}
+        self.use_txmbr_in_callback = True
         self.registerCommand(yumcommands.InstallCommand())
         self.registerCommand(yumcommands.UpdateCommand())
         self.registerCommand(yumcommands.InfoCommand())
commit a11bb92b0ac168535a64c57a20f4730c25ea46d0
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Fri Feb 25 11:37:44 2011 +0200

    Add a new opt-in callback mode where only txmbr is used as the key
    
    We really only want the txmbr in the key, everything else can be
    reached through it. This avoids copying any data around as txmbrs
    reside in memory anyway, so the key is just a cheap reference
    to what we already have. With the new key -> txmbr helper in the
    callback, this is truly trivial to handle there. The new mode
    makes life in the callback somewhat easier and saves gobs of memory.

diff --git a/yum/depsolve.py b/yum/depsolve.py
index 3aaba0e..8f18ccc 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -69,6 +69,8 @@ class Depsolve(object):
         self._ts = None
         self._tsInfo = None
         self.dsCallback = None
+        # Callback-style switch, default to legacy (hdr, file) mode
+        self.use_txmbr_in_callback = False
         self.logger = logging.getLogger("yum.Depsolve")
         self.verbose_logger = logging.getLogger("yum.verbose.Depsolve")
 
@@ -220,8 +222,13 @@ class Depsolve(object):
                         txmbr.ts_state = 'i'
                         txmbr.output_state = TS_INSTALL
 
+                # New-style callback with just txmbr instead of full headers?
+                if self.use_txmbr_in_callback:
+                    cbkey = txmbr
+                else:
+                    cbkey = (hdr, rpmfile)
                 
-                self.ts.addInstall(hdr, (hdr, rpmfile), txmbr.ts_state)
+                self.ts.addInstall(hdr, cbkey, txmbr.ts_state)
                 self.verbose_logger.log(logginglevels.DEBUG_1,
                     _('Adding Package %s in mode %s'), txmbr.po, txmbr.ts_state)
                 if self.dsCallback:
diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index f969b03..08bf99d 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -25,6 +25,7 @@ import types
 import sys
 from yum.constants import *
 from yum import _
+from yum.transactioninfo import TransactionMember
 import misc
 import tempfile
 
@@ -258,7 +259,9 @@ class RPMTransaction:
     # the exact txmbr but we always have a name, so return (name, txmbr)
     # tuples so callers have less twists to deal with.
     def _getTxmbr(self, cbkey):
-        if isinstance(cbkey, tuple):
+        if isinstance(cbkey, TransactionMember):
+            return (cbkey.name, cbkey)
+        elif isinstance(cbkey, tuple):
             pkgtup = self._dopkgtup(cbkey[0])
             txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
             # if this is not one, somebody screwed up
commit 905728eac850b7e2109deb9c8aafd05701ee04c3
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Fri Feb 25 11:36:57 2011 +0200

    Unify callback key guessworks into helper function
    
    Add an internal helper method to deal with the changing key type,
    and locate the associated txmbr object when possible. We can't find
    it on erasures, but we always have a name so return (name, txmbr) tuples
    to simplify life for callers.

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index ecb1129..f969b03 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -254,6 +254,21 @@ class RPMTransaction:
 
         return (hdr['name'], hdr['arch'], epoch, hdr['version'], hdr['release'])
 
+    # Find out txmbr based on the callback key. On erasures we dont know
+    # the exact txmbr but we always have a name, so return (name, txmbr)
+    # tuples so callers have less twists to deal with.
+    def _getTxmbr(self, cbkey):
+        if isinstance(cbkey, tuple):
+            pkgtup = self._dopkgtup(cbkey[0])
+            txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
+            # if this is not one, somebody screwed up
+            assert len(txmbrs) == 1
+            return (txmbrs[0].name, txmbrs[0])
+        elif isinstance(cbkey, basestring):
+            return (cbkey, None)
+        else:
+            return (None, None)
+
     def ts_done(self, package, action):
         """writes out the portions of the transaction which have completed"""
         
@@ -415,9 +430,9 @@ class RPMTransaction:
 
     def _instOpenFile(self, bytes, total, h):
         self.lastmsg = None
-        hdr = None
-        if h is not None:
-            hdr, rpmloc = h[0], h[1]
+        name, txmbr = self._getTxmbr(h)
+        if txmbr is not None:
+            rpmloc = txmbr.po.localPkg()
             try:
                 self.fd = file(rpmloc)
             except IOError, e:
@@ -426,48 +441,41 @@ class RPMTransaction:
                 if self.trans_running:
                     self.total_installed += 1
                     self.complete_actions += 1
-                    self.installed_pkg_names.add([hdr['name']])
+                    self.installed_pkg_names.add(name)
                 return self.fd.fileno()
         else:
             self.display.errorlog("Error: No Header to INST_OPEN_FILE")
             
     def _instCloseFile(self, bytes, total, h):
-        hdr = None
-        if h is not None:
-            hdr, rpmloc = h[0], h[1]
+        name, txmbr = self._getTxmbr(h)
+        if txmbr is not None:
             self.fd.close()
             self.fd = None
             if self.test: return
             if self.trans_running:
-                pkgtup = self._dopkgtup(hdr)
-                txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
-                for txmbr in txmbrs:
-                    self.display.filelog(txmbr.po, txmbr.output_state)
-                    self._scriptout(txmbr.po)
-                    # NOTE: We only do this for install, not erase atm.
-                    #       because we don't get pkgtup data for erase (this 
-                    #       includes "Updated" pkgs).
-                    pid   = self.base.history.pkg2pid(txmbr.po)
-                    state = self.base.history.txmbr2state(txmbr)
-                    self.base.history.trans_data_pid_end(pid, state)
-                    self.ts_done(txmbr.po, txmbr.output_state)
+                self.display.filelog(txmbr.po, txmbr.output_state)
+                self._scriptout(txmbr.po)
+                # NOTE: We only do this for install, not erase atm.
+                #       because we don't get pkgtup data for erase (this 
+                #       includes "Updated" pkgs).
+                pid   = self.base.history.pkg2pid(txmbr.po)
+                state = self.base.history.txmbr2state(txmbr)
+                self.base.history.trans_data_pid_end(pid, state)
+                self.ts_done(txmbr.po, txmbr.output_state)
     
     def _instProgress(self, bytes, total, h):
-        if h is not None:
-            # If h is a string, we're repackaging.
+        name, txmbr = self._getTxmbr(h)
+        if name is not None:
+            # If we only have a name, we're repackaging.
             # Why the RPMCALLBACK_REPACKAGE_PROGRESS flag isn't set, I have no idea
-            if type(h) == type(""):
-                self.display.event(h, 'repackaging',  bytes, total,
+            if txmbr is None:
+                self.display.event(name, 'repackaging',  bytes, total,
                                 self.complete_actions, self.total_actions)
-
             else:
-                hdr, rpmloc = h[0], h[1]
-                pkgtup = self._dopkgtup(hdr)
-                txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
-                for txmbr in txmbrs:
-                    action = txmbr.output_state
-                    self.display.event(txmbr.po, action, bytes, total,
-                                self.complete_actions, self.total_actions)
+                action = txmbr.output_state
+                self.display.event(txmbr.po, action, bytes, total,
+                            self.complete_actions, self.total_actions)
+
     def _unInstStart(self, bytes, total, h):
         pass
         
@@ -475,20 +483,21 @@ class RPMTransaction:
         pass
     
     def _unInstStop(self, bytes, total, h):
+        name, txmbr = self._getTxmbr(h)
         self.total_removed += 1
         self.complete_actions += 1
-        if h not in self.installed_pkg_names:
-            self.display.filelog(h, TS_ERASE)
+        if name not in self.installed_pkg_names:
+            self.display.filelog(name, TS_ERASE)
             action = TS_ERASE
         else:
             action = TS_UPDATED                    
         
-        self.display.event(h, action, 100, 100, self.complete_actions,
+        self.display.event(name, action, 100, 100, self.complete_actions,
                             self.total_actions)
-        self._scriptout(h)
+        self._scriptout(name)
         
         if self.test: return # and we're done
-        self.ts_done(h, action)
+        self.ts_done(name, action)
         
         
     def _rePackageStart(self, bytes, total, h):
@@ -501,20 +510,16 @@ class RPMTransaction:
         pass
         
     def _cpioError(self, bytes, total, h):
-        hdr, rpmloc = h[0], h[1]
-        pkgtup = self._dopkgtup(hdr)
-        txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
-        for txmbr in txmbrs:
+        name, txmbr = self._getTxmbr(h)
+        if txmbr is not None:
             msg = "Error in cpio payload of rpm package %s" % txmbr.po
             txmbr.output_state = TS_FAILED
             self.display.errorlog(msg)
             # FIXME - what else should we do here? raise a failure and abort?
     
     def _unpackError(self, bytes, total, h):
-        hdr, rpmloc = h[0], h[1]
-        pkgtup = self._dopkgtup(hdr)
-        txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
-        for txmbr in txmbrs:
+        name, txmbr = self._getTxmbr(h)
+        if txmbr is not None:
             txmbr.output_state = TS_FAILED
             msg = "Error unpacking rpm package %s" % txmbr.po
             self.display.errorlog(msg)
@@ -522,35 +527,24 @@ class RPMTransaction:
             # right behavior should be
                 
     def _scriptError(self, bytes, total, h):
-        if not isinstance(h, types.TupleType):
-            # fun with install/erase transactions, see rhbz#484729
-            h = (h, None)
-        hdr, rpmloc = h[0], h[1]
-        remove_hdr = False # if we're in a clean up/remove then hdr will not be an rpm.hdr
-        if not isinstance(hdr, rpm.hdr):
-            txmbrs = [hdr]
-            remove_hdr = True
+        # "bytes" carries the failed scriptlet tag,
+        # "total" carries fatal/non-fatal status
+        scriptlet_name = rpm.tagnames.get(bytes, "<unknown>")
+
+        name, txmbr = self._getTxmbr(h)
+        if txmbr is None:
+            package_name = name
         else:
-            pkgtup = self._dopkgtup(hdr)
-            txmbrs = self.base.tsInfo.getMembers(pkgtup=pkgtup)
+            package_name = txmbr.po
             
-        for pkg in txmbrs:
-            # "bytes" carries the failed scriptlet tag,
-            # "total" carries fatal/non-fatal status
-            scriptlet_name = rpm.tagnames.get(bytes, "<unknown>")
-            if remove_hdr:
-                package_name = pkg
-            else:
-                package_name = pkg.po
-                
-            if total:
-                msg = ("Error in %s scriptlet in rpm package %s" % 
-                        (scriptlet_name, package_name))
-                if not remove_hdr:        
-                    pkg.output_state = TS_FAILED
-            else:
-                msg = ("Non-fatal %s scriptlet failure in rpm package %s" % 
-                       (scriptlet_name, package_name))
-            self.display.errorlog(msg)
-            # FIXME - what else should we do here? raise a failure and abort?
+        if total:
+            msg = ("Error in %s scriptlet in rpm package %s" % 
+                    (scriptlet_name, package_name))
+            if txmbr is not None:        
+                txmbr.output_state = TS_FAILED
+        else:
+            msg = ("Non-fatal %s scriptlet failure in rpm package %s" % 
+                   (scriptlet_name, package_name))
+        self.display.errorlog(msg)
+        # FIXME - what else should we do here? raise a failure and abort?
     
commit b7b5fda8079f4357fadd71c4fa58f31e5049bdbd
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Fri Feb 25 11:09:46 2011 +0200

    Eliminate linear search for package names in callback
    
    We only care if the name has been seen so a set works for the
    purpose just as well and is faster.

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 30c9dd3..ecb1129 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -178,7 +178,7 @@ class RPMTransaction:
         self.total_actions = 0
         self.total_installed = 0
         self.complete_actions = 0
-        self.installed_pkg_names = []
+        self.installed_pkg_names = set()
         self.total_removed = 0
         self.logger = logging.getLogger('yum.filelogging.RPMInstallCallback')
         self.filelog = False
@@ -426,7 +426,7 @@ class RPMTransaction:
                 if self.trans_running:
                     self.total_installed += 1
                     self.complete_actions += 1
-                    self.installed_pkg_names.append(hdr['name'])
+                    self.installed_pkg_names.add([hdr['name']])
                 return self.fd.fileno()
         else:
             self.display.errorlog("Error: No Header to INST_OPEN_FILE")
commit 1dd3de9f7cd871444d0a0f2a29b6c41da2dccecf
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Thu Feb 24 09:16:33 2011 +0200

    Remove unnecessary "magic number" test
    
    RPMCALLBACK_TRANS_START is only issued once. That "bytes" happens
    to be a magic value of 6 is just an artifact of truly ancient rpm
    versions from last century issuing RPMCALLBACK_TRANS_START more than once.

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index 06b484a..30c9dd3 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -402,11 +402,10 @@ class RPMTransaction:
     
     
     def _transStart(self, bytes, total, h):
-        if bytes == 6:
-            self.total_actions = total
-            if self.test: return
-            self.trans_running = True
-            self.ts_all() # write out what transaction will do
+        self.total_actions = total
+        if self.test: return
+        self.trans_running = True
+        self.ts_all() # write out what transaction will do
 
     def _transProgress(self, bytes, total, h):
         pass
commit d9cc803c7b7f2f6ad4ec5b33acbf17435af86051
Author: Panu Matilainen <pmatilai at laiskiainen.org>
Date:   Thu Feb 24 08:57:32 2011 +0200

    Simplify callback file open/close
    
    There's never more than one active file descriptor at a time so
    no need to collect them to a dict, remove now unneeded _makeHandle().
    Also use a python file object and return its .fileno() instead of
    the lowlevel os-routines.

diff --git a/yum/rpmtrans.py b/yum/rpmtrans.py
index d479829..06b484a 100644
--- a/yum/rpmtrans.py
+++ b/yum/rpmtrans.py
@@ -174,7 +174,7 @@ class RPMTransaction:
         self.base = base # base yum object b/c we need so much
         self.test = test # are we a test?
         self.trans_running = False
-        self.filehandles = {}
+        self.fd = None
         self.total_actions = 0
         self.total_installed = 0
         self.complete_actions = 0
@@ -254,12 +254,6 @@ class RPMTransaction:
 
         return (hdr['name'], hdr['arch'], epoch, hdr['version'], hdr['release'])
 
-    def _makeHandle(self, hdr):
-        handle = '%s:%s.%s-%s-%s' % (hdr['epoch'], hdr['name'], hdr['version'],
-          hdr['release'], hdr['arch'])
-
-        return handle
-    
     def ts_done(self, package, action):
         """writes out the portions of the transaction which have completed"""
         
@@ -425,18 +419,16 @@ class RPMTransaction:
         hdr = None
         if h is not None:
             hdr, rpmloc = h[0], h[1]
-            handle = self._makeHandle(hdr)
             try:
-                fd = os.open(rpmloc, os.O_RDONLY)
-            except OSError, e:
+                self.fd = file(rpmloc)
+            except IOError, e:
                 self.display.errorlog("Error: Cannot open file %s: %s" % (rpmloc, e))
             else:
-                self.filehandles[handle]=fd
                 if self.trans_running:
                     self.total_installed += 1
                     self.complete_actions += 1
                     self.installed_pkg_names.append(hdr['name'])
-                return fd
+                return self.fd.fileno()
         else:
             self.display.errorlog("Error: No Header to INST_OPEN_FILE")
             
@@ -444,9 +436,8 @@ class RPMTransaction:
         hdr = None
         if h is not None:
             hdr, rpmloc = h[0], h[1]
-            handle = self._makeHandle(hdr)
-            os.close(self.filehandles[handle])
-            fd = 0
+            self.fd.close()
+            self.fd = None
             if self.test: return
             if self.trans_running:
                 pkgtup = self._dopkgtup(hdr)


More information about the Yum-commits mailing list