Optimize dblink.isowner() to use fewer stat calls by doing a basename
authorZac Medico <zmedico@gentoo.org>
Thu, 21 Feb 2008 08:04:33 +0000 (08:04 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 21 Feb 2008 08:04:33 +0000 (08:04 -0000)
comparison to try and eliminate the file before resorting to inode
comparison. This speeds up the `portageq owners` command as well as
the search that is done when collision-protect finds a collision.

svn path=/main/trunk/; revision=9363

pym/portage/dbapi/vartree.py

index b85976931008989e868040c54a05b891574449f8..5d7b0586f4e7f08ba5481f5ecb13f147cc873c7b 100644 (file)
@@ -911,6 +911,7 @@ class dblink(object):
                self._installed_instance = None
                self.contentscache = None
                self._contents_inodes = None
+               self._contents_basenames = None
 
        def lockdb(self):
                if self._lock_vdb:
@@ -1512,6 +1513,16 @@ class dblink(object):
                if pkgfiles and destfile in pkgfiles:
                        return True
                if pkgfiles:
+                       basename = os.path.basename(destfile)
+                       if self._contents_basenames is None:
+                               self._contents_basenames = set(
+                                       os.path.basename(x) for x in pkgfiles)
+                       if basename not in self._contents_basenames:
+                               # This is a shortcut that, in most cases, allows us to
+                               # eliminate this package as an owner without the need
+                               # to examine inode numbers of parent directories.
+                               return False
+
                        # Use stat rather than lstat since we want to follow
                        # any symlinks to the real parent directory.
                        parent_path = os.path.dirname(destfile)
@@ -1547,7 +1558,6 @@ class dblink(object):
                        p_path_list = self._contents_inodes.get(
                                (parent_stat.st_dev, parent_stat.st_ino))
                        if p_path_list:
-                               basename = os.path.basename(destfile)
                                for p_path in p_path_list:
                                        x = os.path.join(p_path, basename)
                                        if x in pkgfiles:
@@ -2103,6 +2113,7 @@ class dblink(object):
                for dblnk in others_in_slot:
                        dblnk.contentscache = None
                        dblnk._contents_inodes = None
+                       dblnk._contents_basenames = None
 
                # If portage is reinstalling itself, remove the old
                # version now since we want to use the temporary