ba740c11fedd49a3319c9fdce0e1cb45f0dc6bcc
[portage.git] / pym / _emerge / QueueScheduler.py
1 # Copyright 1999-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 from _emerge.PollScheduler import PollScheduler
5
6 class QueueScheduler(PollScheduler):
7
8         """
9         Add instances of SequentialTaskQueue and then call run(). The
10         run() method returns when no tasks remain.
11         """
12
13         def __init__(self, max_jobs=None, max_load=None):
14                 PollScheduler.__init__(self)
15
16                 if max_jobs is None:
17                         max_jobs = 1
18
19                 self._max_jobs = max_jobs
20                 self._max_load = max_load
21
22                 self._queues = []
23                 self._schedule_listeners = []
24
25         def add(self, q):
26                 self._queues.append(q)
27
28         def remove(self, q):
29                 self._queues.remove(q)
30
31         def clear(self):
32                 for q in self._queues:
33                         q.clear()
34
35         def run(self, timeout=None):
36
37                 timeout_callback = None
38                 if timeout is not None:
39                         def timeout_callback():
40                                 timeout_callback.timed_out = True
41                                 raise StopIteration()
42                         timeout_callback.timed_out = False
43                         timeout_callback.timeout_id = self.sched_iface.timeout_add(
44                                 timeout, timeout_callback)
45
46                 try:
47                         self._main_loop()
48                 except StopIteration:
49                         pass
50                 finally:
51                         if timeout_callback is not None:
52                                 self.sched_iface.unregister(timeout_callback.timeout_id)
53
54         def _schedule_tasks(self):
55                 """
56                 @rtype: bool
57                 @returns: True if there may be remaining tasks to schedule,
58                         False otherwise.
59                 """
60                 if self._terminated_tasks:
61                         return False
62
63                 while self._can_add_job():
64                         n = self._max_jobs - self._running_job_count()
65                         if n < 1:
66                                 break
67
68                         if not self._start_next_job(n):
69                                 return False
70
71                 for q in self._queues:
72                         if q:
73                                 return True
74                 return False
75
76         def _running_job_count(self):
77                 job_count = 0
78                 for q in self._queues:
79                         job_count += len(q.running_tasks)
80                 self._jobs = job_count
81                 return job_count
82
83         def _start_next_job(self, n=1):
84                 started_count = 0
85                 for q in self._queues:
86                         initial_job_count = len(q.running_tasks)
87                         q.schedule()
88                         final_job_count = len(q.running_tasks)
89                         if final_job_count > initial_job_count:
90                                 started_count += (final_job_count - initial_job_count)
91                         if started_count >= n:
92                                 break
93                 return started_count
94