1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16  """ 
 17  (Very partial) support for builds in the database 
 18  """ 
 19   
 20  from twisted.internet import reactor 
 21  from buildbot.db import base 
 22  from buildbot.util import epoch2datetime 
 23   
 25      """ 
 26      A DBConnectorComponent to handle a little bit of information about builds. 
 27      Avaialble at C{master.db.buildrequests}. 
 28   
 29      NOTE: The interface for this module will change - the builds table 
 30      duplicates some information available in pickles, without including all 
 31      such information.  Do not depend on this API. 
 32   
 33      Note that a single build may be represented in many rows in the builds 
 34      table, as it the builds table represents  
 35   
 36      Builds are represented as dictionaries with keys C{bid} (the build ID, 
 37      globally unique), C{number} (the build number, unique only within this 
 38      master and builder), C{brid} (the ID of the build request that caused this 
 39      build), C{start_time}, and C{finish_time} (datetime objects, or None). 
 40      """ 
 41   
 43          """ 
 44          Get a single build, in the format described above.  Returns 
 45          C{None} if there is no such build. 
 46   
 47          @param bid: build id 
 48          @type bid: integer 
 49   
 50          @returns: Build dictionary as above or None, via Deferred 
 51          """ 
 52          def thd(conn): 
 53              tbl = self.db.model.builds 
 54              res = conn.execute(tbl.select(whereclause=(tbl.c.id == bid))) 
 55              row = res.fetchone() 
 56   
 57              rv = None 
 58              if row: 
 59                  rv = self._bdictFromRow(row) 
 60              res.close() 
 61              return rv 
  62          return self.db.pool.do(thd) 
  63   
 65          """ 
 66          Get a list of builds for the given build request.  The resulting 
 67          build dictionaries are in exactly the same format as for L{getBuild}. 
 68   
 69          @param brids: list of build request ids 
 70   
 71          @returns: List of build dictionaries as above, via Deferred 
 72          """ 
 73          def thd(conn): 
 74              tbl = self.db.model.builds 
 75              q = tbl.select(whereclause=(tbl.c.brid == brid)) 
 76              res = conn.execute(q) 
 77              return [ self._bdictFromRow(row) for row in res.fetchall() ] 
  78          return self.db.pool.do(thd) 
 79   
 81          """ 
 82          Add a new build, recorded as having started now. 
 83   
 84          @param brid: build request id 
 85          @param number: build number 
 86   
 87          @param _reactor: reactor to use (for testing) 
 88          @param _race_hook: hook for testing 
 89   
 90          @returns: build ID via Deferred 
 91          """ 
 92   
 93          def thd(conn): 
 94              start_time = _reactor.seconds() 
 95              r = conn.execute(self.db.model.builds.insert(), 
 96                      dict(number=number, brid=brid, start_time=start_time, 
 97                          finish_time=None)) 
 98              return r.inserted_primary_key[0] 
  99          return self.db.pool.do(thd) 
100   
102          """ 
103   
104          Mark builds as finished, with C{finish_time} now.  This is done 
105          unconditionally, even if the builds are already finished. 
106   
107          @param bids: build ids 
108          @type bids: list 
109   
110          @param _reactor: reactor to use (for testing) 
111   
112          @returns: Deferred 
113          """ 
114          def thd(conn): 
115              tbl = self.db.model.builds 
116              now = _reactor.seconds() 
117   
118               
119               
120              remaining = bids 
121              while remaining: 
122                  batch, remaining = remaining[:100], remaining[100:] 
123                  q = tbl.update(whereclause=(tbl.c.id.in_(batch))) 
124                  conn.execute(q, finish_time=now) 
 125          return self.db.pool.do(thd) 
126   
128          def mkdt(epoch): 
129              if epoch: 
130                  return epoch2datetime(epoch) 
 131   
132          return dict( 
133              bid=row.id, 
134              brid=row.brid, 
135              number=row.number, 
136              start_time=mkdt(row.start_time), 
137              finish_time=mkdt(row.finish_time)) 
138