1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from twisted.internet import defer, reactor
17 from twisted.python import log
18 from buildbot import util, config
19 from buildbot.util import bbcollections, NotABranch
20 from buildbot.changes import filter, changes
21 from buildbot.schedulers import base, dependent
24 """
25 @param onlyImportant: If True, only important changes will be added to the
26 buildset.
27 @type onlyImportant: boolean
28
29 """
30
31 compare_attrs = (base.BaseScheduler.compare_attrs +
32 ('treeStableTimer', 'change_filter', 'fileIsImportant',
33 'onlyImportant') )
34
35 _reactor = reactor
36
38 - def __init__(self, name, shouldntBeSet=NotSet, treeStableTimer=None,
39 builderNames=None, branch=NotABranch, branches=NotABranch,
40 fileIsImportant=None, properties={}, categories=None,
41 change_filter=None, onlyImportant=False):
42 if shouldntBeSet is not self.NotSet:
43 config.error(
44 "pass arguments to schedulers using keyword arguments")
45 if fileIsImportant and not callable(fileIsImportant):
46 config.error(
47 "fileIsImportant must be a callable")
48
49
50 base.BaseScheduler.__init__(self, name, builderNames, properties)
51
52 self.treeStableTimer = treeStableTimer
53 self.fileIsImportant = fileIsImportant
54 self.onlyImportant = onlyImportant
55 self.change_filter = self.getChangeFilter(branch=branch,
56 branches=branches, change_filter=change_filter,
57 categories=categories)
58
59
60
61 self._stable_timers = bbcollections.defaultdict(lambda : None)
62 self._stable_timers_lock = defer.DeferredLock()
63
65 raise NotImplementedError
66
94
96
97 d = base.BaseScheduler.stopService(self)
98 d.addCallback(lambda _ :
99 self._stable_timers_lock.acquire())
100 def cancel_timers(_):
101 for timer in self._stable_timers.values():
102 if timer:
103 timer.cancel()
104 self._stable_timers = {}
105 self._stable_timers_lock.release()
106 d.addCallback(cancel_timers)
107 return d
108
109 @util.deferredLocked('_stable_timers_lock')
111 if not self.treeStableTimer:
112
113
114 if not important:
115 return defer.succeed(None)
116
117
118 return self.addBuildsetForChanges(reason='scheduler',
119 changeids=[ change.number ])
120
121 timer_name = self.getTimerNameForChange(change)
122
123
124
125
126
127 d = self.master.db.schedulers.classifyChanges(
128 self.objectid, { change.number : important })
129 def fix_timer(_):
130 if not important and not self._stable_timers[timer_name]:
131 return
132 if self._stable_timers[timer_name]:
133 self._stable_timers[timer_name].cancel()
134 def fire_timer():
135 d = self.stableTimerFired(timer_name)
136 d.addErrback(log.err, "while firing stable timer")
137 self._stable_timers[timer_name] = self._reactor.callLater(
138 self.treeStableTimer, fire_timer)
139 d.addCallback(fix_timer)
140 return d
141
142 @defer.deferredGenerator
144
145
146
147
148
149
150 wfd = defer.waitForDeferred(
151 self.master.db.schedulers.getChangeClassifications(
152 self.objectid))
153 yield wfd
154 classifications = wfd.getResult()
155
156
157 for changeid, important in classifications.iteritems():
158 wfd = defer.waitForDeferred(
159 self.master.db.changes.getChange(changeid))
160 yield wfd
161 chdict = wfd.getResult()
162
163 if not chdict:
164 continue
165
166 wfd = defer.waitForDeferred(
167 changes.Change.fromChdict(self.master, chdict))
168 yield wfd
169 change = wfd.getResult()
170
171 wfd = defer.waitForDeferred(
172 self.gotChange(change, important))
173 yield wfd
174 wfd.getResult()
175
177 raise NotImplementedError
178
180 """similar to db.schedulers.getChangeClassifications, but given timer
181 name"""
182 raise NotImplementedError
183
184 @util.deferredLocked('_stable_timers_lock')
185 @defer.deferredGenerator
187
188 if not self._stable_timers[timer_name]:
189 return
190
191
192 del self._stable_timers[timer_name]
193
194 wfd = defer.waitForDeferred(
195 self.getChangeClassificationsForTimer(self.objectid,
196 timer_name))
197 yield wfd
198 classifications = wfd.getResult()
199
200
201 if not classifications:
202 return
203
204 changeids = sorted(classifications.keys())
205 wfd = defer.waitForDeferred(
206 self.addBuildsetForChanges(reason='scheduler',
207 changeids=changeids))
208 yield wfd
209 wfd.getResult()
210
211 max_changeid = changeids[-1]
212 wfd = defer.waitForDeferred(
213 self.master.db.schedulers.flushChangeClassifications(
214 self.objectid, less_than=max_changeid+1))
215 yield wfd
216 wfd.getResult()
217
240
243 "alias for SingleBranchScheduler"
245 log.msg("WARNING: the name 'Scheduler' is deprecated; use " +
246 "buildbot.schedulers.basic.SingleBranchScheduler instead " +
247 "(note that this may require you to change your import " +
248 "statement)")
249 SingleBranchScheduler.__init__(self, *args, **kwargs)
250
266
267
268 Dependent = dependent.Dependent
269