LinkageMapELF: add getOwners() method and use it
authorZac Medico <zmedico@gentoo.org>
Fri, 22 Jul 2011 22:59:13 +0000 (15:59 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 22 Jul 2011 22:59:13 +0000 (15:59 -0700)
This preserves the owner information inside LinkageMap.rebuild() and
uses it to implement a getOwners() method, which makes it possible to
efficiently lookup owners of library providers and consumers.

pym/_emerge/actions.py
pym/_emerge/main.py
pym/portage/_sets/libs.py
pym/portage/util/_dyn_libs/LinkageMapELF.py

index 219ed7101a2f638e76312b0d7f6b9ffeebc02cff..610fc73d12401c74f67b9ee2632afe1420ee5ddd 100644 (file)
@@ -992,7 +992,15 @@ def calc_depclean(settings, trees, ldpath_mtimes,
                                                search_files.update(providers)
 
                        writemsg_level(">>> Assigning files to packages...\n")
-                       file_owners = real_vardb._owners.getFileOwnerMap(search_files)
+                       file_owners = {}
+                       for f in search_files:
+                               owner_set = set()
+                               for owner in linkmap.getOwners(f):
+                                       owner_dblink = real_vardb._dblink(owner)
+                                       if owner_dblink.exists():
+                                               owner_set.add(owner_dblink)
+                               if owner_set:
+                                       file_owners[f] = owner_set
 
                        for pkg, consumers in list(consumer_map.items()):
                                for lib, consumer_providers in list(consumers.items()):
index 11a33149d87580001d592c3ca960656173f6d015..28431c58fc67fa1a4334c551faf562541755b3b0 100644 (file)
@@ -260,7 +260,15 @@ def display_preserved_libs(vardbapi, myopts):
                                        consumer_map[f] = consumers
                                        search_for_owners.update(consumers[:MAX_DISPLAY+1])
 
-                       owners = vardbapi._owners.getFileOwnerMap(search_for_owners)
+                       owners = {}
+                       for f in search_for_owners:
+                               owner_set = set()
+                               for owner in linkmap.getOwners(f):
+                                       owner_dblink = vardbapi._dblink(owner)
+                                       if owner_dblink.exists():
+                                               owner_set.add(owner_dblink)
+                               if owner_set:
+                                       owners[f] = owner_set
 
                for cpv in plibdata:
                        print(colorize("WARN", ">>>") + " package: %s" % cpv)
index 20347e4520aceb7a30f1880df1bbf10415a02a64..3543b8d15aecfe3063d066480a35c07bf3000b47 100644 (file)
@@ -19,10 +19,12 @@ class LibraryConsumerSet(PackageSet):
 
        def mapPathsToAtoms(self, paths):
                rValue = set()
-               for link, p in self.dbapi._owners.iter_owners(paths):
-                       cat, pn = catpkgsplit(link.mycpv)[:2]
-                       slot = self.dbapi.aux_get(link.mycpv, ["SLOT"])[0]
-                       rValue.add("%s/%s:%s" % (cat, pn, slot))
+               for p in paths:
+                       owners = self.dbapi._linkmap.getOwners(p)
+                       for cpv in owners:
+                               cat, pn = catpkgsplit(cpv)[:2]
+                               slot, = self.dbapi.aux_get(cpv, ["SLOT"])
+                               rValue.add("%s/%s:%s" % (cat, pn, slot))
                return rValue
 
 class LibraryFileConsumerSet(LibraryConsumerSet):
index 90d43e7ec0d38bbd0aad7e8ed0d3925f2bf45088..c3c07064836f27254f2463bff1640ee2c934e80c 100644 (file)
@@ -28,14 +28,16 @@ class LinkageMapELF(object):
 
        class _obj_properies_class(object):
 
-               __slots__ = ("arch", "needed", "runpaths", "soname", "alt_paths",)
+               __slots__ = ("arch", "needed", "runpaths", "soname", "alt_paths",
+                       "owner",)
 
-               def __init__(self, arch, needed, runpaths, soname, alt_paths):
+               def __init__(self, arch, needed, runpaths, soname, alt_paths, owner):
                        self.arch = arch
                        self.needed = needed
                        self.runpaths = runpaths
                        self.soname = soname
                        self.alt_paths = alt_paths
+                       self.owner = owner
 
                def __iter__(self):
                        """Backward compatibility with 5-tuples."""
@@ -204,7 +206,7 @@ class LinkageMapELF(object):
                # overrides any data from previously installed files.
                if include_file is not None:
                        for line in grabfile(include_file):
-                               lines.append((include_file, line))
+                               lines.append((None, include_file, line))
 
                aux_keys = [self._needed_aux_key]
                can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK)
@@ -217,16 +219,16 @@ class LinkageMapELF(object):
                                needed_file = self._dbapi.getpath(cpv,
                                        filename=self._needed_aux_key)
                                for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines():
-                                       lines.append((needed_file, line))
+                                       lines.append((cpv, needed_file, line))
                finally:
                        if can_lock:
                                self._dbapi.unlock()
 
                # have to call scanelf for preserved libs here as they aren't 
                # registered in NEEDED.ELF.2 files
-               plibs = set()
+               plibs = {}
                if preserve_paths is not None:
-                       plibs.update(preserve_paths)
+                       plibs.update((x, None) for x in preserve_paths)
                if self._dbapi._plib_registry and \
                        self._dbapi._plib_registry.hasEntries():
                        for cpv, items in \
@@ -238,7 +240,7 @@ class LinkageMapELF(object):
                                        # already represented via the preserve_paths
                                        # parameter.
                                        continue
-                               plibs.update(items)
+                               plibs.update((x, cpv) for x in items)
                if plibs:
                        args = ["/usr/bin/scanelf", "-qF", "%a;%F;%S;%r;%n"]
                        args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
@@ -270,8 +272,8 @@ class LinkageMapELF(object):
                                                        level=logging.ERROR, noiselevel=-1)
                                                continue
                                        fields[1] = fields[1][root_len:]
