1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """
17 Support for buildsets in the database
18 """
19
20 import sqlalchemy as sa
21 from twisted.internet import reactor
22 from buildbot.util import json
23 from buildbot.db import base
24 from buildbot.util import epoch2datetime, datetime2epoch
25
28
30
31
32 - def addBuildset(self, sourcestampsetid, reason, properties, builderNames,
33 external_idstring=None, _reactor=reactor):
34 def thd(conn):
35 buildsets_tbl = self.db.model.buildsets
36 submitted_at = _reactor.seconds()
37
38 self.check_length(buildsets_tbl.c.reason, reason)
39 self.check_length(buildsets_tbl.c.external_idstring,
40 external_idstring)
41
42 transaction = conn.begin()
43
44
45 r = conn.execute(buildsets_tbl.insert(), dict(
46 sourcestampsetid=sourcestampsetid, submitted_at=submitted_at,
47 reason=reason, complete=0, complete_at=None, results=-1,
48 external_idstring=external_idstring))
49 bsid = r.inserted_primary_key[0]
50
51
52 if properties:
53 bs_props_tbl = self.db.model.buildset_properties
54
55 inserts = [
56 dict(buildsetid=bsid, property_name=k,
57 property_value=json.dumps([v,s]))
58 for k,(v,s) in properties.iteritems() ]
59 for i in inserts:
60 self.check_length(bs_props_tbl.c.property_name,
61 i['property_name'])
62
63 conn.execute(bs_props_tbl.insert(), inserts)
64
65
66
67
68
69 brids = {}
70 br_tbl = self.db.model.buildrequests
71 ins = br_tbl.insert()
72 for buildername in builderNames:
73 self.check_length(br_tbl.c.buildername, buildername)
74 r = conn.execute(ins,
75 dict(buildsetid=bsid, buildername=buildername, priority=0,
76 claimed_at=0, claimed_by_name=None,
77 claimed_by_incarnation=None, complete=0, results=-1,
78 submitted_at=submitted_at, complete_at=None))
79
80 brids[buildername] = r.inserted_primary_key[0]
81
82 transaction.commit()
83
84 return (bsid, brids)
85 return self.db.pool.do(thd)
86
89 if complete_at is not None:
90 complete_at = datetime2epoch(complete_at)
91 else:
92 complete_at = _reactor.seconds()
93
94 def thd(conn):
95 tbl = self.db.model.buildsets
96
97 q = tbl.update(whereclause=(
98 (tbl.c.id == bsid) &
99 ((tbl.c.complete == None) | (tbl.c.complete != 1))))
100 res = conn.execute(q,
101 complete=1,
102 results=results,
103 complete_at=complete_at)
104
105 if res.rowcount != 1:
106 raise KeyError
107 return self.db.pool.do(thd)
108
110 def thd(conn):
111 bs_tbl = self.db.model.buildsets
112 q = bs_tbl.select(whereclause=(bs_tbl.c.id == bsid))
113 res = conn.execute(q)
114 row = res.fetchone()
115 if not row:
116 return None
117 return self._row2dict(row)
118 return self.db.pool.do(thd)
119
121 def thd(conn):
122 bs_tbl = self.db.model.buildsets
123 q = bs_tbl.select()
124 if complete is not None:
125 if complete:
126 q = q.where(bs_tbl.c.complete != 0)
127 else:
128 q = q.where((bs_tbl.c.complete == 0) |
129 (bs_tbl.c.complete == None))
130 res = conn.execute(q)
131 return [ self._row2dict(row) for row in res.fetchall() ]
132 return self.db.pool.do(thd)
133
136 def thd(conn):
137 bs_tbl = self.db.model.buildsets
138 ss_tbl = self.db.model.sourcestamps
139 j = sa.join(self.db.model.buildsets,
140 self.db.model.sourcestampsets)
141 j = j.join(self.db.model.sourcestamps)
142 q = sa.select(columns=[bs_tbl], from_obj=[j],
143 distinct=True)
144 q = q.order_by(sa.desc(bs_tbl.c.submitted_at))
145 q = q.limit(count)
146
147 if complete is not None:
148 if complete:
149 q = q.where(bs_tbl.c.complete != 0)
150 else:
151 q = q.where((bs_tbl.c.complete == 0) |
152 (bs_tbl.c.complete == None))
153 if branch:
154 q = q.where(ss_tbl.c.branch == branch)
155 if repository:
156 q = q.where(ss_tbl.c.repository == repository)
157 res = conn.execute(q)
158 return list(reversed([ self._row2dict(row)
159 for row in res.fetchall() ]))
160 return self.db.pool.do(thd)
161
163 """
164 Return the properties for a buildset, in the same format they were
165 given to L{addBuildset}.
166
167 Note that this method does not distinguish a nonexistent buildset from
168 a buildset with no properties, and returns C{{}} in either case.
169
170 @param buildsetid: buildset ID
171
172 @returns: dictionary mapping property name to (value, source), via
173 Deferred
174 """
175 def thd(conn):
176 bsp_tbl = self.db.model.buildset_properties
177 q = sa.select(
178 [ bsp_tbl.c.property_name, bsp_tbl.c.property_value ],
179 whereclause=(bsp_tbl.c.buildsetid == buildsetid))
180 l = []
181 for row in conn.execute(q):
182 try:
183 properties = json.loads(row.property_value)
184 l.append((row.property_name,
185 tuple(properties)))
186 except ValueError:
187 pass
188 return dict(l)
189 return self.db.pool.do(thd)
190
192 def mkdt(epoch):
193 if epoch:
194 return epoch2datetime(epoch)
195 return BsDict(external_idstring=row.external_idstring,
196 reason=row.reason, sourcestampsetid=row.sourcestampsetid,
197 submitted_at=mkdt(row.submitted_at),
198 complete=bool(row.complete),
199 complete_at=mkdt(row.complete_at), results=row.results,
200 bsid=row.id)
201