1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import itertools
17 import sqlalchemy as sa
18 from twisted.internet import reactor
19 from twisted.python import log
20 from buildbot.db import base
21 from buildbot.util import epoch2datetime, datetime2epoch
25
28
31
35 def wrap(self, *args, **kwargs):
36 d = self.db.master.getObjectId()
37 d.addCallback(lambda master_objectid :
38 fn(self, _master_objectid=master_objectid, *args, **kwargs))
39 return d
40 wrap.__name__ = fn.__name__
41 wrap.__doc__ = fn.__doc__
42 return wrap
43
45
46
47 @with_master_objectid
49 def thd(conn):
50 reqs_tbl = self.db.model.buildrequests
51 claims_tbl = self.db.model.buildrequest_claims
52 res = conn.execute(sa.select([
53 reqs_tbl.outerjoin(claims_tbl,
54 (reqs_tbl.c.id == claims_tbl.c.brid)) ],
55 whereclause=(reqs_tbl.c.id == brid)))
56 row = res.fetchone()
57
58 rv = None
59 if row:
60 rv = self._brdictFromRow(row, _master_objectid)
61 res.close()
62 return rv
63 return self.db.pool.do(thd)
64
65 @with_master_objectid
66 - def getBuildRequests(self, buildername=None, complete=None, claimed=None,
67 bsid=None, _master_objectid=None):
68 def thd(conn):
69 reqs_tbl = self.db.model.buildrequests
70 claims_tbl = self.db.model.buildrequest_claims
71 q = sa.select([ reqs_tbl.outerjoin(claims_tbl,
72 reqs_tbl.c.id == claims_tbl.c.brid) ])
73 if claimed is not None:
74 if not claimed:
75 q = q.where(
76 (claims_tbl.c.claimed_at == None) &
77 (reqs_tbl.c.complete == 0))
78 elif claimed == "mine":
79 q = q.where(
80 (claims_tbl.c.objectid == _master_objectid))
81 else:
82 q = q.where(
83 (claims_tbl.c.claimed_at != None))
84 if buildername is not None:
85 q = q.where(reqs_tbl.c.buildername == buildername)
86 if complete is not None:
87 if complete:
88 q = q.where(reqs_tbl.c.complete != 0)
89 else:
90 q = q.where(reqs_tbl.c.complete == 0)
91 if bsid is not None:
92 q = q.where(reqs_tbl.c.buildsetid == bsid)
93 res = conn.execute(q)
94
95 return [ self._brdictFromRow(row, _master_objectid)
96 for row in res.fetchall() ]
97 return self.db.pool.do(thd)
98
99 @with_master_objectid
102 if claimed_at is not None:
103 claimed_at = datetime2epoch(claimed_at)
104 else:
105 claimed_at = _reactor.seconds()
106
107 def thd(conn):
108 transaction = conn.begin()
109 tbl = self.db.model.buildrequest_claims
110
111 try:
112 q = tbl.insert()
113 conn.execute(q, [ dict(brid=id, objectid=_master_objectid,
114 claimed_at=claimed_at)
115 for id in brids ])
116 except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
117 transaction.rollback()
118 raise AlreadyClaimedError
119
120 transaction.commit()
121
122 return self.db.pool.do(thd)
123
124 @with_master_objectid
127 def thd(conn):
128 transaction = conn.begin()
129 tbl = self.db.model.buildrequest_claims
130 claimed_at = _reactor.seconds()
131
132
133
134 iterator = iter(brids)
135
136 while 1:
137 batch = list(itertools.islice(iterator, 100))
138 if not batch:
139 break
140
141 q = tbl.update(tbl.c.brid.in_(batch)
142 & (tbl.c.objectid==_master_objectid))
143 res = conn.execute(q, claimed_at=claimed_at)
144
145
146
147 if res.rowcount != len(batch):
148 transaction.rollback()
149 raise AlreadyClaimedError
150
151 transaction.commit()
152 return self.db.pool.do(thd)
153
154 @with_master_objectid
156 def thd(conn):
157 transaction = conn.begin()
158 claims_tbl = self.db.model.buildrequest_claims
159
160
161
162 iterator = iter(brids)
163
164 while 1:
165 batch = list(itertools.islice(iterator, 100))
166 if not batch:
167 break
168
169 try:
170 q = claims_tbl.delete(
171 (claims_tbl.c.brid.in_(batch))
172 & (claims_tbl.c.objectid == _master_objectid))
173 conn.execute(q)
174 except:
175 transaction.rollback()
176 raise
177
178 transaction.commit()
179 return self.db.pool.do(thd)
180
181 @with_master_objectid
184 if complete_at is not None:
185 complete_at = datetime2epoch(complete_at)
186 else:
187 complete_at = _reactor.seconds()
188
189 def thd(conn):
190 transaction = conn.begin()
191
192
193
194
195
196
197 reqs_tbl = self.db.model.buildrequests
198
199
200
201 iterator = iter(brids)
202
203 while 1:
204 batch = list(itertools.islice(iterator, 100))
205 if not batch:
206 break
207
208 q = reqs_tbl.update()
209 q = q.where(reqs_tbl.c.id.in_(batch))
210 q = q.where(reqs_tbl.c.complete != 1)
211 res = conn.execute(q,
212 complete=1,
213 results=results,
214 complete_at=complete_at)
215
216
217 if res.rowcount != len(batch):
218 log.msg("tried to complete %d buildreqests, "
219 "but only completed %d" % (len(batch), res.rowcount))
220 transaction.rollback()
221 raise NotClaimedError
222 transaction.commit()
223 return self.db.pool.do(thd)
224
226 def thd(conn):
227 reqs_tbl = self.db.model.buildrequests
228 claims_tbl = self.db.model.buildrequest_claims
229 old_epoch = _reactor.seconds() - old
230
231
232 expired_brids = sa.select([ reqs_tbl.c.id ],
233 whereclause=(reqs_tbl.c.complete != 1))
234 res = conn.execute(claims_tbl.delete(
235 (claims_tbl.c.claimed_at < old_epoch) &
236 claims_tbl.c.brid.in_(expired_brids)))
237 return res.rowcount
238 d = self.db.pool.do(thd)
239 def log_nonzero_count(count):
240 if count != 0:
241 log.msg("unclaimed %d expired buildrequests (over %d seconds "
242 "old)" % (count, old))
243 d.addCallback(log_nonzero_count)
244 return d
245
247 claimed = mine = False
248 claimed_at = None
249 if row.claimed_at is not None:
250 claimed_at = row.claimed_at
251 claimed = True
252 mine = row.objectid == master_objectid
253
254 def mkdt(epoch):
255 if epoch:
256 return epoch2datetime(epoch)
257 submitted_at = mkdt(row.submitted_at)
258 complete_at = mkdt(row.complete_at)
259 claimed_at = mkdt(row.claimed_at)
260
261 return BrDict(brid=row.id, buildsetid=row.buildsetid,
262 buildername=row.buildername, priority=row.priority,
263 claimed=claimed, claimed_at=claimed_at, mine=mine,
264 complete=bool(row.complete), results=row.results,
265 submitted_at=submitted_at, complete_at=complete_at)
266