From: Zac Medico Date: Sat, 8 Jun 2013 20:45:25 +0000 (-0700) Subject: emerge_main: hold large objects in emerge_config X-Git-Tag: v2.2.0_alpha179~2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=8ee7bafff1c81d129f1a4392b4df7c5ded05c1bc;p=portage.git emerge_main: hold large objects in emerge_config This allows emerge_main to avoid having direct local references to large local objects (like "settings" and "trees"), making it easier to ensure that stale objects can be garbage collected when other functions refresh the config with calls to load_emerge_config(). This will be much more flexible than the "gc_locals" approach that was introduce in commit e9fd283aedf54e2effc73f4157524fe9a26993c0. --- diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py index 1629d9280..c7139d4c3 100644 --- a/pym/_emerge/actions.py +++ b/pym/_emerge/actions.py @@ -55,6 +55,7 @@ from portage._sets.base import InternalPackageSet from portage.util import cmp_sort_key, writemsg, varexpand, \ writemsg_level, writemsg_stdout from portage.util.digraph import digraph +from portage.util.SlotObject import SlotObject from portage.util._async.run_main_scheduler import run_main_scheduler from portage.util._async.SchedulerInterface import SchedulerInterface from portage.util._eventloop.global_event_loop import global_event_loop @@ -3128,25 +3129,49 @@ def git_sync_timestamps(portdb, portdir): return os.EX_OK -def load_emerge_config(trees=None): +class _emerge_config(SlotObject): + + __slots__ = ('action', 'args', 'mtimedb', 'opts', 'settings', 'trees') + + # Support unpack as tuple, for load_emerge_config backward compatibility. + def __getitem__(self, index): + if index == 0: + return self.settings + elif index == 1: + return self.trees + elif index == 2: + return self.mtimedb + raise IndexError(index) + + def __len__(self): + return 3 + +def load_emerge_config(emerge_config=None, **kargs): + + if emerge_config is None: + emerge_config = _emerge_config(**kargs) + kwargs = {} for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")): v = os.environ.get(envvar, None) if v and v.strip(): kwargs[k] = v - trees = portage.create_trees(trees=trees, **portage._native_kwargs(kwargs)) + emerge_config.trees = portage.create_trees(trees=emerge_config.trees, + **portage._native_kwargs(kwargs)) - for root_trees in trees.values(): + for root_trees in emerge_config.trees.values(): settings = root_trees["vartree"].settings settings._init_dirs() setconfig = load_default_config(settings, root_trees) root_trees["root_config"] = RootConfig(settings, root_trees, setconfig) - settings = trees[trees._target_eroot]['vartree'].settings - mtimedbfile = os.path.join(settings['EROOT'], portage.CACHE_PATH, "mtimedb") - mtimedb = portage.MtimeDB(mtimedbfile) - QueryCommand._db = trees - return settings, trees, mtimedb + target_eroot = emerge_config.trees._target_eroot + emerge_config.settings = emerge_config.trees[target_eroot]['vartree'].settings + emerge_config.mtimedb = portage.MtimeDB( + os.path.join(target_eroot, portage.CACHE_PATH, "mtimedb")) + QueryCommand._db = emerge_config.trees + + return emerge_config def getgccversion(chost): """ @@ -3506,14 +3531,14 @@ def repo_name_duplicate_check(trees): return bool(ignored_repos) -def run_action(settings, trees, mtimedb, myaction, myopts, myfiles, - gc_locals=None): +def run_action(emerge_config): - # The caller may have its local variables garbage collected, so - # they don't consume any memory during this long-running function. - if gc_locals is not None: - gc_locals() - gc_locals = None + myaction = emerge_config.action + myfiles = emerge_config.args + mtimedb = emerge_config.mtimedb + myopts = emerge_config.opts + settings = emerge_config.settings + trees = emerge_config.trees # skip global updates prior to sync, since it's called after sync if myaction not in ('help', 'info', 'sync', 'version') and \ @@ -3521,7 +3546,8 @@ def run_action(settings, trees, mtimedb, myaction, myopts, myfiles, _global_updates(trees, mtimedb["updates"], quiet=("--quiet" in myopts)): mtimedb.commit() # Reload the whole config from scratch. - settings, trees, mtimedb = load_emerge_config(trees=trees) + settings, trees, mtimedb = \ + load_emerge_config(emerge_config=emerge_config) xterm_titles = "notitles" not in settings.features if xterm_titles: @@ -3531,7 +3557,8 @@ def run_action(settings, trees, mtimedb, myaction, myopts, myfiles, os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest" # Reload the whole config from scratch so that the portdbapi internal # config is updated with new FEATURES. - settings, trees, mtimedb = load_emerge_config(trees=trees) + settings, trees, mtimedb = \ + load_emerge_config(emerge_config=emerge_config) # NOTE: adjust_configs() can map options to FEATURES, so any relevant # options adjustments should be made prior to calling adjust_configs(). diff --git a/pym/_emerge/main.py b/pym/_emerge/main.py index e066c8700..4b9af7ca8 100644 --- a/pym/_emerge/main.py +++ b/pym/_emerge/main.py @@ -1041,17 +1041,18 @@ def emerge_main(args=None): os.umask(0o22) if myaction == "sync": portage._sync_disabled_warnings = True - settings, trees, mtimedb = load_emerge_config() - rval = profile_check(trees, myaction) + emerge_config = load_emerge_config( + action=myaction, args=myfiles, opts=myopts) + rval = profile_check(emerge_config.trees, emerge_config.action) if rval != os.EX_OK: return rval tmpcmdline = [] if "--ignore-default-opts" not in myopts: tmpcmdline.extend(portage.util.shlex_split( - settings.get("EMERGE_DEFAULT_OPTS", ""))) + emerge_config.settings.get("EMERGE_DEFAULT_OPTS", ""))) tmpcmdline.extend(args) - myaction, myopts, myfiles = parse_opts(tmpcmdline) + emerge_config.action, emerge_config.opts, emerge_config.args = \ + parse_opts(tmpcmdline) - return run_action(settings, trees, mtimedb, myaction, myopts, myfiles, - gc_locals=locals().clear) + return run_action(emerge_config)