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

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: 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
191 # The slave is offline. Is this slave within the grace period?
192 #
bpastene 2016/08/17 01:22:13 nit: remove line
dnj 2016/08/17 01:24:17 Done.
187 # Get the 'SlaveStatus' object for this slave 193 # Get the 'SlaveStatus' object for this slave
188 slave_status = slave_status_map.get(slave_name) 194 slave_status = slave_status_map.get(slave_name)
189 if slave_status is None: 195 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: 196 if last_seen < grace_threshold:
195 # No, the slave is older than our grace period. 197 # No, the slave is older than our grace period.
196 self._debug('Slave [%s] is OFFLINE and outside grace period ' 198 self._debug('Slave [%s] is OFFLINE and outside grace period '
197 '(%s < %s).', slave_name, last_seen, grace_threshold) 199 '(%s < %s).', slave_name, last_seen, grace_threshold)
198 continue 200 continue
199 201
200 # This slave is within its grace threshold. Add it to the list of 202 # 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 203 # desired slaves from this set and update our wait delta in case we
202 # have to poke. 204 # have to poke.
203 # 205 #
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 @staticmethod 249 @staticmethod
248 def _get_all_slave_status(builder): 250 def _get_all_slave_status(builder):
249 # Try using the builder's BuilderStatus object to get a list of all slaves 251 # Try using the builder's BuilderStatus object to get a list of all slaves
250 if builder.builder_status is not None: 252 if builder.builder_status is not None:
251 return builder.builder_status.getSlaves() 253 return builder.builder_status.getSlaves()
252 254
253 # Satisfy with the list of currently-connected slaves 255 # Satisfy with the list of currently-connected slaves
254 return [slave_builder.slave.slave_status 256 return [slave_builder.slave.slave_status
255 for slave_builder in builder.slaves] 257 for slave_builder in builder.slaves]
256 258
257 def _get_latest_seen_time(self, slave_status): 259 def _get_latest_seen_time(self, slave_name, slave_status):
258 times = [] 260 times = [self._slave_seen_times[slave_name]]
259 261
260 # Add all of the registered connect times 262 if slave_status:
261 times += [datetime.fromtimestamp(connect_time) 263 # Add all of the registered connect times
262 for connect_time in slave_status.connect_times] 264 times += [datetime.fromtimestamp(connect_time)
265 for connect_time in slave_status.connect_times]
263 266
264 # Add the time of the slave's last message 267 # Add the time of the slave's last message
265 times.append(datetime.fromtimestamp(slave_status.lastMessageReceived())) 268 times.append(datetime.fromtimestamp(slave_status.lastMessageReceived()))
266
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 269
272 if not times: 270 if not times:
bpastene 2016/08/17 01:22:13 OOC, would times ever be empty here? If I'm readin
dnj 2016/08/17 01:24:17 Oh yeah that's not needed anymore.
273 return None 271 return None
274 return max(times) 272 return max(times)
275 273
276 def _record_slave_seen_time(self, build_slave, now): 274 def _record_slave_seen_time(self, build_slave, now):
277 self._slave_seen_times[build_slave.slavename] = now 275 self._slave_seen_times[build_slave.slavename] = now
278 276
279 def _schedule_builder_timer(self, builder, delta): 277 def _schedule_builder_timer(self, builder, delta):
280 poke_builder_timer = self._poke_builder_timers.get(builder.name) 278 poke_builder_timer = self._poke_builder_timers.get(builder.name)
281 if poke_builder_timer is None: 279 if poke_builder_timer is None:
282 poke_builder_timer = PokeBuilderTimer( 280 poke_builder_timer = PokeBuilderTimer(
283 builder.botmaster, 281 builder.botmaster,
284 builder.name, 282 builder.name,
285 ) 283 )
286 self._poke_builder_timers[builder.name] = poke_builder_timer 284 self._poke_builder_timers[builder.name] = poke_builder_timer
287 poke_builder_timer.reset(delta) 285 poke_builder_timer.reset(delta)
288 286
289 def _cancel_builder_timer(self, builder): 287 def _cancel_builder_timer(self, builder):
290 poke_builder_timer = self._poke_builder_timers.get(builder.name) 288 poke_builder_timer = self._poke_builder_timers.get(builder.name)
291 if poke_builder_timer is None: 289 if poke_builder_timer is None:
292 return 290 return
293 poke_builder_timer.cancel() 291 poke_builder_timer.cancel()
294 292
295 293
296 def _get_now(): 294 def _get_now():
297 """Returns (datetime.datetime): The current time. 295 """Returns (datetime.datetime): The current time.
298 296
299 This exists so it can be overridden by mocks in unit tests. 297 This exists so it can be overridden by mocks in unit tests.
300 """ 298 """
301 return datetime.now() 299 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