Ticket #313: bblock.txt

File bblock.txt, 6.3 kB (added by albertHofkamp, 2 months ago)

New description of current implementation. I left out some examples, as they don't seem to add much.

Line 
1 Until now, we assumed that a master can run builds at any slave whenever needed
2 or desired.
3 Some times, you want to enforce additional constraints on builds. For reasons
4 like limited network bandwidth, old slave machines, or a self-willed data base
5 server, you may want to limit the number of builds (or build steps) that can
6 access a resource.
7
8 The mechanism used by Buildbot is known as the read/write lock.@footnote{See
9 http://en.wikipedia.org/wiki/Read/write_lock_pattern for more information.}
10 It allows either many readers or a single writer but not a combination of
11 readers and writers.
12 The general lock has been modified and extended for use in Buildbot.
13 Firstly, the general lock allows an infinite number of readers. In Buildbot,
14 we often want to put an upper limit on the number of readers, for example
15 allowing two out of five possible builds at the same time. To do this, the lock
16 counts the number of active readers.
17 Secondly, the terms @emph{read mode} and @emph{write mode} are confusing in
18 Buildbot context. They have been replaced by @emph{counting mode} (since the
19 lock counts them) and @{exclusive mode}.
20 As a result of these changes, locks in Buildbot allow a number of builds (upto
21 some fixed number) in counting mode, or they allow one build in exclusive mode.
22
23 Often, not all slaves are equal. To allow for this situation, Buildbot allows to
24 have a seperate upper limit on the count for each slave. In this way, you can
25 have at most 3 concurrent builds at a fast slave, 2 at a slightly older slave,
26 and 1 at all other slaves.
27
28 The final thing you can specify when you introduce a new lock is its scope. Some
29 constraints are global, they must be enforced over all slaves. Other constraints
30 are local to each slave.
31 A @emph{master lock} is used for the global constraints. You can ensure for
32 example that at most one build (of all builds running at all slaves) accesses
33 the data base server. With a @emph{slave lock} you can add a limit local for
34 each slave. With such a lock, you can for example enforce an upper limit to the
35 number of active builds at a slave, like above.
36
37 Time for a few examples. Below a master lock is defined to protect a data base,
38 and a slave lock is created to limit the number of builds at each slave.
39 @verbatim
40 from buildbot import locks
41
42 db_lock = locks.MasterLock("database")
43 build_lock = locks.SlaveLock("slave_builds",
44                              maxCount = 1,
45                              maxCountForSlave = { 'fast': 3, 'new': 2 })
46 @end verbatim
47 After importing locks from buildbot, @code{db_lock} is defined to be a master
48 lock. The @code{"database"} string is used for uniquely identifying the lock.
49 At the next line, a slave lock called @code{build_lock} is created. It is
50 identified by the @code{"slave_builds"} string. Since the requirements of the
51 lock are a bit more complicated, two optional arguments are also specified. The
52 @code{maxCount} parameter sets the default limit for builds in counting mode to
53 @code{1}. For the slave called @code{'fast'} however, we want to have at most
54 three builds, and for the slave called @code{'new'} the upper limit is two
55 builds running at the same time.
56
57 The next step is using the locks in builds.
58 Buildbot allows a lock to be used during an entire build (from beginning to
59 end), or only during a single build step. In the latter case, the lock is
60 claimed for use just before the step starts, and released again when the step
61 ends. To prevent deadlocks,@footnote{Deadlock is the situation where two or more
62 slaves each hold a lock in exclusive mode, and in addition want to claim the
63 lock held by the other slave exclusively as well. Since locks allow at most one
64 exclusive user, both slaves will wait forever.} it is not possible to claim or
65 release locks at other times.
66
67 To use locks, you should add them with a @code{locks} argument.
68 Each use of a lock is either in counting mode (that is, possibly shared with
69 other builds) or in exclusive mode. A build or build step proceeds only when it
70 has acquired all locks. If a build or step needs a lot of locks, it may be
71 starved@footnote{Starving is the situation that only a few locks are available,
72 and they are immediately grabbed by another build. As a result, it may take a
73 long time before all locks needed by the starved build are free at the same
74 time.} by other builds that need less locks.
75
76 To illustrate use of locks, a few examples.
77 @example
78 from buildbot import locks
79 from buildbot.steps import source, shell
80 from buildbot.process import factory
81
82 db_lock = locks.MasterLock("database")
83 build_lock = locks.SlaveLock("slave_builds",
84                              maxCount = 1,
85                              maxCountForSlave = { 'fast': 3, 'new': 2 })
86
87 f = factory.BuildFactory()
88 f.addStep(source.SVN(svnurl="http://example.org/svn/Trunk"))
89 f.addStep(shell.ShellCommand(command="make all"))
90 f.addStep(shell.ShellCommand(command="make test",
91                              locks=[db_lock.access('exclusive')]))
92
93 b1 = @{'name': 'full1', 'slavename': 'fast',  'builddir': 'f1', 'factory': f,
94        'locks': [build_lock.access('counting')] @}
95
96 b2 = @{'name': 'full2', 'slavename': 'new',   'builddir': 'f2', 'factory': f.
97        'locks': [build_lock.access('counting')] @}
98
99 b3 = @{'name': 'full3', 'slavename': 'old',   'builddir': 'f3', 'factory': f.
100        'locks': [build_lock.access('counting')] @}
101
102 b4 = @{'name': 'full4', 'slavename': 'other', 'builddir': 'f4', 'factory': f.
103        'locks': [build_lock.access('counting')] @}
104
105 c['builders'] = [b1, b2, b3, b4]
106 @end example
107 Here we have four slaves @code{b1}, @code{b2}, @code{b3}, and @code{b4}. Each
108 slave performs the same checkout, make, and test build step sequence.
109 We want to enforce that at most one test step is executed between all slaves due
110 to restrictions with the data base server. This is done by adding the
111 @code{locks=} parameter with the third step. It takes a list of locks with their
112 access mode. In this case only the @code{db_lock} is needed. The exclusive
113 access mode is used to ensure there is at most one slave that executes the test
114 step.
115
116 In addition to exclusive accessing the data base, we also want that slaves stay
117 responsive even under the load of a large number of builds being triggered. For
118 this purpose, the slave lock called @code{build_lock} is defined. Since the
119 restraint holds for entire builds, the lock is specified in the builder with
120 @code{'locks': [build_lock.access('counting')]}.