[Yum-devel] [PATCH 3/9] Cache checkFileRequires data

James Antill james at and.org
Sun Nov 8 20:26:37 UTC 2009


---
 yum/depsolve.py |   73 +++++++++++++++++++++--------
 yum/rpmsack.py  |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+), 20 deletions(-)

diff --git a/yum/depsolve.py b/yum/depsolve.py
index 7871e98..4b35cec 100644
--- a/yum/depsolve.py
+++ b/yum/depsolve.py
@@ -923,26 +923,21 @@ class Depsolve(object):
 
         # generate list of file requirement in rpmdb
         if self.installedFileRequires is None:
-            self.installedFileRequires = {}
-            self.installedUnresolvedFileRequires = set()
-            resolved = set()
-            for pkg in self.rpmdb.returnPackages():
-                for name, flag, evr in pkg.requires:
-                    if not name.startswith('/'):
-                        continue
-                    self.installedFileRequires.setdefault(pkg, []).append(name)
-                    if name not in resolved:
-                        dep = self.rpmdb.getProvides(name, flag, evr)
-                        resolved.add(name)
-                        if not dep:
-                            self.installedUnresolvedFileRequires.add(name)
+            self.installedFileRequires, \
+              self.installedUnresolvedFileRequires, \
+              self.installedFileProviders = self.rpmdb._get_file_requires()
 
         # get file requirements from packages not deleted
-        for po, files in self.installedFileRequires.iteritems():
-            if not self._tsInfo.getMembersWithState(po.pkgtup, output_states=TS_REMOVE_STATES):
+        todel = []
+        for pkgtup, files in self.installedFileRequires.iteritems():
+            if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
+                todel.append(pkgtup)
+            else:
                 fileRequires.update(files)
                 for filename in files:
-                    reverselookup.setdefault(filename, []).append(po)
+                    reverselookup.setdefault(filename, []).append(pkgtup)
+        for pkgtup in todel:
+            del self.installedFileRequires[pkgtup]
 
         fileRequires -= self.installedUnresolvedFileRequires
 
@@ -950,6 +945,8 @@ class Depsolve(object):
         for txmbr in self._tsInfo.getMembersWithState(output_states=TS_INSTALL_STATES):
             for name, flag, evr in txmbr.po.requires:
                 if name.startswith('/'):
+                    pt = txmbr.po.pkgtup
+                    self.installedFileRequires.setdefault(pt, []).append(name)
                     # check if file requires was already unresolved in update
                     if name in self.installedUnresolvedFileRequires:
                         already_broken = False
@@ -960,13 +957,49 @@ class Depsolve(object):
                         if already_broken:
                             continue
                     fileRequires.add(name)
-                    reverselookup.setdefault(name, []).append(txmbr.po)
+                    reverselookup.setdefault(name, []).append(txmbr.po.pkgtup)
+
+        todel = []
+        for fname in self.installedFileProviders:
+            niFP_fname = []
+            for pkgtup in self.installedFileProviders[fname]:
+                if self._tsInfo.getMembersWithState(pkgtup, output_states=TS_REMOVE_STATES):
+                    continue
+                niFP_fname.append(pkgtup)
+
+            if not niFP_fname:
+                todel.append(fname)
+                continue
+
+            self.installedFileProviders[fname] = niFP_fname
+        for fname in todel:
+            del self.installedFileProviders[fname]
 
         # check the file requires
         for filename in fileRequires:
-            if not self.tsInfo.getOldProvides(filename) and not self.tsInfo.getNewProvides(filename):
-                for po in reverselookup[filename]:
-                    ret.append( (po, (filename, 0, '')) )
+            nprov = self.tsInfo.getNewProvides(filename)
+            if nprov:
+                pkgtups = [po.pkgtup for po in nprov]
+                self.installedFileProviders[filename] = pkgtups
+                continue
+
+            if filename in self.installedFileProviders:
+                continue 
+
+            oprov = self.tsInfo.getOldProvides(filename)
+            if oprov:
+                pkgtups = [po.pkgtup for po in oprov]
+                self.installedFileProviders[filename] = pkgtups
+                continue
+
+            for pkgtup in reverselookup[filename]:
+                po = self.getInstalledPackageObject(pkgtup)
+                ret.append( (po, (filename, 0, '')) )
+
+        self.rpmdb._write_file_requires(self.installedFileRequires, 
+                                        self.installedUnresolvedFileRequires,
+                                        self.installedFileProviders,
+                                        ret)
 
         return ret
 
diff --git a/yum/rpmsack.py b/yum/rpmsack.py
index b0f2094..6d2a831 100644
--- a/yum/rpmsack.py
+++ b/yum/rpmsack.py
@@ -114,6 +114,7 @@ class RPMDBPackageSack(PackageSackBase):
             cachedir = misc.getCacheDir()
         self._cachedir = cachedir + "/rpmdb-cache/"
         self._have_cached_rpmdbv_data = None
+        self._use_cached_file_requires = True
         self.ts = None
         self.auto_close = False # this forces a self.ts.close() after
                                      # most operations so it doesn't leave
@@ -384,6 +385,141 @@ class RPMDBPackageSack(PackageSackBase):
             ret.append(self._makePackageObject(hdr, mi.instance()))
         return ret
 
