"Fossies" - the Fresh Open Source Software Archive

Member "buildbot-2.3.1/buildbot/db/schedulers.py" (23 May 2019, 8213 Bytes) of package /linux/misc/buildbot-2.3.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "schedulers.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.0_vs_2.0.0.

    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 import sqlalchemy as sa
   17 import sqlalchemy.exc
   18 
   19 from twisted.internet import defer
   20 
   21 from buildbot.db import NULL
   22 from buildbot.db import base
   23 
   24 
   25 class SchedulerAlreadyClaimedError(Exception):
   26     pass
   27 
   28 
   29 class SchedulersConnectorComponent(base.DBConnectorComponent):
   30     # Documentation is in developer/db.rst
   31 
   32     # returns a Deferred that returns None
   33     def enable(self, schedulerid, v):
   34         def thd(conn):
   35             tbl = self.db.model.schedulers
   36             q = tbl.update(whereclause=(tbl.c.id == schedulerid))
   37             conn.execute(q, enabled=int(v))
   38         return self.db.pool.do(thd)
   39 
   40     # returns a Deferred that returns None
   41     def classifyChanges(self, schedulerid, classifications):
   42         def thd(conn):
   43             tbl = self.db.model.scheduler_changes
   44             ins_q = tbl.insert()
   45             upd_q = tbl.update(
   46                 ((tbl.c.schedulerid == schedulerid) &
   47                  (tbl.c.changeid == sa.bindparam('wc_changeid'))))
   48             for changeid, important in classifications.items():
   49                 transaction = conn.begin()
   50                 # convert the 'important' value into an integer, since that
   51                 # is the column type
   52                 imp_int = int(bool(important))
   53                 try:
   54                     conn.execute(ins_q,
   55                                  schedulerid=schedulerid,
   56                                  changeid=changeid,
   57                                  important=imp_int).close()
   58                 except (sqlalchemy.exc.ProgrammingError,
   59                         sqlalchemy.exc.IntegrityError):
   60                     transaction.rollback()
   61                     transaction = conn.begin()
   62                     # insert failed, so try an update
   63                     conn.execute(upd_q,
   64                                  wc_changeid=changeid,
   65                                  important=imp_int).close()
   66 
   67                 transaction.commit()
   68         return self.db.pool.do(thd)
   69 
   70     # returns a Deferred that returns None
   71     def flushChangeClassifications(self, schedulerid, less_than=None):
   72         def thd(conn):
   73             sch_ch_tbl = self.db.model.scheduler_changes
   74             wc = (sch_ch_tbl.c.schedulerid == schedulerid)
   75             if less_than is not None:
   76                 wc = wc & (sch_ch_tbl.c.changeid < less_than)
   77             q = sch_ch_tbl.delete(whereclause=wc)
   78             conn.execute(q).close()
   79         return self.db.pool.do(thd)
   80 
   81     # returns a Deferred that returns a value
   82     def getChangeClassifications(self, schedulerid, branch=-1,
   83                                  repository=-1, project=-1,
   84                                  codebase=-1):
   85         # -1 here stands for "argument not given", since None has meaning
   86         # as a branch
   87         def thd(conn):
   88             sch_ch_tbl = self.db.model.scheduler_changes
   89             ch_tbl = self.db.model.changes
   90 
   91             wc = (sch_ch_tbl.c.schedulerid == schedulerid)
   92 
   93             # may need to filter further based on branch, etc
   94             extra_wheres = []
   95             if branch != -1:
   96                 extra_wheres.append(ch_tbl.c.branch == branch)
   97             if repository != -1:
   98                 extra_wheres.append(ch_tbl.c.repository == repository)
   99             if project != -1:
  100                 extra_wheres.append(ch_tbl.c.project == project)
  101             if codebase != -1:
  102                 extra_wheres.append(ch_tbl.c.codebase == codebase)
  103 
  104             # if we need to filter further append those, as well as a join
  105             # on changeid (but just once for that one)
  106             if extra_wheres:
  107                 wc &= (sch_ch_tbl.c.changeid == ch_tbl.c.changeid)
  108                 for w in extra_wheres:
  109                     wc &= w
  110 
  111             q = sa.select(
  112                 [sch_ch_tbl.c.changeid, sch_ch_tbl.c.important],
  113                 whereclause=wc)
  114             return {r.changeid: [False, True][r.important]
  115                     for r in conn.execute(q)}
  116         return self.db.pool.do(thd)
  117 
  118     def findSchedulerId(self, name):
  119         tbl = self.db.model.schedulers
  120         name_hash = self.hashColumns(name)
  121         return self.findSomethingId(
  122             tbl=tbl,
  123             whereclause=(tbl.c.name_hash == name_hash),
  124             insert_values=dict(
  125                 name=name,
  126                 name_hash=name_hash,
  127             ))
  128 
  129     # returns a Deferred that returns None
  130     def setSchedulerMaster(self, schedulerid, masterid):
  131         def thd(conn):
  132             sch_mst_tbl = self.db.model.scheduler_masters
  133 
  134             # handle the masterid=None case to get it out of the way
  135             if masterid is None:
  136                 q = sch_mst_tbl.delete(
  137                     whereclause=(sch_mst_tbl.c.schedulerid == schedulerid))
  138                 conn.execute(q).close()
  139                 return
  140 
  141             # try a blind insert..
  142             try:
  143                 q = sch_mst_tbl.insert()
  144                 conn.execute(q,
  145                              dict(schedulerid=schedulerid, masterid=masterid)).close()
  146             except (sa.exc.IntegrityError, sa.exc.ProgrammingError):
  147                 # someone already owns this scheduler, but who?
  148                 join = self.db.model.masters.outerjoin(
  149                     sch_mst_tbl,
  150                     (self.db.model.masters.c.id == sch_mst_tbl.c.masterid))
  151 
  152                 q = sa.select([self.db.model.masters.c.name,
  153                                sch_mst_tbl.c.masterid], from_obj=join, whereclause=(
  154                     sch_mst_tbl.c.schedulerid == schedulerid))
  155                 row = conn.execute(q).fetchone()
  156                 # ok, that was us, so we just do nothing
  157                 if row['masterid'] == masterid:
  158                     return
  159                 raise SchedulerAlreadyClaimedError(
  160                     "already claimed by {}".format(row['name']))
  161 
  162         return self.db.pool.do(thd)
  163 
  164     @defer.inlineCallbacks
  165     def getScheduler(self, schedulerid):
  166         sch = yield self.getSchedulers(_schedulerid=schedulerid)
  167         if sch:
  168             return sch[0]
  169 
  170     # returns a Deferred that returns a value
  171     def getSchedulers(self, active=None, masterid=None, _schedulerid=None):
  172         def thd(conn):
  173             sch_tbl = self.db.model.schedulers
  174             sch_mst_tbl = self.db.model.scheduler_masters
  175 
  176             # handle the trivial case of masterid=xx and active=False
  177             if masterid is not None and active is not None and not active:
  178                 return []
  179 
  180             join = sch_tbl.outerjoin(sch_mst_tbl,
  181                                      (sch_tbl.c.id == sch_mst_tbl.c.schedulerid))
  182 
  183             # if we're given a _schedulerid, select only that row
  184             wc = None
  185             if _schedulerid:
  186                 wc = (sch_tbl.c.id == _schedulerid)
  187             else:
  188                 # otherwise, filter with active, if necessary
  189                 if masterid is not None:
  190                     wc = (sch_mst_tbl.c.masterid == masterid)
  191                 elif active:
  192                     wc = (sch_mst_tbl.c.masterid != NULL)
  193                 elif active is not None:
  194                     wc = (sch_mst_tbl.c.masterid == NULL)
  195 
  196             q = sa.select([sch_tbl.c.id, sch_tbl.c.name, sch_tbl.c.enabled,
  197                            sch_mst_tbl.c.masterid],
  198                           from_obj=join, whereclause=wc)
  199 
  200             return [dict(id=row.id, name=row.name, enabled=bool(row.enabled),
  201                          masterid=row.masterid)
  202                     for row in conn.execute(q).fetchall()]
  203         return self.db.pool.do(thd)