From 16cd42f25994f53359679c0fbc02474259815ffc Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Mon, 6 Sep 2010 00:04:12 -0700 Subject: Make depgraph.schedulerGraph() return an instance of _scheduler_graph_config instead of just a digraph. This new object includes instances of FakeVartree and a package cache that is pruned to contain only installed packages or those in the digraph. --- pym/_emerge/Scheduler.py | 50 ++++++++++++++++++++++++------------------------ pym/_emerge/depgraph.py | 24 ++++++++++++++++++++++- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index e94b0461b..400ce1940 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -137,7 +137,7 @@ class Scheduler(PollScheduler): portage.exception.PortageException.__init__(self, value) def __init__(self, settings, trees, mtimedb, myopts, - spinner, mergelist, favorites, digraph): + spinner, mergelist, favorites, graph_config): PollScheduler.__init__(self) self.settings = settings self.target_root = settings["ROOT"] @@ -203,8 +203,6 @@ class Scheduler(PollScheduler): for root in self.trees: self._config_pool[root] = [] - self._init_installed_graph() - fetch_iface = self._fetch_iface_class(log_file=self._fetch_log, schedule=self._schedule_fetch) self._sched_iface = self._iface_class( @@ -244,7 +242,7 @@ class Scheduler(PollScheduler): self._job_delay_exp = 1.5 self._previous_job_start_time = None - self._set_digraph(digraph) + self._init_graph(graph_config) # This is used to memoize the _choose_pkg() result when # no packages can be chosen until one of the existing @@ -283,7 +281,7 @@ class Scheduler(PollScheduler): self._running_portage = self._pkg(cpv, "installed", self._running_root, installed=True) - def _init_installed_graph(self): + def _init_graph(self, graph_config): """ Initialization structures used for dependency calculations involving currently installed packages. @@ -292,20 +290,24 @@ class Scheduler(PollScheduler): # that's updated incrementally with each upgrade/uninstall operation # This will be useful for making quick and safe decisions with respect # to aggressive parallelization discussed in bug #279623. + self._set_graph_config(graph_config) self._blocker_db = {} for root in self.trees: - self._blocker_db[root] = \ - BlockerDB(FakeVartree(self.trees[root]["root_config"])) + if graph_config is None: + fake_vartree = FakeVartree(self.trees[root]["root_config"]) + else: + fake_vartree = graph_config.trees[root]['vartree'] + self._blocker_db[root] = BlockerDB(fake_vartree) - def _destroy_installed_graph(self): + def _destroy_graph(self): """ - Use this to free memory before calling _calc_resume_list(). - After _calc_resume_list(), the _init_installed_graph() and - _set_digraph() methods need to be called in order to - re-generate the structures that this method destroys. + Use this to free memory at the beginning of _calc_resume_list(). + After _calc_resume_list(), the _init_graph() method + must to be called in order to re-generate the structures that + this method destroys. """ self._blocker_db = None - self._set_digraph(None) + self._set_graph_config(None) gc.collect() def _poll(self, timeout=None): @@ -374,15 +376,17 @@ class Scheduler(PollScheduler): interactive_tasks.append(task) return interactive_tasks - def _set_digraph(self, digraph): + def _set_graph_config(self, graph_config): if "--nodeps" in self.myopts or \ - digraph is None or \ + graph_config is None or \ (self._max_jobs is not True and self._max_jobs < 2): # save some memory + self._graph_config = None self._digraph = None return - self._digraph = digraph + self._graph_config = graph_config + self._digraph = graph_config.graph self._find_system_deps() self._prune_digraph() self._prevent_builddir_collisions() @@ -1078,10 +1082,6 @@ class Scheduler(PollScheduler): if not mergelist: break - # free some memory before creating - # the resume depgraph - self._destroy_installed_graph() - if not self._calc_resume_list(): break @@ -1089,10 +1089,6 @@ class Scheduler(PollScheduler): if not self._mergelist: break - # Initialize the installed graph again - # since it was destroyed above in order - # to free memory. - self._init_installed_graph() self._save_resume_list() self._pkg_count.curval = 0 self._pkg_count.maxval = len([x for x in self._mergelist \ @@ -1734,6 +1730,10 @@ class Scheduler(PollScheduler): """ print(colorize("GOOD", "*** Resuming merge...")) + # free some memory before creating + # the resume depgraph + self._destroy_graph() + myparams = create_depgraph_params(self.myopts, None) success = False e = None @@ -1799,7 +1799,7 @@ class Scheduler(PollScheduler): mydepgraph.break_refs(mylist) mydepgraph.break_refs(dropped_tasks) self._mergelist = mylist - self._set_digraph(mydepgraph.schedulerGraph()) + self._init_graph(mydepgraph.schedulerGraph()) msg_width = 75 for task in dropped_tasks: diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 3230d9a73..2a4d6eecd 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -63,6 +63,12 @@ if sys.hexversion >= 0x3000000: basestring = str long = int +class _scheduler_graph_config(object): + def __init__(self, trees, pkg_cache, graph): + self.trees = trees + self.pkg_cache = pkg_cache + self.graph = graph + class _frozen_depgraph_config(object): def __init__(self, settings, trees, myopts, spinner): @@ -3486,7 +3492,23 @@ class depgraph(object): if priority.satisfied: priority.satisfied = True - return self._dynamic_config._scheduler_graph + pkg_cache = self._frozen_config._pkg_cache + graph = self._dynamic_config._scheduler_graph + trees = self._frozen_config.trees + pruned_pkg_cache = {} + for pkg in pkg_cache: + if pkg in graph or \ + (pkg.installed and pkg in trees[pkg.root]['vartree'].dbapi): + pruned_pkg_cache[pkg] = pkg + + for root in trees: + trees[root]['vartree']._pkg_cache = pruned_pkg_cache + + self.break_refs(pruned_pkg_cache) + sched_config = \ + _scheduler_graph_config(trees, pruned_pkg_cache, graph) + + return sched_config def break_refs(self, nodes): """ -- cgit v1.2.3-1-g7c22