+    def _read_file_requires(self):
+        def _read_str(fo):
+            return fo.readline()[:-1]
+
+        assert self.__cache_rpmdb__
+        if not os.path.exists(self._cachedir + '/file-requires'):
+            return None, None
+
+        rpmdbv = self.simpleVersion(main_only=True)[0]
+        fo = open(self._cachedir + '/file-requires')
+        frpmdbv = fo.readline()
+        if not frpmdbv or rpmdbv != frpmdbv[:-1]:
+            return None, None
+
+        iFR = {}
+        iFP = {}
+        try:
+            # Read the requires...
+            pkgtups_num = int(_read_str(fo))
+            while pkgtups_num > 0:
+                pkgtups_num -= 1
+
+                # n, a, e, v, r
+                pkgtup = (_read_str(fo), _read_str(fo),
+                          _read_str(fo), _read_str(fo), _read_str(fo))
+                int(pkgtup[2]) # Check epoch is valid
+
+                files_num = int(_read_str(fo))
+                while files_num > 0:
+                    files_num -= 1
+
+                    fname = _read_str(fo)
+
+                    iFR.setdefault(pkgtup, []).append(fname)
+
+            # Read the provides...
+            files_num = int(_read_str(fo))
+            while files_num > 0:
+                files_num -= 1
+                fname = _read_str(fo)
+                pkgtups_num = int(_read_str(fo))
+                while pkgtups_num > 0:
+                    pkgtups_num -= 1
+
+                    # n, a, e, v, r
+                    pkgtup = (_read_str(fo), _read_str(fo),
+                              _read_str(fo), _read_str(fo), _read_str(fo))
+                    int(pkgtup[2]) # Check epoch is valid
+
+                    iFP.setdefault(fname, []).append(pkgtup)
+
+            if fo.readline() != '': # Should be EOF
+                return None, None
+        except ValueError:
+            return None, None
+
+        return iFR, iFP
+
+    def _get_file_requires(self):
+        print "JDBG:", 'BEG: _all_file_requires', self._use_cached_file_requires
+        if self.__cache_rpmdb__ and self._use_cached_file_requires:
+            iFR, iFP = self._read_file_requires()
+            if iFR is not None:
+                print "JDBG:", 'CACHE'
+                return iFR, set(), iFP
+
+        print "JDBG:", '** no CACHE'
+        installedFileRequires = {}
+        installedUnresolvedFileRequires = set()
+        resolved = set()
+        for pkg in self.returnPackages():
+            for name, flag, evr in pkg.requires:
+                if not name.startswith('/'):
+                    continue
+                installedFileRequires.setdefault(pkg.pkgtup, []).append(name)
+                if name not in resolved:
+                    dep = self.getProvides(name, flag, evr)
+                    resolved.add(name)
+                    if not dep:
+                        installedUnresolvedFileRequires.add(name)
+
+        if self.__cache_rpmdb__:
+            self._write_file_requires(installedFileRequires,
+                                      installedUnresolvedFileRequires,
+                                      {}, [])
+            self._rename_file_requires(self.simpleVersion(main_only=True)[0])
+        return installedFileRequires, installedUnresolvedFileRequires, {}
+
+    def _write_file_requires(self, installedFileRequires,
+                             installedUnresolvedFileRequires,
+                             installedFileProvides,
+                             problems):
+        if not self.__cache_rpmdb__:
+            return
+
+        if not self._use_cached_file_requires:
+            return
+        if installedUnresolvedFileRequires or problems:
+            return
+        # FIXME: ... real tmp. file
+        fo = open(self._cachedir + '/file-requires.un.tmp', 'w')
+        fo.write("%u\n" % len(installedFileRequires))
+        for pkgtup in sorted(installedFileRequires):
+            for var in pkgtup:
+                fo.write("%s\n" % var)
+            filenames = set(installedFileRequires[pkgtup])
+            fo.write("%u\n" % len(filenames))
+            for fname in sorted(filenames):
+                fo.write("%s\n" % fname)
+
+        fo.write("%u\n" % len(installedFileProvides))
+        for fname in sorted(installedFileProvides):
+            fo.write("%s\n" % fname)
+
+            pkgtups = set(installedFileProvides[fname])
+            fo.write("%u\n" % len(pkgtups))
+            for pkgtup in sorted(pkgtups):
+                for var in pkgtup:
+                    fo.write("%s\n" % var)
+        fo.close()
+
+    def _rename_file_requires(self, rpmdbversion):
+        if not os.path.exists(self._cachedir + '/file-requires.un.tmp'):
+            return
+
+        rfo = open(self._cachedir + '/file-requires.un.tmp')
+        wfo = open(self._cachedir + '/file-requires.tmp', 'w')
+        wfo.write("%s\n" % rpmdbversion)
+        wfo.write(rfo.read())
+        rfo.close()
+        wfo.close()
+        os.rename(self._cachedir + '/file-requires.tmp',
+                  self._cachedir + '/file-requires')
+        os.unlink(self._cachedir + '/file-requires.un.tmp')
+
     def _get_cached_simpleVersion_main(self):
         """ Return the cached string of the main rpmdbv. """
         if self._have_cached_rpmdbv_data is not None:
-- 
1.6.2.5



More information about the Yum-devel mailing list