-                                       plibs.discard(fields[1])
-                                       lines.append(("scanelf", ";".join(fields)))
+                                       owner = plibs.pop(fields[1], None)
+                                       lines.append((owner, "scanelf", ";".join(fields)))
                                proc.wait()
 
                if plibs:
@@ -281,14 +283,14 @@ class LinkageMapELF(object):
                        # preserved library has an entry in self._obj_properties. This
                        # is important in order to prevent findConsumers from raising
                        # an unwanted KeyError.
-                       for x in plibs:
-                               lines.append(("plibs", ";".join(['', x, '', '', ''])))
+                       for cpv, x in plibs.items():
+                               lines.append((cpv, "plibs", ";".join(['', x, '', '', ''])))
 
                # Share identical frozenset instances when available,
                # in order to conserve memory.
                frozensets = {}
 
-               for location, l in lines:
+               for owner, location, l in lines:
                        l = l.rstrip("\n")
                        if not l:
                                continue
@@ -315,7 +317,7 @@ class LinkageMapELF(object):
                        if myprops is None:
                                indexed = False
                                myprops = self._obj_properies_class(
-                                       arch, needed, path, soname, [])
+                                       arch, needed, path, soname, [], owner)
                                obj_properties[obj_key] = myprops
                        # All object paths are added into the obj_properties tuple.
                        myprops.alt_paths.append(obj)
@@ -560,6 +562,32 @@ class LinkageMapELF(object):
                                        rValue.extend(self._obj_properties[obj_key].alt_paths)
                return rValue
 
+       def getOwners(self, obj):
+               """
+               Return the package(s) associated with an object. Raises KeyError
+               if the object is unknown. Returns an empty tuple if the owner(s)
+               are unknown.
+
+               @param obj: absolute path to an object
+               @type obj: string (example: '/usr/bin/bar')
+               @rtype: tuple
+               @return: a tuple of cpv
+               """
+               if not self._libs:
+                       self.rebuild()
+               if isinstance(obj, self._ObjectKey):
+                       obj_key = obj
+               else:
+                       obj_key = self._obj_key_cache.get(obj)
+                       if obj_key is None:
+                               raise KeyError("%s not in object list" % obj)
+               obj_props = self._obj_properties.get(obj_key)
+               if obj_props is None:
+                       raise KeyError("%s not in object list" % obj_key)
+               if obj_props.owner is None:
+                       return ()
+               return (obj_props.owner,)
+
        def getSoname(self, obj):
                """
                Return the soname associated with an object.