Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: scripts/master/floating_builder.py

Issue 2255643002: Floating builder logic waits at startup. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Fix nits. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | scripts/master/unittests/floating_builder_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import itertools
5 from datetime import datetime 6 from datetime import datetime
6 7
7 from twisted.python import log 8 from twisted.python import log
8 from twisted.internet import reactor 9 from twisted.internet import reactor
9 10
10 11
11 class FloatingSet(object): 12 class FloatingSet(object):
12 """A set describing available primary/floating slaves.""" 13 """A set describing available primary/floating slaves."""
13 def __init__(self): 14 def __init__(self):
14 self._primary = set() 15 self._primary = set()
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 Args: 87 Args:
87 fs (FloatingSet): The set of available primary/floating slaves. 88 fs (FloatingSet): The set of available primary/floating slaves.
88 grace_period: (timedelta) The amount of time that a slave can be offline 89 grace_period: (timedelta) The amount of time that a slave can be offline
89 before builds fall through to a lower strata. 90 before builds fall through to a lower strata.
90 """ 91 """
91 92
92 def __init__(self, fs, grace_period): 93 def __init__(self, fs, grace_period):
93 self._primary, self._floating = fs.Get() 94 self._primary, self._floating = fs.Get()
94 self._fs = fs 95 self._fs = fs
95 self._grace_period = grace_period 96 self._grace_period = grace_period
96 self._slave_seen_times = {}
97 self._poke_builder_timers = {} 97 self._poke_builder_timers = {}
98 self.verbose = False 98 self.verbose = False
99 99
100 started = _get_now()
101 self._slave_seen_times = dict((s, started) for s in itertools.chain(
102 self._primary, self._floating))
103
100 def __repr__(self): 104 def __repr__(self):
101 return '%s(%s)' % (type(self).__name__, self._fs) 105 return '%s(%s)' % (type(self).__name__, self._fs)
102 106
103 def __call__(self, builder, slave_builders): 107 def __call__(self, builder, slave_builders):
104 """Main 'nextSlave' invocation point. 108 """Main 'nextSlave' invocation point.
105 109
106 When this is called, we are given the following information: 110 When this is called, we are given the following information:
107 - The Builder 111 - The Builder
108 - A set of 'SlaveBuilder' instances that are available and ready for 112 - A set of 'SlaveBuilder' instances that are available and ready for
109 assignment (slave_builders). 113 assignment (slave_builders).
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 181
178 # Is this slave online? If so, we won't consider floating candiates. 182 # Is this slave online? If so, we won't consider floating candiates.
179 if slave_name in online_slave_builders: 183 if slave_name in online_slave_builders:
180 # The slave is online, but is not proposed (BUSY); add it to the 184 # The slave is online, but is not proposed (BUSY); add it to the
181 # desired slaves list. 185 # desired slaves list.
182 self._debug('Slave [%s] is online but BUSY.', slave_name) 186 self._debug('Slave [%s] is online but BUSY.', slave_name)
183 within_grace_period.append(slave_name) 187 within_grace_period.append(slave_name)
184 some_primary_were_busy = True 188 some_primary_were_busy = True
185 continue 189 continue
186 190
187 # Get the 'SlaveStatus' object for this slave 191 # The slave is offline. Is this slave within the grace period?
188 slave_status = slave_status_map.get(slave_name) 192 slave_status = slave_status_map.get(slave_name)
189 if slave_status is None: 193 last_seen = self._get_latest_seen_time(slave_name, slave_status)
190 continue
191
192 # The slave is offline. Is this slave within the grace period?
193 last_seen = self._get_latest_seen_time(slave_status)
194 if last_seen < grace_threshold: 194 if last_seen < grace_threshold:
195 # No, the slave is older than our grace period. 195 # No, the slave is older than our grace period.
196 self._debug('Slave [%s] is OFFLINE and outside grace period ' 196 self._debug('Slave [%s] is OFFLINE and outside grace period '
197 '(%s < %s).', slave_name, last_seen, grace_threshold) 197 '(%s < %s).', slave_name, last_seen, grace_threshold)
198 continue 198 continue
199 199
200 # This slave is within its grace threshold. Add it to the list of 200 # This slave is within its grace threshold. Add it to the list of
201 # desired slaves from this set and update our wait delta in case we 201 # desired slaves from this set and update our wait delta in case we
202 # have to poke. 202 # have to poke.
203 # 203 #
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 @staticmethod 247 @staticmethod
248 def _get_all_slave_status(builder): 248 def _get_all_slave_status(builder):
249 # Try using the builder's BuilderStatus object to get a list of all slaves 249 # Try using the builder's BuilderStatus object to get a list of all slaves
250 if builder.builder_status is not None: 250 if builder.builder_status is not None:
251 return builder.builder_status.getSlaves() 251 return builder.builder_status.getSlaves()
252 252
253 # Satisfy with the list of currently-connected slaves 253 # Satisfy with the list of currently-connected slaves
254 return [slave_builder.slave.slave_status 254 return [slave_builder.slave.slave_status
255 for slave_builder in builder.slaves] 255 for slave_builder in builder.slaves]
256 256
257 def _get_latest_seen_time(self, slave_status): 257 def _get_latest_seen_time(self, slave_name, slave_status):
258 times = [] 258 times = [self._slave_seen_times[slave_name]]
259 259
260 # Add all of the registered connect times 260 if slave_status:
261 times += [datetime.fromtimestamp(connect_time) 261 # Add all of the registered connect times
262 for connect_time in slave_status.connect_times] 262 times += [datetime.fromtimestamp(connect_time)
263 for connect_time in slave_status.connect_times]
263 264
264 # Add the time of the slave's last message 265 # Add the time of the slave's last message
265 times.append(datetime.fromtimestamp(slave_status.lastMessageReceived())) 266 times.append(datetime.fromtimestamp(slave_status.lastMessageReceived()))
266 267
267 # Add the last time we've seen the slave in our 'nextSlave' function
268 last_seen_time = self._slave_seen_times.get(slave_status.name)
269 if last_seen_time is not None:
270 times.append(last_seen_time)
271
272 if not times:
273 return None
274 return max(times) 268 return max(times)
275 269
276 def _record_slave_seen_time(self, build_slave, now): 270 def _record_slave_seen_time(self, build_slave, now):
277 self._slave_seen_times[build_slave.slavename] = now 271 self._slave_seen_times[build_slave.slavename] = now
278 272
279 def _schedule_builder_timer(self, builder, delta): 273 def _schedule_builder_timer(self, builder, delta):
280 poke_builder_timer = self._poke_builder_timers.get(builder.name) 274 poke_builder_timer = self._poke_builder_timers.get(builder.name)
281 if poke_builder_timer is None: 275 if poke_builder_timer is None:
282 poke_builder_timer = PokeBuilderTimer( 276 poke_builder_timer = PokeBuilderTimer(
283 builder.botmaster, 277 builder.botmaster,
284 builder.name, 278 builder.name,
285 ) 279 )
286 self._poke_builder_timers[builder.name] = poke_builder_timer 280 self._poke_builder_timers[builder.name] = poke_builder_timer
287 poke_builder_timer.reset(delta) 281 poke_builder_timer.reset(delta)
288 282
289 def _cancel_builder_timer(self, builder): 283 def _cancel_builder_timer(self, builder):
290 poke_builder_timer = self._poke_builder_timers.get(builder.name) 284 poke_builder_timer = self._poke_builder_timers.get(builder.name)
291 if poke_builder_timer is None: 285 if poke_builder_timer is None:
292 return 286 return
293 poke_builder_timer.cancel() 287 poke_builder_timer.cancel()
294 288
295 289
296 def _get_now(): 290 def _get_now():
297 """Returns (datetime.datetime): The current time. 291 """Returns (datetime.datetime): The current time.
298 292
299 This exists so it can be overridden by mocks in unit tests. 293 This exists so it can be overridden by mocks in unit tests.
300 """ 294 """
301 return datetime.now() 295 return datetime.now()
OLDNEW
« no previous file with comments | « no previous file | scripts/master/unittests/floating_builder_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698