Package buildbot :: Package schedulers :: Module manager
[frames] | no frames]

Source Code for Module buildbot.schedulers.manager

 1  # This file is part of Buildbot.  Buildbot is free software: you can 
 2  # redistribute it and/or modify it under the terms of the GNU General Public 
 3  # License as published by the Free Software Foundation, version 2. 
 4  # 
 5  # This program is distributed in the hope that it will be useful, but WITHOUT 
 6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
 7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
 8  # details. 
 9  # 
10  # You should have received a copy of the GNU General Public License along with 
11  # this program; if not, write to the Free Software Foundation, Inc., 51 
12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
13  # 
14  # Copyright Buildbot Team Members 
15   
16  from twisted.internet import defer 
17  from twisted.application import service 
18  from twisted.python import log 
19  from buildbot.util import bbcollections, deferredLocked 
20 21 -class SchedulerManager(service.MultiService):
22 - def __init__(self, master):
23 service.MultiService.__init__(self) 24 self.master = master 25 self.upstream_subscribers = bbcollections.defaultdict(list) 26 self._updateLock = defer.DeferredLock()
27 28 @deferredLocked('_updateLock')
29 - def updateSchedulers(self, newschedulers):
30 """Add and start any Scheduler that isn't already a child of ours. 31 Stop and remove any that are no longer in the list. Make sure each 32 one has a schedulerid in the database.""" 33 # compute differences 34 old = dict((s.name,s) for s in self) 35 old_names = set(old) 36 new = dict((s.name,s) for s in newschedulers) 37 new_names = set(new) 38 39 added_names = new_names - old_names 40 removed_names = old_names - new_names 41 42 # find any existing schedulers that need to be updated 43 updated_names = set(name for name in (new_names & old_names) 44 if old[name] != new[name]) 45 46 log.msg("removing %d old schedulers, updating %d, and adding %d" 47 % (len(removed_names), len(updated_names), len(added_names))) 48 49 # treat updates as an add and a remove, for simplicity 50 added_names |= updated_names 51 removed_names |= updated_names 52 53 # build a deferred chain that stops all of the removed schedulers, 54 # *then* starts all of the added schedulers. note that _setUpScheduler 55 # is called before the service starts, and _shutDownSchedler is called 56 # after the service is stopped. Also note that this shuts down all 57 # relevant schedulers before starting any schedulers - there's unlikely 58 # to be any payoff to more parallelism 59 d = defer.succeed(None) 60 61 def stopScheduler(sch): 62 d = defer.maybeDeferred(lambda : sch.disownServiceParent()) 63 d.addCallback(lambda _ : sch._shutDownScheduler()) 64 return d
65 d.addCallback(lambda _ : 66 defer.gatherResults([stopScheduler(old[n]) for n in removed_names])) 67 68 # account for some renamed classes in buildbot - classes that have 69 # changed their module import path, but should still access the same 70 # state 71 72 new_class_names = { 73 # new : old 74 'buildbot.schedulers.dependent.Dependent' : 75 'buildbot.schedulers.basic.Dependent', 76 'buildbot.schedulers.basic.SingleBranchScheduler' : 77 'buildbot.schedulers.basic.Scheduler', 78 } 79 def startScheduler(sch): 80 class_name = '%s.%s' % (sch.__class__.__module__, 81 sch.__class__.__name__) 82 class_name = new_class_names.get(class_name, class_name) 83 d = self.master.db.schedulers.getSchedulerId(sch.name, class_name) 84 d.addCallback(lambda schedulerid : 85 sch._setUpScheduler(schedulerid, self.master, self)) 86 d.addCallback(lambda _ : 87 sch.setServiceParent(self)) 88 return d
89 d.addCallback(lambda _ : 90 defer.gatherResults([startScheduler(new[n]) for n in added_names])) 91 92 d.addErrback(log.err) 93 return d 94