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
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 assert shouldntBeSet is self.NotSet, \
43 "pass arguments to schedulers using keyword arguments"
44 if fileIsImportant:
45 assert callable(fileIsImportant)
46
47
48 base.BaseScheduler.__init__(self, name, builderNames, properties)
49
50 self.treeStableTimer = treeStableTimer
51 self.fileIsImportant = fileIsImportant
52 self.onlyImportant = onlyImportant
53 self.change_filter = self.getChangeFilter(branch=branch,
54 branches=branches, change_filter=change_filter,
55 categories=categories)
56
57
58
59 self._stable_timers = bbcollections.defaultdict(lambda : None)
60 self._stable_timers_lock = defer.DeferredLock()
61
63 raise NotImplementedError
64
92
94
95 d = base.BaseScheduler.stopService(self)
96 d.addCallback(lambda _ :
97 self._stable_timers_lock.acquire())
98 def cancel_timers(_):
99 for timer in self._stable_timers.values():
100 if timer:
101 timer.cancel()
102 self._stable_timers = {}
103 self._stable_timers_lock.release()
104 d.addCallback(cancel_timers)
105 return d
106
107 @util.deferredLocked('_stable_timers_lock')
109 if not self.treeStableTimer:
110
111
112 if not important:
113 return defer.succeed(None)
114
115
116 return self.addBuildsetForChanges(reason='scheduler',
117 changeids=[ change.number ])
118
119 timer_name = self.getTimerNameForChange(change)
120
121
122
123
124
125 d = self.master.db.schedulers.classifyChanges(
126 self.schedulerid, { change.number : important })
127 def fix_timer(_):
128 if not important and not self._stable_timers[timer_name]:
129 return
130 if self._stable_timers[timer_name]:
131 self._stable_timers[timer_name].cancel()
132 self._stable_timers[timer_name] = self._reactor.callLater(
133 self.treeStableTimer, self.stableTimerFired, timer_name)
134 d.addCallback(fix_timer)
135 return d
136
137 @defer.deferredGenerator
139
140
141
142
143
144
145 wfd = defer.waitForDeferred(
146 self.master.db.schedulers.getChangeClassifications(
147 self.schedulerid))
148 yield wfd
149 classifications = wfd.getResult()
150
151
152 for changeid, important in classifications.iteritems():
153 wfd = defer.waitForDeferred(
154 self.master.db.changes.getChange(changeid))
155 yield wfd
156 chdict = wfd.getResult()
157
158 if not chdict:
159 continue
160
161 wfd = defer.waitForDeferred(
162 changes.Change.fromChdict(self.master, chdict))
163 yield wfd
164 change = wfd.getResult()
165
166 wfd = defer.waitForDeferred(
167 self.gotChange(change, important))
168 yield wfd
169 wfd.getResult()
170
172 raise NotImplementedError
173
175 """similar to db.schedulers.getChangeClassifications, but given timer
176 name"""
177 raise NotImplementedError
178
179 @util.deferredLocked('_stable_timers_lock')
180 @defer.deferredGenerator
182
183 if not self._stable_timers[timer_name]:
184 return
185
186
187 del self._stable_timers[timer_name]
188
189 wfd = defer.waitForDeferred(
190 self.getChangeClassificationsForTimer(self.schedulerid,
191 timer_name))
192 yield wfd
193 classifications = wfd.getResult()
194
195
196 if not classifications:
197 return
198
199 changeids = sorted(classifications.keys())
200 wfd = defer.waitForDeferred(
201 self.addBuildsetForChanges(reason='scheduler',
202 changeids=changeids))
203 yield wfd
204 wfd.getResult()
205
206 max_changeid = changeids[-1]
207 wfd = defer.waitForDeferred(
208 self.master.db.schedulers.flushChangeClassifications(
209 self.schedulerid, less_than=max_changeid+1))
210 yield wfd
211 wfd.getResult()
212
231
234 "alias for SingleBranchScheduler"
236 log.msg("WARNING: the name 'Scheduler' is deprecated; use " +
237 "buildbot.schedulers.basic.SingleBranchScheduler instead " +
238 "(note that this may require you to change your import " +
239 "statement)")
240 SingleBranchScheduler.__init__(self, *args, **kwargs)
241
257
258
259 Dependent = dependent.Dependent
260