bbangert /
buildbot-xmlrpc
Buildbot fork with additional XMLRPC methods and bugfixes.
Clone URL : http://bitbucket.org/bbangert/buildbot-xmlrpc/ (size: 1.9 MB)
| commit 714: | cdb0c18d5cf2 |
| parent 713: | 15e18eb06e53 |
| branch: | default |
docstrings, name changes, optimizations, new BaseLockId parent class
4 months ago
Changed (Δ1.1 KB):
raw changeset »
buildbot/locks.py (25 lines added, 2 lines removed)
buildbot/master.py (11 lines added, 10 lines removed)
buildbot/util.py (8 lines added, 4 lines removed)
docs/buildbot.texinfo (15 lines added, 15 lines removed)
Up to file-list buildbot/locks.py:
| … | … | @@ -10,6 +10,16 @@ else: |
10 |
10 |
debuglog = lambda m: None |
11 |
11 |
|
12 |
12 |
class BaseLock: |
13 |
""" |
|
14 |
Class handling claiming and releasing of L{self}, and keeping track of |
|
15 |
current and waiting owners. |
|
16 |
||
17 |
@note: Ideally, we'd like to maintain FIFO order. The place to do that |
|
18 |
would be the L{isAvailable()} function. However, this function is |
|
19 |
called by builds/steps both for the first time, and after waking |
|
20 |
them up by L{self} from the L{self.waiting} queue. There is |
|
21 |
currently no way of distinguishing between them. |
|
22 |
""" |
|
13 |
23 |
description = "<BaseLock>" |
14 |
24 |
|
15 |
25 |
def __init__(self, name, maxCount=1): |
| … | … | @@ -22,10 +32,12 @@ class BaseLock: |
22 |
32 |
return self.description |
23 |
33 |
|
24 |
34 |
def isAvailable(self): |
35 |
""" Return a boolean whether the lock is available for claiming """ |
|
25 |
36 |
debuglog("%s isAvailable: self.owners=%r" % (self, self.owners)) |
26 |
37 |
return len(self.owners) < self.maxCount |
27 |
38 |
|
28 |
39 |
def claim(self, owner): |
40 |
""" Claim the lock (lock must be available) """ |
|
29 |
41 |
debuglog("%s claim(%s)" % (self, owner)) |
30 |
42 |
assert owner is not None |
31 |
43 |
assert len(self.owners) < self.maxCount, "ask for isAvailable() first" |
| … | … | @@ -33,6 +45,7 @@ class BaseLock: |
33 |
45 |
debuglog(" %s is claimed" % (self,)) |
34 |
46 |
|
35 |
47 |
def release(self, owner): |
48 |
""" Release the lock """ |
|
36 |
49 |
debuglog("%s release(%s)" % (self, owner)) |
37 |
50 |
assert owner in self.owners |
38 |
51 |
self.owners.remove(owner) |
| … | … | @@ -90,11 +103,21 @@ class RealSlaveLock: |
90 |
103 |
return self.locks[slavename] |
91 |
104 |
|
92 |
105 |
|
106 |
class BaseLockId(util.ComparableMixin): |
|
107 |
""" Abstract base class for LockId classes. |
|
108 |
||
109 |
Derived classes should add |
|
110 |
- Comparison with the L{util.ComparableMixin} via the L{compare_attrs} |
|
111 |
class variable. |
|
112 |
- Link to the actual lock class should be added with the L{lockClass} |
|
113 |
class variable. |
|
114 |
""" |
|
115 |
||
93 |
116 |
# master.cfg should only reference the following MasterLock and SlaveLock |
94 |
117 |
# classes. They are identifiers that will be turned into real Locks later, |
95 |
118 |
# via the BotMaster.getLockByID method. |
96 |
119 |
|
97 |
class MasterLock( |
|
120 |
class MasterLock(BaseLockId): |
|
98 |
121 |
"""I am a semaphore that limits the number of simultaneous actions. |
99 |
122 |
|
100 |
123 |
Builds and BuildSteps can declare that they wish to claim me as they run. |
| … | … | @@ -113,7 +136,7 @@ class MasterLock(util.ComparableMixin): |
113 |
136 |
self.name = name |
114 |
137 |
self.maxCount = maxCount |
115 |
138 |
|
116 |
class SlaveLock( |
|
139 |
class SlaveLock(BaseLockId): |
|
117 |
140 |
"""I am a semaphore that limits simultaneous actions on each buildslave. |
118 |
141 |
|
119 |
142 |
Builds and BuildSteps can declare that they wish to claim me as they run. |
Up to file-list buildbot/master.py:
| … | … | @@ -27,7 +27,7 @@ from buildbot.changes.changes import Cha |
27 |
27 |
from buildbot.changes.changes import Change, ChangeMaster |
28 |
28 |
from buildbot.sourcestamp import SourceStamp |
29 |
29 |
from buildbot.buildslave import BuildSlave |
30 |
from buildbot import interfaces |
|
30 |
from buildbot import interfaces, locks |
|
31 |
31 |
from buildbot.process.properties import Properties |
32 |
32 |
|
33 |
33 |
######################################## |
| … | … | @@ -211,6 +211,7 @@ class BotMaster(service.MultiService): |
211 |
211 |
@param lockid: a locks.MasterLock or locks.SlaveLock instance |
212 |
212 |
@return: a locks.RealMasterLock or locks.RealSlaveLock instance |
213 |
213 |
""" |
214 |
assert isinstance(lockid, (locks.MasterLock, locks.SlaveLock)) |
|
214 |
215 |
if not lockid in self.locks: |
215 |
216 |
self.locks[lockid] = lockid.lockClass(lockid) |
216 |
217 |
# if the master.cfg file has changed maxCount= on the lock, the next |
| … | … | @@ -637,28 +638,28 @@ class BuildMaster(service.MultiService, |
637 |
638 |
|
638 |
639 |
# assert that all locks used by the Builds and their Steps are |
639 |
640 |
# uniquely named. |
640 |
lock |
|
641 |
lock_dict = {} |
|
641 |
642 |
for b in builders: |
642 |
643 |
for l in b.get('locks', []): |
643 |
if locks.has_key(l.name): |
|
644 |
if locks[l.name] is not l: |
|
644 |
if lock_dict.has_key(l.name): |
|
645 |
if lock_dict[l.name] is not l: |
|
645 |
646 |
raise ValueError("Two different locks (%s and %s) " |
646 |
647 |
"share the name %s" |
647 |
% (l, lock |
|
648 |
% (l, lock_dict[l.name], l.name)) |
|
648 |
649 |
else: |
649 |
lock |
|
650 |
lock_dict[l.name] = l |
|
650 |
651 |
# TODO: this will break with any BuildFactory that doesn't use a |
651 |
652 |
# .steps list, but I think the verification step is more |
652 |
653 |
# important. |
653 |
654 |
for s in b['factory'].steps: |
654 |
655 |
for l in s[1].get('locks', []): |
655 |
if locks.has_key(l.name): |
|
656 |
if locks[l.name] is not l: |
|
656 |
if lock_dict.has_key(l.name): |
|
657 |
if lock_dict[l.name] is not l: |
|
657 |
658 |
raise ValueError("Two different locks (%s and %s)" |
658 |
659 |
" share the name %s" |
659 |
% (l, lock |
|
660 |
% (l, lock_dict[l.name], l.name)) |
|
660 |
661 |
else: |
661 |
lock |
|
662 |
lock_dict[l.name] = l |
|
662 |
663 |
|
663 |
664 |
if not isinstance(properties, dict): |
664 |
665 |
raise ValueError("c['properties'] must be a dictionary") |
Up to file-list buildbot/util.py:
| … | … | @@ -71,10 +71,14 @@ class ComparableMixin: |
71 |
71 |
return hash(tuple(alist)) |
72 |
72 |
|
73 |
73 |
def __cmp__(self, them): |
74 |
if cmp(type(self), type(them)): |
|
75 |
return cmp(type(self), type(them)) |
|
76 |
if cmp(self.__class__, them.__class__): |
|
77 |
return cmp(self.__class__, them.__class__) |
|
74 |
result = cmp(type(self), type(them)) |
|
75 |
if result: |
|
76 |
return result |
|
77 |
||
78 |
result = cmp(self.__class__, them.__class__) |
|
79 |
if result: |
|
80 |
return result |
|
81 |
||
78 |
82 |
assert self.compare_attrs == them.compare_attrs |
79 |
83 |
self_list= [getattr(self, name, _None) for name in self.compare_attrs] |
80 |
84 |
them_list= [getattr(them, name, _None) for name in self.compare_attrs] |
Up to file-list docs/buildbot.texinfo:
| … | … | @@ -5806,7 +5806,7 @@ simultaneous builds as there are machine |
5806 |
5806 |
simultaneous builds as there are machines. |
5807 |
5807 |
|
5808 |
5808 |
Each @code{Lock} is created with a unique name. Each lock gets a count |
5809 |
of how many owners it may have: how many processes can claim it at th |
|
5809 |
of how many owners it may have: how many processes can claim it at the |
|
5810 |
5810 |
same time. This limit defaults to one, and is controllable through the |
5811 |
5811 |
@code{maxCount} argument. On @code{SlaveLock}s you can set the owner |
5812 |
5812 |
count on a per-slave basis by providing a dictionary (that maps from |
| … | … | @@ -5856,9 +5856,9 @@ f.addStep(source.SVN(svnurl="http://exam |
5856 |
5856 |
f.addStep(source.SVN(svnurl="http://example.org/svn/Trunk")) |
5857 |
5857 |
f.addStep(shell.ShellCommand(command="make all")) |
5858 |
5858 |
f.addStep(shell.ShellCommand(command="make test", locks=[db_lock])) |
5859 |
b1 = @{'name': 'full1', 'slavename': 'bot-1', builddir='f1', 'factory': f@} |
|
5860 |
b2 = @{'name': 'full2', 'slavename': 'bot-2', builddir='f2', 'factory': f@} |
|
5861 |
b |
|
5859 |
b1 = @{'name': 'full1', 'slavename': 'bot-1', 'builddir': 'f1', 'factory': f@} |
|
5860 |
b2 = @{'name': 'full2', 'slavename': 'bot-2', 'builddir': 'f2', 'factory': f@} |
|
5861 |
b3 = @{'name': 'full3', 'slavename': 'bot-3', 'builddir': 'f3', 'factory': f@} |
|
5862 |
5862 |
c['builders'] = [b1, b2, b3] |
5863 |
5863 |
@end example |
5864 |
5864 |
|
| … | … | @@ -5885,12 +5885,12 @@ f22 = factory.Trial(source, trialpython= |
5885 |
5885 |
f22 = factory.Trial(source, trialpython=["python2.2"]) |
5886 |
5886 |
f23 = factory.Trial(source, trialpython=["python2.3"]) |
5887 |
5887 |
f24 = factory.Trial(source, trialpython=["python2.4"]) |
5888 |
b1 = @{'name': 'p22', 'slavename': 'bot-1', builddir='p22', 'factory': f22, |
|
5889 |
'locks': [slow_lock] @} |
|
5890 |
b2 = @{'name': 'p23', 'slavename': 'bot-1', builddir='p23', 'factory': f23, |
|
5891 |
'locks': [slow_lock] @} |
|
5892 |
b3 = @{'name': 'p24', 'slavename': 'bot-1', builddir='p24', 'factory': f24, |
|
5893 |
'locks': [slow_lock] @} |
|
5888 |
b1 = @{'name': 'p22', 'slavename': 'bot-1', 'builddir': 'p22', |
|
5889 |
'factory': f22, 'locks': [slow_lock] @} |
|
5890 |
b2 = @{'name': 'p23', 'slavename': 'bot-1', 'builddir': 'p23', |
|
5891 |
'factory': f23, 'locks': [slow_lock] @} |
|
5892 |
b3 = @{'name': 'p24', 'slavename': 'bot-1', 'builddir': 'p24', |
|
5893 |
'factory': f24, 'locks': [slow_lock] @} |
|
5894 |
5894 |
c['builders'] = [b1, b2, b3] |
5895 |
5895 |
@end example |
5896 |
5896 |
|
| … | … | @@ -5918,13 +5918,13 @@ f.addStep(shell.ShellCommand(command="ma |
5918 |
5918 |
f.addStep(shell.ShellCommand(command="make test", locks=[cpu_lock])) |
5919 |
5919 |
f.addStep(shell.ShellCommand(command="make db-test", locks=[db_lock, cpu_lock])) |
5920 |
5920 |
|
5921 |
b1 = @{'name': 'full1', 'slavename': 'bot-slow', |
|
5921 |
b1 = @{'name': 'full1', 'slavename': 'bot-slow', 'builddir': 'full1', |
|
5922 |
5922 |
'factory': f@} |
5923 |
b2 = @{'name': 'full2', 'slavename': 'bot-slow', |
|
5923 |
b2 = @{'name': 'full2', 'slavename': 'bot-slow', 'builddir': 'full2', |
|
5924 |
5924 |
'factory': f@} |
5925 |
b3 = @{'name': 'full3', 'slavename': 'bot-fast', |
|
5925 |
b3 = @{'name': 'full3', 'slavename': 'bot-fast', 'builddir': 'full3', |
|
5926 |
5926 |
'factory': f@} |
5927 |
b4 = @{'name': 'full4', 'slavename': 'bot-fast', |
|
5927 |
b4 = @{'name': 'full4', 'slavename': 'bot-fast', 'builddir': 'full4', |
|
5928 |
5928 |
'factory': f@} |
5929 |
5929 |
c['builders'] = [b1, b2, b3, b4] |
5930 |
5930 |
@end example |
| … | … | @@ -6899,7 +6899,7 @@ from a future release. |
6899 |
6899 |
|
6900 |
6900 |
@example |
6901 |
6901 |
from buildbot.status import html |
6902 |
w = html.W |
|
6902 |
w = html.WebStatus(http_port=8080) |
|
6903 |
6903 |
c['status'].append(w) |
6904 |
6904 |
@end example |
6905 |
6905 |
