Package buildbot :: Package db :: Module buildsets
[frames] | no frames]

Source Code for Module buildbot.db.buildsets

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 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   
26 -class BsDict(dict):
27 pass
28
29 -class BuildsetsConnectorComponent(base.DBConnectorComponent):
30 # Documentation is in developer/database.rst 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 # insert the buildset itself 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 # add any properties 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 # and finish with a build request for each builder. Note that 66 # sqlalchemy and the Python DBAPI do not provide a way to recover 67 # inserted IDs from a multi-row insert, so this is done one row at 68 # a time. 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
87 - def completeBuildset(self, bsid, results, complete_at=None, 88 _reactor=reactor):
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
109 - def getBuildset(self, bsid):
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
120 - def getBuildsets(self, complete=None):
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
134 - def getRecentBuildsets(self, count, branch=None, repository=None, 135 complete=None):
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
162 - def getBuildsetProperties(self, buildsetid):
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
191 - def _row2dict(self, row):
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