From 9411ac7406c6e775998bf6055ca8f022acce9e25 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 10 Mar 2011 22:02:19 -0800 Subject: [PATCH] PollScheduler: tweek termination logic * PollScheduler and all subclasses now use the _terminated_tasks variable to check whether or not _terminate_tasks() has been called, and behave appropriately in that case. * The _schedule_tasks() method now has documentation about the relationship with _terminate_tasks() and _terminated_tasks. --- pym/_emerge/MetadataRegen.py | 15 ++++++++------- pym/_emerge/PollScheduler.py | 21 +++++++++++++++++++++ pym/_emerge/QueueScheduler.py | 3 +++ pym/_emerge/Scheduler.py | 8 ++++---- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pym/_emerge/MetadataRegen.py b/pym/_emerge/MetadataRegen.py index 45c4f4d29..810317533 100644 --- a/pym/_emerge/MetadataRegen.py +++ b/pym/_emerge/MetadataRegen.py @@ -44,7 +44,7 @@ class MetadataRegen(PollScheduler): portage.writemsg_stdout("Regenerating cache entries...\n") every_cp.sort(reverse=True) try: - while not self._terminated.is_set(): + while not self._terminated_tasks: yield every_cp.pop() except IndexError: pass @@ -56,13 +56,13 @@ class MetadataRegen(PollScheduler): consumer = self._consumer for cp in self._cp_iter: - if self._terminated.is_set(): + if self._terminated_tasks: break cp_set.add(cp) portage.writemsg_stdout("Processing %s\n" % cp) cpv_list = portdb.cp_list(cp) for cpv in cpv_list: - if self._terminated.is_set(): + if self._terminated_tasks: break valid_pkgs.add(cpv) ebuild_path, repo_path = portdb.findname2(cpv) @@ -94,7 +94,7 @@ class MetadataRegen(PollScheduler): while self._jobs: self._poll_loop() - if self._terminated.is_set(): + if self._terminated_tasks: self.returncode = 1 return @@ -145,9 +145,10 @@ class MetadataRegen(PollScheduler): @returns: True if there may be remaining tasks to schedule, False otherwise. """ + if self._terminated_tasks: + return False + while self._can_add_job(): - if self._terminated.is_set(): - return False try: metadata_process = next(self._process_iter) except StopIteration: @@ -167,7 +168,7 @@ class MetadataRegen(PollScheduler): self.returncode = 1 self._error_count += 1 self._valid_pkgs.discard(metadata_process.cpv) - if not self._terminated.is_set(): + if not self._terminated_tasks: portage.writemsg("Error processing %s, continuing...\n" % \ (metadata_process.cpv,), noiselevel=-1) diff --git a/pym/_emerge/PollScheduler.py b/pym/_emerge/PollScheduler.py index 94fd92407..8f4bd64b9 100644 --- a/pym/_emerge/PollScheduler.py +++ b/pym/_emerge/PollScheduler.py @@ -65,6 +65,24 @@ class PollScheduler(object): """ raise NotImplementedError() + def _schedule_tasks(self): + """ + This is called from inside the _schedule() method, which + guarantees the following: + + 1) It will not be called recursively. + 2) _terminate_tasks() will not be called while it is running. + 3) The state of the boolean _terminated_tasks variable will + not change while it is running. + + Unless this method is used to perform user interface updates, + or something like that, the first thing it should do is check + the state of _terminated_tasks and if that is True then it + should return False immediately (since there's no need to + schedule anything after _terminate_tasks() has been called). + """ + raise NotImplementedError() + def _schedule(self): """ Calls _schedule_tasks() and automatically returns early from @@ -90,6 +108,9 @@ class PollScheduler(object): return self._jobs def _can_add_job(self): + if self._terminated_tasks: + return False + max_jobs = self._max_jobs max_load = self._max_load diff --git a/pym/_emerge/QueueScheduler.py b/pym/_emerge/QueueScheduler.py index 8a7ea300a..2d727c95d 100644 --- a/pym/_emerge/QueueScheduler.py +++ b/pym/_emerge/QueueScheduler.py @@ -79,6 +79,9 @@ class QueueScheduler(PollScheduler): @returns: True if there may be remaining tasks to schedule, False otherwise. """ + if self._terminated_tasks: + return False + while self._can_add_job(): n = self._max_jobs - self._running_job_count() if n < 1: diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py index 9f7285634..c6161201a 100644 --- a/pym/_emerge/Scheduler.py +++ b/pym/_emerge/Scheduler.py @@ -1443,7 +1443,7 @@ class Scheduler(PollScheduler): build_dir=build_dir, build_log=build_log, pkg=pkg, returncode=merge.returncode)) - if not self._terminated.is_set(): + if not self._terminated_tasks: self._failed_pkg_msg(self._failed_pkgs[-1], "install", "to") self._status_display.failed = len(self._failed_pkgs) return @@ -1478,7 +1478,7 @@ class Scheduler(PollScheduler): mtimedb.commit() def _build_exit(self, build): - if build.returncode == os.EX_OK and self._terminated.is_set(): + if build.returncode == os.EX_OK and self._terminated_tasks: # We've been interrupted, so we won't # add this to the merge queue. self.curval += 1 @@ -1507,7 +1507,7 @@ class Scheduler(PollScheduler): build_dir=build_dir, build_log=build_log, pkg=build.pkg, returncode=build.returncode)) - if not self._terminated.is_set(): + if not self._terminated_tasks: self._failed_pkg_msg(self._failed_pkgs[-1], "emerge", "for") self._status_display.failed = len(self._failed_pkgs) self._deallocate_config(build.settings) @@ -1687,7 +1687,7 @@ class Scheduler(PollScheduler): self._poll_loop() def _keep_scheduling(self): - return bool(not self._terminated.is_set() and self._pkg_queue and \ + return bool(not self._terminated_tasks and self._pkg_queue and \ not (self._failed_pkgs and not self._build_opts.fetchonly)) def _is_work_scheduled(self): -- 2.26.2