# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-from buildfarm import (
- BuildFarm,
+from buildfarm.tree import (
Tree,
)
from buildfarm.build import (
- Build,
- BuildResultStore,
- BuildStatus,
- NoSuchBuildError,
+ StormBuild,
+ Test,
+ TestResult,
)
from buildfarm.hostdb import (
Host,
NoSuchHost,
)
-import os
+
try:
from pysqlite2 import dbapi2 as sqlite3
except ImportError:
import sqlite3
from storm.database import create_database
from storm.expr import EXPR, FuncExpr, compile
-from storm.locals import Bool, Desc, Int, Unicode, RawStr
+from storm.locals import Bool, Desc, Int, RawStr, Reference, Unicode
from storm.store import Store
return "CAST(%s AS %s)" % (column, cast.type)
-class StormBuild(Build):
- __storm_table__ = "build"
-
- id = Int(primary=True)
- tree = RawStr()
- revision = RawStr()
- host = RawStr()
- compiler = RawStr()
- checksum = RawStr()
- upload_time = Int(name="age")
- status_str = RawStr(name="status")
- basename = RawStr()
- host_id = Int()
- tree_id = Int()
- compiler_id = Int()
-
- def status(self):
- return BuildStatus.__deserialize__(self.status_str)
-
- def revision_details(self):
- return self.revision
-
- def log_checksum(self):
- return self.checksum
-
- def remove(self):
- super(StormBuild, self).remove()
- Store.of(self).remove(self)
-
- def remove_logs(self):
- super(StormBuild, self).remove_logs()
- self.basename = None
-
-
class StormHost(Host):
__storm_table__ = "host"
return self.store.find(StormHost).order_by(StormHost.name)
def __getitem__(self, name):
- result = self.store.find(StormHost, Cast(StormHost.name, "TEXT") == Cast(name, "TEXT"))
+ result = self.store.find(StormHost,
+ Cast(StormHost.name, "TEXT") == Cast(name, "TEXT"))
ret = result.one()
if ret is None:
raise NoSuchHost(name)
self.store.commit()
-class StormCachingBuildResultStore(BuildResultStore):
-
- def __init__(self, basedir, store=None):
- super(StormCachingBuildResultStore, self).__init__(basedir)
-
- if store is None:
- store = memory_store()
-
- self.store = store
-
- def __contains__(self, build):
- return not (self.store.find(StormBuild,
- Cast(StormBuild.checksum, "TEXT") == build.log_checksum()).is_empty())
-
- def get_previous_revision(self, tree, host, compiler, revision):
- result = self.store.find(StormBuild,
- StormBuild.tree == tree,
- StormBuild.host == host,
- StormBuild.compiler == compiler,
- Cast(StormBuild.revision, "TEXT") == revision)
- cur_build = result.any()
- if cur_build is None:
- raise NoSuchBuildError(tree, host, compiler, revision)
-
- result = self.store.find(StormBuild,
- StormBuild.tree == tree,
- StormBuild.host == host,
- StormBuild.compiler == compiler,
- Cast(StormBuild.revision, "TEXT") != revision,
- StormBuild.id < cur_build.id)
- result = result.order_by(Desc(StormBuild.id))
- prev_build = result.first()
- if prev_build is None:
- raise NoSuchBuildError(tree, host, compiler, revision)
- return prev_build.revision
-
- def get_latest_revision(self, tree, host, compiler):
- result = self.store.find(StormBuild,
- StormBuild.tree == tree,
- StormBuild.host == host,
- StormBuild.compiler == compiler)
- result = result.order_by(Desc(StormBuild.id))
- build = result.first()
- if build is None:
- raise NoSuchBuildError(tree, host, compiler)
- return build.revision
-
- def upload_build(self, build):
- existing_build = self.store.find(StormBuild,
- Cast(StormBuild.checksum, "TEXT") == build.log_checksum()).order_by(StormBuild.upload_time).first()
- if existing_build is not None:
- # Already present
- assert build.tree == existing_build.tree
- assert build.host == existing_build.host
- assert build.compiler == existing_build.compiler
- return existing_build
- rev = build.revision_details()
- super(StormCachingBuildResultStore, self).upload_build(build)
- new_basename = self.build_fname(build.tree, build.host, build.compiler, rev)
- new_build = StormBuild(new_basename, build.tree, build.host,
- build.compiler, rev)
- new_build.checksum = build.log_checksum()
- new_build.upload_time = build.upload_time
- new_build.status_str = build.status().__serialize__()
- new_build.basename = new_basename
- new_build.host_id = self.store.find(
- StormHost, Cast(StormHost.name, "TEXT") == build.host).one().id
- self.store.add(new_build)
- return new_build
-
- def get_old_builds(self, tree, host, compiler):
- result = self.store.find(StormBuild,
- StormBuild.tree == tree,
- StormBuild.host == host,
- StormBuild.compiler == compiler)
- return result.order_by(Desc(StormBuild.upload_time))
-
- def get_build(self, tree, host, compiler, revision=None, checksum=None):
- expr = [
- StormBuild.tree == tree,
- StormBuild.host == host,
- StormBuild.compiler == compiler,
- ]
- if revision is not None:
- expr.append(Cast(StormBuild.revision, "TEXT") == revision)
- if checksum is not None:
- expr.append(Cast(StormBuild.checksum, "TEXT") == checksum)
- result = self.store.find(StormBuild, *expr).order_by(Desc(StormBuild.upload_time))
- ret = result.first()
- if ret is None:
- raise NoSuchBuildError(tree, host, compiler, revision)
- return ret
-
-
def distinct_builds(builds):
done = set()
for build in builds:
yield build
-class StormCachingBuildFarm(BuildFarm):
-
- def __init__(self, path=None, store=None, timeout=0.5):
- self.timeout = timeout
- self.store = store
- super(StormCachingBuildFarm, self).__init__(path)
-
- def _get_store(self):
- if self.store is not None:
- return self.store
- db_path = os.path.join(self.path, "db", "hostdb.sqlite")
- db = create_database("sqlite:%s?timeout=%f" % (db_path, self.timeout))
- self.store = Store(db)
- setup_schema(self.store)
- return self.store
-
- def _open_hostdb(self):
- return StormHostDatabase(self._get_store())
-
- def _open_build_results(self):
- path = os.path.join(self.path, "data", "oldrevs")
- return StormCachingBuildResultStore(path, self._get_store())
-
- def get_host_builds(self, host):
- result = self._get_store().find(StormBuild, StormBuild.host == host)
- return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
-
- def get_tree_builds(self, tree):
- result = self._get_store().find(StormBuild, Cast(StormBuild.tree, "TEXT") == tree)
- return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
-
- def get_last_builds(self):
- result = self._get_store().find(StormBuild)
- return distinct_builds(result.order_by(Desc(StormBuild.upload_time)))
-
- def get_revision_builds(self, tree, revision=None):
- return self._get_store().find(StormBuild,
- Cast(StormBuild.tree, "TEXT") == tree,
- Cast(StormBuild.revision, "TEXT") == revision)
-
- def commit(self):
- self.store.commit()
-
-
class StormTree(Tree):
__storm_table__ = "tree"
scm = RawStr()
+class StormTest(Test):
+ __storm_table__ = "test"
+
+ id = Int(primary=True)
+ name = RawStr()
+
+
+class StormTestResult(TestResult):
+ __storm_table__ = "test_result"
+
+ id = Int(primary=True)
+ build_id = Int(name="build")
+ build = Reference(build_id, StormBuild)
+
+ test_id = Int(name="test")
+ test = Reference(test_id, StormTest)
+
+
def setup_schema(db):
db.execute("PRAGMA foreign_keys = 1;", noresult=True)
db.execute("""
db.execute("""
CREATE UNIQUE INDEX IF NOT EXISTS unique_compiler_name ON compiler(name);
""", noresult=True)
+ db.execute("""
+CREATE TABLE IF NOT EXISTS test (
+ id integer primary key autoincrement,
+ name text not null);
+ """, noresult=True)
+ db.execute("CREATE UNIQUE INDEX IF NOT EXISTS test_name ON test(name);",
+ noresult=True)
+ db.execute("""CREATE TABLE IF NOT EXISTS test_result (
+ build int,
+ test int,
+ result int
+ );""", noresult=True)
+ db.execute("""CREATE UNIQUE INDEX IF NOT EXISTS build_test_result ON test_result(build, test);""", noresult=True)
def memory_store():