Let the BinaryPackageUnvierse track broken packages

Signed-off-by: Niels Thykier <niels@thykier.net>
This commit is contained in:
Niels Thykier 2018-11-01 07:12:36 +00:00
parent 8867ef0cf9
commit ef813bf0d8
No known key found for this signature in database
GPG Key ID: A65B78DBE67C7AAC
3 changed files with 30 additions and 13 deletions

View File

@ -308,11 +308,10 @@ class InstallabilityTesterBuilder(object):
relations, eqv_table = self._build_eqv_packages_table(package_table, reverse_package_table) relations, eqv_table = self._build_eqv_packages_table(package_table, reverse_package_table)
universe = BinaryPackageUniverse(relations, intern_set(self._essentials)) universe = BinaryPackageUniverse(relations, intern_set(self._essentials), intern_set(broken))
solver = InstallabilityTester(universe, solver = InstallabilityTester(universe,
self._testing, self._testing,
self._broken,
eqv_table) eqv_table)
return universe, solver return universe, solver

View File

@ -22,7 +22,7 @@ from britney2.utils import iter_except
class InstallabilityTester(object): class InstallabilityTester(object):
def __init__(self, universe, testing, broken, eqv_table): def __init__(self, universe, testing, eqv_table):
"""Create a new installability tester """Create a new installability tester
universe is a BinaryPackageUniverse universe is a BinaryPackageUniverse
@ -30,9 +30,6 @@ class InstallabilityTester(object):
testing is a (mutable) set of package ids that determines testing is a (mutable) set of package ids that determines
which of the packages in universe are currently in testing. which of the packages in universe are currently in testing.
broken is a (mutable) set of package ids that are known to
be uninstallable.
Package id: (pkg_name, pkg_version, pkg_arch) Package id: (pkg_name, pkg_version, pkg_arch)
- NB: arch:all packages are "re-mapped" to given architecture. - NB: arch:all packages are "re-mapped" to given architecture.
(simplifies caches and dependency checking) (simplifies caches and dependency checking)
@ -40,7 +37,6 @@ class InstallabilityTester(object):
self._universe = universe self._universe = universe
self._testing = testing self._testing = testing
self._broken = broken
self._eqv_table = eqv_table self._eqv_table = eqv_table
self._stats = InstallabilityStats() self._stats = InstallabilityStats()
logger_name = ".".join((self.__class__.__module__, self.__class__.__name__)) logger_name = ".".join((self.__class__.__module__, self.__class__.__name__))
@ -122,7 +118,7 @@ class InstallabilityTester(object):
if pkg_id not in self._universe: # pragma: no cover if pkg_id not in self._universe: # pragma: no cover
raise KeyError(str(pkg_id)) raise KeyError(str(pkg_id))
if pkg_id in self._broken: if pkg_id in self._universe.broken_packages:
self._testing.add(pkg_id) self._testing.add(pkg_id)
elif pkg_id not in self._testing: elif pkg_id not in self._testing:
self._testing.add(pkg_id) self._testing.add(pkg_id)
@ -162,7 +158,7 @@ class InstallabilityTester(object):
if not self._universe.reverse_dependencies_of(pkg_id): if not self._universe.reverse_dependencies_of(pkg_id):
# no reverse relations - safe # no reverse relations - safe
return True return True
if pkg_id not in self._broken and pkg_id in self._cache_inst: if pkg_id not in self._universe.broken_packages and pkg_id in self._cache_inst:
# It is in our cache (and not guaranteed to be broken) - throw out the cache # It is in our cache (and not guaranteed to be broken) - throw out the cache
self._cache_inst = set() self._cache_inst = set()
self._stats.cache_drops += 1 self._stats.cache_drops += 1
@ -185,7 +181,7 @@ class InstallabilityTester(object):
if pkg_id not in self._universe: # pragma: no cover if pkg_id not in self._universe: # pragma: no cover
raise KeyError(str(pkg_id)) raise KeyError(str(pkg_id))
if pkg_id not in self._testing or pkg_id in self._broken: if pkg_id not in self._testing or pkg_id in self._universe.broken_packages:
self._stats.cache_hits += 1 self._stats.cache_hits += 1
return False return False

View File

@ -36,11 +36,25 @@ class BinaryPackageUniverse(object):
Being immutable, the universe does *not* track stateful data such Being immutable, the universe does *not* track stateful data such
as "which package is in what suite?" nor "is this package installable as "which package is in what suite?" nor "is this package installable
in that suite?". in that suite?".
The universe also includes some packages that are considered "broken".
These packages have been identified to always be uninstallability
regardless of the selection of package available (e.g. the depend
on a non-existent package or has a relation that is impossible to
satisfy).
For these packages, the universe only tracks that they
exist and that they are broken. This implies that their relations
have been nulled into empty sets and they have been removed from
the relations of other packages. This optimizes analysis of the
universe on packages that is/can be installable at the expense
of a "minor" lie about the "broken" packages.
""" """
def __init__(self, relations, essential_packages): def __init__(self, relations, essential_packages, broken_packages):
self._relations = relations self._relations = relations
self._essential_packages = essential_packages self._essential_packages = essential_packages
self._broken_packages = broken_packages
def dependencies_of(self, pkg_id): def dependencies_of(self, pkg_id):
"""Returns the set of dependencies of a given package """Returns the set of dependencies of a given package
@ -96,8 +110,7 @@ class BinaryPackageUniverse(object):
:param pkg_id: The BinaryPackageId of a binary package. :param pkg_id: The BinaryPackageId of a binary package.
:return: A frozenset of all package ids that are equivalent to the :return: A frozenset of all package ids that are equivalent to the
input package. Note that this set always includes the input input package.
package assuming it is a known package.
""" """
return self._relations[pkg_id].pkg_ids return self._relations[pkg_id].pkg_ids
@ -119,6 +132,15 @@ class BinaryPackageUniverse(object):
""" """
return self._essential_packages return self._essential_packages
@property
def broken_packages(self):
"""A frozenset of all broken binaries in the universe
:return A frozenset of BinaryPackageIds of all binaries that are
considered "broken" and had their relations nulled.
"""
return self._broken_packages
def __contains__(self, pkg_id): def __contains__(self, pkg_id):
return pkg_id in self._relations return pkg_id in self._relations