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
dustin@zmanda.com
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(util.ComparableMixin):
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(util.ComparableMixin):
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
        locks = {}
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, locks[l.name], l.name))
648
                                         % (l, lock_dict[l.name], l.name))
648
649
                else:
649
                    locks[l.name] = l
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, locks[l.name], l.name))
660
                                             % (l, lock_dict[l.name], l.name))
660
661
                    else:
661
                        locks[l.name] = l
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 ths
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
b3 = @{'name': 'full3', 'slavename': 'bot-3', builddir='f3', 'factory': f@}
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', builddir='full1',
5921
b1 = @{'name': 'full1', 'slavename': 'bot-slow', 'builddir': 'full1',
5922
5922
      'factory': f@}
5923
b2 = @{'name': 'full2', 'slavename': 'bot-slow', builddir='full2',
5923
b2 = @{'name': 'full2', 'slavename': 'bot-slow', 'builddir': 'full2',
5924
5924
      'factory': f@}
5925
b3 = @{'name': 'full3', 'slavename': 'bot-fast', builddir='full3',
5925
b3 = @{'name': 'full3', 'slavename': 'bot-fast', 'builddir': 'full3',
5926
5926
      'factory': f@}
5927
b4 = @{'name': 'full4', 'slavename': 'bot-fast', builddir='full4',
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.Waterfall(http_port=8080)
6902
w = html.WebStatus(http_port=8080)
6903
6903
c['status'].append(w)
6904
6904
@end example
6905
6905