| # Copyright 1999-2012 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| from _emerge.PollScheduler import PollScheduler |
| |
| class QueueScheduler(PollScheduler): |
| |
| """ |
| Add instances of SequentialTaskQueue and then call run(). The |
| run() method returns when no tasks remain. |
| """ |
| |
| def __init__(self, max_jobs=None, max_load=None): |
| PollScheduler.__init__(self) |
| |
| if max_jobs is None: |
| max_jobs = 1 |
| |
| self._max_jobs = max_jobs |
| self._max_load = max_load |
| |
| self._queues = [] |
| self._schedule_listeners = [] |
| |
| def add(self, q): |
| self._queues.append(q) |
| |
| def remove(self, q): |
| self._queues.remove(q) |
| |
| def clear(self): |
| for q in self._queues: |
| q.clear() |
| |
| def run(self, timeout=None): |
| |
| timeout_callback = None |
| if timeout is not None: |
| def timeout_callback(): |
| timeout_callback.timed_out = True |
| return False |
| timeout_callback.timed_out = False |
| timeout_callback.timeout_id = self.sched_iface.timeout_add( |
| timeout, timeout_callback) |
| |
| term_check_id = self.sched_iface.idle_add(self._termination_check) |
| try: |
| while not (timeout_callback is not None and |
| timeout_callback.timed_out): |
| # We don't have any callbacks to trigger _schedule(), |
| # so we have to call it explicitly here. |
| self._schedule() |
| if self._keep_scheduling(): |
| self.sched_iface.iteration() |
| else: |
| break |
| |
| while self._is_work_scheduled() and \ |
| not (timeout_callback is not None and |
| timeout_callback.timed_out): |
| self.sched_iface.iteration() |
| finally: |
| self.sched_iface.source_remove(term_check_id) |
| if timeout_callback is not None: |
| self.sched_iface.unregister(timeout_callback.timeout_id) |
| |
| def _schedule_tasks(self): |
| """ |
| @rtype: bool |
| @returns: True if there may be remaining tasks to schedule, |
| False otherwise. |
| """ |
| if self._terminated_tasks: |
| return |
| |
| while self._can_add_job(): |
| n = self._max_jobs - self._running_job_count() |
| if n < 1: |
| break |
| |
| if not self._start_next_job(n): |
| return |
| |
| def _keep_scheduling(self): |
| return not self._terminated_tasks and any(self._queues) |
| |
| def _running_job_count(self): |
| job_count = 0 |
| for q in self._queues: |
| job_count += len(q.running_tasks) |
| self._jobs = job_count |
| return job_count |
| |
| def _start_next_job(self, n=1): |
| started_count = 0 |
| for q in self._queues: |
| initial_job_count = len(q.running_tasks) |
| q.schedule() |
| final_job_count = len(q.running_tasks) |
| if final_job_count > initial_job_count: |
| started_count += (final_job_count - initial_job_count) |
| if started_count >= n: |
| break |
| return started_count |
| |