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 self.check_length(bs_props_tbl.c.property_value, 63 i['property_value']) 64 65 conn.execute(bs_props_tbl.insert(), inserts) 66 67 # and finish with a build request for each builder. Note that 68 # sqlalchemy and the Python DBAPI do not provide a way to recover 69 # inserted IDs from a multi-row insert, so this is done one row at 70 # a time. 71 brids = {} 72 br_tbl = self.db.model.buildrequests 73 ins = br_tbl.insert() 74 for buildername in builderNames: 75 self.check_length(br_tbl.c.buildername, buildername) 76 r = conn.execute(ins, 77 dict(buildsetid=bsid, buildername=buildername, priority=0, 78 claimed_at=0, claimed_by_name=None, 79 claimed_by_incarnation=None, complete=0, results=-1, 80 submitted_at=submitted_at, complete_at=None)) 81 82 brids[buildername] = r.inserted_primary_key[0] 83 84 transaction.commit() 85 86 return (bsid, brids)
87 return self.db.pool.do(thd)
88
89 - def completeBuildset(self, bsid, results, complete_at=None, 90 _reactor=reactor):
91 if complete_at is not None: 92 complete_at = datetime2epoch(complete_at) 93 else: 94 complete_at = _reactor.seconds() 95 96 def thd(conn): 97 tbl = self.db.model.buildsets 98 99 q = tbl.update(whereclause=( 100 (tbl.c.id == bsid) & 101 ((tbl.c.complete == None) | (tbl.c.complete != 1)))) 102 res = conn.execute(q, 103 complete=1, 104 results=results, 105 complete_at=complete_at) 106 107 if res.rowcount != 1: 108 raise KeyError
109 return self.db.pool.do(thd) 110
111 - def getBuildset(self, bsid):
112 def thd(conn): 113 bs_tbl = self.db.model.buildsets 114 q = bs_tbl.select(whereclause=(bs_tbl.c.id == bsid)) 115 res = conn.execute(q) 116 row = res.fetchone() 117 if not row: 118 return None 119 return self._row2dict(row)
120 return self.db.pool.do(thd) 121
122 - def getBuildsets(self, complete=None):
123 def thd(conn): 124 bs_tbl = self.db.model.buildsets 125 q = bs_tbl.select() 126 if complete is not None: 127 if complete: 128 q = q.where(bs_tbl.c.complete != 0) 129 else: 130 q = q.where((bs_tbl.c.complete == 0) | 131 (bs_tbl.c.complete == None)) 132 res = conn.execute(q) 133 return [ self._row2dict(row) for row in res.fetchall() ]
134 return self.db.pool.do(thd) 135
136 - def getBuildsetProperties(self, buildsetid):
137 """ 138 Return the properties for a buildset, in the same format they were 139 given to L{addBuildset}. 140 141 Note that this method does not distinguish a nonexistent buildset from 142 a buildset with no properties, and returns C{{}} in either case. 143 144 @param buildsetid: buildset ID 145 146 @returns: dictionary mapping property name to (value, source), via 147 Deferred 148 """ 149 def thd(conn): 150 bsp_tbl = self.db.model.buildset_properties 151 q = sa.select( 152 [ bsp_tbl.c.property_name, bsp_tbl.c.property_value ], 153 whereclause=(bsp_tbl.c.buildsetid == buildsetid)) 154 l = [] 155 for row in conn.execute(q): 156 try: 157 properties = json.loads(row.property_value) 158 l.append((row.property_name, 159 tuple(properties))) 160 except ValueError: 161 pass 162 return dict(l)
163 return self.db.pool.do(thd) 164
165 - def _row2dict(self, row):
166 def mkdt(epoch): 167 if epoch: 168 return epoch2datetime(epoch)
169 return BsDict(external_idstring=row.external_idstring, 170 reason=row.reason, sourcestampsetid=row.sourcestampsetid, 171 submitted_at=mkdt(row.submitted_at), 172 complete=bool(row.complete), 173 complete_at=mkdt(row.complete_at), results=row.results, 174 bsid=row.id) 175