| author | paulson | 
| Sun, 13 Apr 2025 23:01:03 +0100 | |
| changeset 82502 | f72b374b6a69 | 
| parent 82142 | 508a673c87ac | 
| child 82720 | 956ecf2c07a0 | 
| permissions | -rw-r--r-- | 
| 79502 | 1 | /* Title: Pure/Build/build_process.scala | 
| 77238 | 2 | Author: Makarius | 
| 3 | ||
| 4 | Build process for sessions, with build database, optional heap, and | |
| 5 | optional presentation. | |
| 6 | */ | |
| 7 | ||
| 8 | package isabelle | |
| 9 | ||
| 10 | ||
| 77246 | 11 | import scala.math.Ordering | 
| 12 | ||
| 13 | ||
| 77238 | 14 | object Build_Process {
 | 
| 78421 | 15 | /** state vs. database **/ | 
| 77257 | 16 | |
| 78238 | 17 | sealed case class Build( | 
| 78173 | 18 | build_uuid: String, // Database_Progress.context_uuid | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 19 | build_id: Long, | 
| 77660 | 20 | ml_platform: String, | 
| 21 | options: String, | |
| 22 | start: Date, | |
| 78226 | 23 | stop: Option[Date], | 
| 24 | sessions: List[String] | |
| 78222 | 25 |   ) {
 | 
| 26 | def active: Boolean = stop.isEmpty | |
| 79845 | 27 | def active_build_uuid: Option[String] = if (active) Some(build_uuid) else None | 
| 78633 | 28 | |
| 29 | def print: String = | |
| 30 | build_uuid + " (platform: " + ml_platform + ", start: " + Build_Log.print_date(start) + | |
| 31 | if_proper(stop, ", stop: " + Build_Log.print_date(stop.get)) + ")" | |
| 78222 | 32 | } | 
| 77660 | 33 | |
| 78238 | 34 | sealed case class Worker( | 
| 78173 | 35 | worker_uuid: String, // Database_Progress.agent_uuid | 
| 77631 | 36 | build_uuid: String, | 
| 37 | start: Date, | |
| 38 | stamp: Date, | |
| 39 | stop: Option[Date], | |
| 40 | serial: Long | |
| 41 | ) | |
| 42 | ||
| 79829 | 43 |   object Task {
 | 
| 44 | type Entry = (String, Task) | |
| 45 | def entry(session: Build_Job.Session_Context, build_context: isabelle.Build.Context): Entry = | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 46 | session.name -> Task(session.name, session.deps, build_context.build_uuid) | 
| 79829 | 47 | } | 
| 48 | ||
| 78238 | 49 | sealed case class Task( | 
| 77631 | 50 | name: String, | 
| 51 | deps: List[String], | |
| 77661 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 wenzelm parents: 
77660diff
changeset | 52 | build_uuid: String | 
| 80270 | 53 |   ) extends Name.T {
 | 
| 77313 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 wenzelm parents: 
77312diff
changeset | 54 | def is_ready: Boolean = deps.isEmpty | 
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 55 | def resolve(dep: String): Option[Task] = | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 56 | if (deps.contains(dep)) Some(copy(deps = deps.filterNot(_ == dep))) else None | 
| 77313 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 wenzelm parents: 
77312diff
changeset | 57 | } | 
| 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 wenzelm parents: 
77312diff
changeset | 58 | |
| 78238 | 59 | sealed case class Job( | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 60 | name: String, | 
| 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 61 | worker_uuid: String, | 
| 77634 | 62 | build_uuid: String, | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 63 | node_info: Host.Node_Info, | 
| 78841 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 Fabian Huch <huch@in.tum.de> parents: 
78839diff
changeset | 64 | start_date: Date, | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 65 | build: Option[Build_Job] | 
| 80270 | 66 | ) extends Name.T | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 67 | |
| 78238 | 68 | sealed case class Result( | 
| 77651 | 69 | name: String, | 
| 70 | worker_uuid: String, | |
| 71 | build_uuid: String, | |
| 72 | node_info: Host.Node_Info, | |
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 73 | start_date: Date, | 
| 77461 | 74 | process_result: Process_Result, | 
| 77460 
ccca589d7027
tuned signature: support general Build_Job instances;
 wenzelm parents: 
77459diff
changeset | 75 | output_shasum: SHA1.Shasum, | 
| 77461 | 76 | current: Boolean | 
| 80270 | 77 |   ) extends Name.T {
 | 
| 77259 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 wenzelm parents: 
77258diff
changeset | 78 | def ok: Boolean = process_result.ok | 
| 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 wenzelm parents: 
77258diff
changeset | 79 | } | 
| 77312 | 80 | |
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 81 |   object Sessions {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 82 | type Graph = isabelle.Graph[String, Build_Job.Session_Context] | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 83 | val empty: Sessions = new Sessions(Graph.string) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 84 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 85 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 86 |   final class Sessions private(val graph: Sessions.Graph) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 87 | override def toString: String = graph.toString | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 88 | |
| 78500 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 89 | def defined(name: String): Boolean = graph.defined(name) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 90 | def apply(name: String): Build_Job.Session_Context = graph.get_node(name) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 91 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 92 | def iterator: Iterator[Build_Job.Session_Context] = | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 93 | for (name <- graph.topological_order.iterator) yield apply(name) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 94 | |
| 80118 | 95 | def store_heap(name: String): Boolean = | 
| 96 | isabelle.Sessions.is_pure(name) || iterator.exists(_.ancestors.contains(name)) | |
| 97 | ||
| 80272 | 98 | def data: Name.Data[Build_Job.Session_Context] = | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 99 | Map.from(for ((_, (session, _)) <- graph.iterator) yield session.name -> session) | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 100 | |
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 101 | def make(new_graph: Sessions.Graph): Sessions = | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 102 | if (graph == new_graph) this | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 103 |       else {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 104 | new Sessions( | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 105 |           new_graph.iterator.foldLeft(new_graph) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 106 | case (g, (name, (session, _))) => g.add_deps_acyclic(name, session.deps) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 107 | }) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 108 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 109 | |
| 80274 | 110 |     def update(updates: List[Update.Op[Build_Job.Session_Context]]): Sessions = {
 | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 111 | val graph1 = | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 112 |         updates.foldLeft(graph) {
 | 
| 80274 | 113 | case (g, Update.Delete(name)) => g.del_node(name) | 
| 114 | case (g, Update.Insert(session)) => | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 115 | (if (g.defined(session.name)) g.del_node(session.name) else g) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 116 | .new_node(session.name, session) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 117 | } | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 118 | make(graph1) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 119 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 120 | |
| 78372 | 121 | def init( | 
| 78421 | 122 | build_context: isabelle.Build.Context, | 
| 78374 | 123 | database_server: Option[SQL.Database], | 
| 124 | progress: Progress = new Progress | |
| 78372 | 125 |     ): Sessions = {
 | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 126 | val sessions_structure = build_context.sessions_structure | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 127 | make( | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 128 |         sessions_structure.build_graph.iterator.foldLeft(graph) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 129 | case (graph0, (name, (info, _))) => | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 130 | val deps = info.parent.toList | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 131 | val prefs = info.session_prefs | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 132 | val ancestors = sessions_structure.build_requirements(deps) | 
| 79643 | 133 | val sources_shasum = build_context.deps.sources_shasum(name) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 134 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 135 |             if (graph0.defined(name)) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 136 | val session0 = graph0.get_node(name) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 137 | val prefs0 = session0.session_prefs | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 138 | val ancestors0 = session0.ancestors | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 139 | val sources_shasum0 = session0.sources_shasum | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 140 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 141 | def err(msg: String, a: String, b: String): Nothing = | 
| 78501 | 142 |                 error("Conflicting dependencies for session " + quote(name) + ": " + msg + "\n" +
 | 
| 143 | Library.indent_lines(2, a) + "\nvs.\n" + Library.indent_lines(2, b)) | |
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 144 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 145 |               if (prefs0 != prefs) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 146 |                 err("preferences disagree",
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 147 | Symbol.cartouche_decoded(prefs0), Symbol.cartouche_decoded(prefs)) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 148 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 149 |               if (ancestors0 != ancestors) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 150 |                 err("ancestors disagree", commas_quote(ancestors0), commas_quote(ancestors))
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 151 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 152 |               if (sources_shasum0 != sources_shasum) {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 153 | val a = sources_shasum0 - sources_shasum | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 154 | val b = sources_shasum - sources_shasum0 | 
| 78501 | 155 |                 err("sources disagree",
 | 
| 156 | Library.trim_line(a.toString), | |
| 157 | Library.trim_line(b.toString)) | |
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 158 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 159 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 160 | graph0 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 161 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 162 |             else {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 163 | val session = | 
| 78374 | 164 | Build_Job.Session_Context.load(database_server, | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 165 | build_context.build_uuid, name, deps, ancestors, prefs, sources_shasum, | 
| 78374 | 166 | info.timeout, build_context.store, progress = progress) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 167 | graph0.new_node(name, session) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 168 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 169 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 170 | ) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 171 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 172 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 173 |     lazy val max_time: Map[String, Double] = {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 174 | val maximals = graph.maximals.toSet | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 175 |       def descendants_time(name: String): Double = {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 176 | if (maximals.contains(name)) apply(name).old_time.seconds | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 177 |         else {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 178 | val descendants = graph.all_succs(List(name)).toSet | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 179 | val g = graph.restrict(descendants) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 180 |           (0.0 :: g.maximals.flatMap { desc =>
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 181 | val ps = g.all_preds(List(desc)) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 182 | if (ps.exists(p => !graph.defined(p))) None | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 183 | else Some(ps.map(p => apply(p).old_time.seconds).sum) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 184 | }).max | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 185 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 186 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 187 | Map.from( | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 188 | for (name <- graph.keys_iterator) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 189 | yield name -> descendants_time(name)).withDefaultValue(0.0) | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 190 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 191 | |
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 192 | lazy val ordering: Ordering[String] = | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 193 | (a: String, b: String) => | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 194 |         max_time(b) compare max_time(a) match {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 195 | case 0 => | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 196 |             apply(b).timeout compare apply(a).timeout match {
 | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 197 | case 0 => a compare b | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 198 | case ord => ord | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 199 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 200 | case ord => ord | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 201 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 202 | } | 
| 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 203 | |
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 204 | sealed case class Snapshot( | 
| 77660 | 205 | builds: List[Build], // available build configurations | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 206 | workers: List[Worker], // available worker processes | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 207 | sessions: Sessions, // static build targets | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 208 | pending: State.Pending, // dynamic build "queue" | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 209 | running: State.Running, // presently running jobs | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 210 | results: State.Results) // finished results | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 211 | |
| 77496 | 212 |   object State {
 | 
| 79866 
75871d47e400
tuned signature: fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79863diff
changeset | 213 |     def inc_serial(serial: Long): Long = {
 | 
| 79835 | 214 | require(serial < Long.MaxValue, "serial overflow") | 
| 215 | serial + 1 | |
| 216 | } | |
| 217 | ||
| 80272 | 218 | type Pending = Name.Data[Task] | 
| 219 | type Running = Name.Data[Job] | |
| 220 | type Results = Name.Data[Result] | |
| 77496 | 221 | } | 
| 222 | ||
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 223 | sealed case class State( | 
| 77372 | 224 | serial: Long = 0, | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 225 | sessions: Sessions = Sessions.empty, | 
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 226 | pending: State.Pending = Map.empty, | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 227 | running: State.Running = Map.empty, | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 228 | results: State.Results = Map.empty | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 229 |   ) {
 | 
| 79835 | 230 | def next_serial: Long = State.inc_serial(serial) | 
| 77513 | 231 | |
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 232 | def ready: List[Task] = pending.valuesIterator.filter(_.is_ready).toList.sortBy(_.name) | 
| 79885 | 233 | def next_ready: List[Task] = ready.filter(task => !is_running(task.name)) | 
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 234 | def exists_ready: Boolean = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 235 | pending.valuesIterator.exists(task => task.is_ready && !is_running(task.name)) | 
| 78968 
faa5af35fb65
clarified signature: more operations;
 Fabian Huch <huch@in.tum.de> parents: 
78893diff
changeset | 236 | |
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 237 | def remove_pending(a: String): State = | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 238 | copy(pending = | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 239 |         pending.foldLeft(pending) {
 | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 240 | case (map, (b, task)) => | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 241 | if (a == b) map - a | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 242 |             else {
 | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 243 |               task.resolve(a) match {
 | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 244 | case None => map | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 245 | case Some(task1) => map + (b -> task1) | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 246 | } | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 247 | } | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79827diff
changeset | 248 | }) | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 249 | |
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 250 | def is_running(name: String): Boolean = running.isDefinedAt(name) | 
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 251 | |
| 79887 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 252 | def build_running: List[Build_Job] = | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 253 | running.valuesIterator.flatMap(_.build).toList | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 254 | |
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 255 | def finished_running(): Boolean = | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 256 | build_running.exists(_.is_finished) | 
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 257 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 258 | def busy_running(jobs: Int): Boolean = | 
| 79887 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 259 | jobs <= 0 || jobs <= build_running.length | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 260 | |
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 261 | def add_running(job: Job): State = | 
| 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 262 | copy(running = running + (job.name -> job)) | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 263 | |
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 264 | def remove_running(name: String): State = | 
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 265 | copy(running = running - name) | 
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 266 | |
| 77336 | 267 | def make_result( | 
| 77651 | 268 | result_name: (String, String, String), | 
| 77461 | 269 | process_result: Process_Result, | 
| 77460 
ccca589d7027
tuned signature: support general Build_Job instances;
 wenzelm parents: 
77459diff
changeset | 270 | output_shasum: SHA1.Shasum, | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 271 | start_date: Date, | 
| 77475 | 272 | node_info: Host.Node_Info = Host.Node_Info.none, | 
| 77461 | 273 | current: Boolean = false | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 274 |     ): State = {
 | 
| 77651 | 275 | val (name, worker_uuid, build_uuid) = result_name | 
| 276 | val result = | |
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 277 | Result(name, worker_uuid, build_uuid, node_info, start_date, process_result, output_shasum, | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 278 | current) | 
| 77651 | 279 | copy(results = results + (name -> result)) | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 280 | } | 
| 78500 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 281 | |
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 282 |     def ancestor_results(name: String): Option[List[Result]] = {
 | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 283 | val defined = | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 284 | sessions.defined(name) && | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 285 | sessions(name).ancestors.forall(a => sessions.defined(a) && results.isDefinedAt(a)) | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 286 | if (defined) Some(sessions(name).ancestors.map(results)) else None | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 287 | } | 
| 77334 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 288 | } | 
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 289 | |
| 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 wenzelm parents: 
77333diff
changeset | 290 | |
| 77436 | 291 | |
| 292 | /** SQL data model **/ | |
| 77372 | 293 | |
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 294 |   object private_data extends SQL.Data("isabelle_build") {
 | 
| 78168 | 295 |     val database: Path = Path.explode("$ISABELLE_HOME_USER/build.db")
 | 
| 296 | ||
| 79881 | 297 | |
| 298 | /* tables */ | |
| 299 | ||
| 79844 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 300 | override lazy val tables: SQL.Tables = | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 301 | SQL.Tables( | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 302 | Updates.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 303 | Sessions.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 304 | Pending.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 305 | Running.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 306 | Results.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 307 | Base.table, | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 308 | Workers.table) | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79843diff
changeset | 309 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 310 | private lazy val build_uuid_tables = tables.filter(Generic.build_uuid_table) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 311 | private lazy val build_id_tables = | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 312 | tables.filter(t => Generic.build_id_table(t) && !Generic.build_uuid_table(t)) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 313 | |
| 79881 | 314 | |
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 315 | /* notifications */ | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 316 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 317 | lazy val channel: String = Base.table.name | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 318 | lazy val channel_ready: SQL.Notification = SQL.Notification(channel, payload = "ready") | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 319 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 320 | |
| 79881 | 321 | /* generic columns */ | 
| 322 | ||
| 77372 | 323 |     object Generic {
 | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 324 |       val build_id = SQL.Column.long("build_id")
 | 
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 325 |       val build_uuid = SQL.Column.string("build_uuid")
 | 
| 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 326 |       val worker_uuid = SQL.Column.string("worker_uuid")
 | 
| 77372 | 327 |       val name = SQL.Column.string("name")
 | 
| 328 | ||
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 329 | def build_id_table(table: SQL.Table): Boolean = | 
| 79861 | 330 | table.columns.exists(_.equals_name(build_id)) | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 331 | |
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 332 | def build_uuid_table(table: SQL.Table): Boolean = | 
| 79861 | 333 | table.columns.exists(_.equals_name(build_uuid)) | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 334 | |
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 335 | def sql( | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 336 | build_id: Long = 0, | 
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 337 | build_uuid: String = "", | 
| 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 338 | worker_uuid: String = "", | 
| 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 339 | names: Iterable[String] = Nil | 
| 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 340 | ): SQL.Source = | 
| 77372 | 341 | SQL.and( | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 342 | if_proper(build_id > 0, Generic.build_id.equal(build_id)), | 
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 343 | if_proper(build_uuid, Generic.build_uuid.equal(build_uuid)), | 
| 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 344 | if_proper(worker_uuid, Generic.worker_uuid.equal(worker_uuid)), | 
| 77375 | 345 | if_proper(names, Generic.name.member(names))) | 
| 77662 | 346 | |
| 347 | def sql_where( | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 348 | build_id: Long = 0, | 
| 77662 | 349 | build_uuid: String = "", | 
| 350 | worker_uuid: String = "", | |
| 351 | names: Iterable[String] = Nil | |
| 352 |       ): SQL.Source = {
 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 353 | SQL.where(sql( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 354 | build_id = build_id, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 355 | build_uuid = build_uuid, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 356 | worker_uuid = worker_uuid, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 357 | names = names)) | 
| 77662 | 358 | } | 
| 77372 | 359 | } | 
| 360 | ||
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 361 | |
| 79839 | 362 | /* recorded updates */ | 
| 363 | ||
| 364 |     object Updates {
 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 365 | val build_id = Generic.build_id.make_primary_key | 
| 79839 | 366 |       val serial = SQL.Column.long("serial").make_primary_key
 | 
| 367 |       val kind = SQL.Column.int("kind").make_primary_key
 | |
| 368 | val name = Generic.name.make_primary_key | |
| 369 | ||
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 370 | val table = make_table(List(build_id, serial, kind, name), name = "updates") | 
| 79862 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 371 | |
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 372 | // virtual columns for JOIN with data | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 373 |       val delete = SQL.Column.bool("delete").make_expr(name.undefined)
 | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 374 |       val dom = SQL.Column.string("dom")
 | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 375 | val dom_name = dom.make_expr(name.ident) | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 376 | val name_dom = name.make_expr(dom.ident) | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 377 | } | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 378 | |
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 379 | def read_updates[A]( | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 380 | db: SQL.Database, | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 381 | table: SQL.Table, | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 382 | build_id: Long, | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 383 | serial_seen: Long, | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 384 | get: SQL.Result => A | 
| 80274 | 385 |     ): List[Update.Op[A]] = {
 | 
| 79862 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 386 | val domain_columns = List(Updates.dom_name) | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 387 | val domain_table = | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 388 |         SQL.Table("domain", domain_columns, body =
 | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 389 | Updates.table.select(domain_columns, distinct = true, sql = | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 390 | SQL.where_and( | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 391 | Updates.build_id.equal(build_id), | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 392 | Updates.serial.ident + " > " + serial_seen, | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 393 | Updates.kind.equal(tables.index(table))))) | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 394 | |
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 395 | val select_columns = | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 396 | Updates.delete :: Updates.name_dom :: table.columns.filterNot(_.equals_name(Generic.name)) | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 397 | val select_sql = | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 398 | SQL.select(select_columns, sql = | 
| 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 399 | domain_table.query_named + SQL.join_outer + table + | 
| 79863 
81717ee51920
minor performance tuning: SQL.order_by is only for demo purposes;
 wenzelm parents: 
79862diff
changeset | 400 | " ON " + Updates.dom + " = " + Generic.name) | 
| 79862 
98d65411bfdb
support efficient access to state updates, based on LEFT OUTER JOIN;
 wenzelm parents: 
79861diff
changeset | 401 | |
| 80274 | 402 | db.execute_query_statement(select_sql, List.from[Update.Op[A]], | 
| 79869 | 403 | res => | 
| 80274 | 404 | if (res.bool(Updates.delete)) Update.Delete(res.string(Updates.name)) | 
| 405 | else Update.Insert(get(res))) | |
| 79839 | 406 | } | 
| 407 | ||
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 408 | def write_updates( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 409 | db: SQL.Database, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 410 | build_id: Long, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 411 | serial: Long, | 
| 80274 | 412 | updates: List[Update] | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 413 | ): Unit = | 
| 79839 | 414 | db.execute_batch_statement(db.insert_permissive(Updates.table), batch = | 
| 415 | for (update <- updates.iterator; kind = update.kind; name <- update.domain.iterator) | |
| 416 |         yield { (stmt: SQL.Statement) =>
 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 417 | require(build_id > 0 && serial > 0 && kind > 0 && name.nonEmpty, | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 418 | "Bad database update: build_id = " + build_id + ", serial = " + serial + | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 419 | ", kind = " + kind + ", name = " + quote(name)) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 420 | stmt.long(1) = build_id | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 421 | stmt.long(2) = serial | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 422 | stmt.int(3) = kind | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 423 | stmt.string(4) = name | 
| 79839 | 424 | }) | 
| 425 | ||
| 426 | ||
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 427 | /* base table */ | 
| 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 428 | |
| 77417 | 429 |     object Base {
 | 
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 430 | val build_uuid = Generic.build_uuid.make_primary_key | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 431 | val build_id = Generic.build_id.make_primary_key | 
| 77387 
cd10b8edfdf5
clarified db content: avoid redundancy of historic ML_IDENTIFIER;
 wenzelm parents: 
77385diff
changeset | 432 |       val ml_platform = SQL.Column.string("ml_platform")
 | 
| 77372 | 433 |       val options = SQL.Column.string("options")
 | 
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 434 |       val start = SQL.Column.date("start")
 | 
| 77545 | 435 |       val stop = SQL.Column.date("stop")
 | 
| 77372 | 436 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 437 | val table = make_table(List(build_uuid, build_id, ml_platform, options, start, stop)) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 438 | } | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 439 | |
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 440 | def read_build_ids(db: SQL.Database, build_uuids: List[String]): List[Long] = | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 441 | db.execute_query_statement( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 442 | Base.table.select(List(Base.build_id), | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 443 | sql = if_proper(build_uuids, Base.build_uuid.where_member(build_uuids))), | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 444 | List.from[Long], res => res.long(Base.build_id)) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 445 | |
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 446 |     def get_build_id(db: SQL.Database, build_uuid: String): Long = {
 | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 447 |       read_build_ids(db, build_uuids = List(build_uuid)) match {
 | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 448 | case build_id :: _ => build_id | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 449 | case _ => | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 450 | db.execute_query_statementO( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 451 | Base.table.select(List(Base.build_id.max)), _.long(Base.build_id)).getOrElse(0L) + 1L | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 452 | } | 
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 453 | } | 
| 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 454 | |
| 78632 | 455 |     def read_builds(db: SQL.Database): List[Build] = {
 | 
| 78226 | 456 | val builds = | 
| 78632 | 457 | db.execute_query_statement(Base.table.select(), List.from[Build], | 
| 78226 | 458 |           { res =>
 | 
| 459 | val build_uuid = res.string(Base.build_uuid) | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 460 | val build_id = res.long(Base.build_id) | 
| 78226 | 461 | val ml_platform = res.string(Base.ml_platform) | 
| 462 | val options = res.string(Base.options) | |
| 463 | val start = res.date(Base.start) | |
| 464 | val stop = res.get_date(Base.stop) | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 465 | Build(build_uuid, build_id, ml_platform, options, start, stop, Nil) | 
| 78226 | 466 | }) | 
| 467 | ||
| 468 |       for (build <- builds.sortBy(_.start)(Date.Ordering)) yield {
 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 469 | build.copy(sessions = private_data.read_sessions(db, build_uuid = build.build_uuid).sorted) | 
| 78226 | 470 | } | 
| 471 | } | |
| 77660 | 472 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 473 | def remove_builds(db: SQL.Database, build_uuids: List[String]): Unit = | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 474 |       if (build_uuids.nonEmpty) {
 | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 475 | val build_ids = read_build_ids(db, build_uuids = build_uuids) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 476 | |
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 477 | val sql1 = Generic.build_uuid.where_member(build_uuids) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 478 | val sql2 = Generic.build_id.where_member_long(build_ids) | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 479 | db.execute_statement( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 480 | SQL.MULTI( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 481 | build_uuid_tables.map(_.delete(sql = sql1)) ++ | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 482 | build_id_tables.map(_.delete(sql = sql2)))) | 
| 78635 | 483 | } | 
| 484 | ||
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 485 | def start_build( | 
| 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 486 | db: SQL.Database, | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 487 | build_id: Long, | 
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 488 | build_uuid: String, | 
| 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 489 | ml_platform: String, | 
| 79811 
d9fc2cc37694
more robust build_start for master and workers (via database);
 wenzelm parents: 
79810diff
changeset | 490 | options: String, | 
| 
d9fc2cc37694
more robust build_start for master and workers (via database);
 wenzelm parents: 
79810diff
changeset | 491 | start: Date | 
| 77536 
7c7f1473e51a
clarified database content and prepare/init stages;
 wenzelm parents: 
77534diff
changeset | 492 |     ): Unit = {
 | 
| 77541 | 493 | db.execute_statement(Base.table.insert(), body = | 
| 494 |         { stmt =>
 | |
| 495 | stmt.string(1) = build_uuid | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 496 | stmt.long(2) = build_id | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 497 | stmt.string(3) = ml_platform | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 498 | stmt.string(4) = options | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 499 | stmt.date(5) = start | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 500 | stmt.date(6) = None | 
| 77541 | 501 | }) | 
| 77372 | 502 | } | 
| 503 | ||
| 77545 | 504 | def stop_build(db: SQL.Database, build_uuid: String): Unit = | 
| 77541 | 505 | db.execute_statement( | 
| 77636 | 506 | Base.table.update(List(Base.stop), sql = Base.build_uuid.where_equal(build_uuid)), | 
| 77541 | 507 |         body = { stmt => stmt.date(1) = db.now() })
 | 
| 77538 | 508 | |
| 77539 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 wenzelm parents: 
77538diff
changeset | 509 |     def clean_build(db: SQL.Database): Unit = {
 | 
| 78635 | 510 | val remove = | 
| 77552 | 511 | db.execute_query_statement( | 
| 512 | Base.table.select(List(Base.build_uuid), sql = SQL.where(Base.stop.defined)), | |
| 513 | List.from[String], res => res.string(Base.build_uuid)) | |
| 77539 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 wenzelm parents: 
77538diff
changeset | 514 | |
| 78635 | 515 | remove_builds(db, remove) | 
| 77539 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 wenzelm parents: 
77538diff
changeset | 516 | } | 
| 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 wenzelm parents: 
77538diff
changeset | 517 | |
| 77416 
d88c12f22ab0
clarified scope of "serial" and "numa_index" within database;
 wenzelm parents: 
77415diff
changeset | 518 | |
| 77531 | 519 | /* sessions */ | 
| 77505 | 520 | |
| 77496 | 521 |     object Sessions {
 | 
| 522 | val name = Generic.name.make_primary_key | |
| 523 |       val deps = SQL.Column.string("deps")
 | |
| 524 |       val ancestors = SQL.Column.string("ancestors")
 | |
| 77610 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 525 |       val options = SQL.Column.string("options")
 | 
| 77496 | 526 |       val sources = SQL.Column.string("sources")
 | 
| 527 |       val timeout = SQL.Column.long("timeout")
 | |
| 528 |       val old_time = SQL.Column.long("old_time")
 | |
| 529 |       val old_command_timings = SQL.Column.bytes("old_command_timings")
 | |
| 77529 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 wenzelm parents: 
77527diff
changeset | 530 | val build_uuid = Generic.build_uuid | 
| 77496 | 531 | |
| 78266 | 532 | val table = | 
| 533 | make_table( | |
| 534 | List(name, deps, ancestors, options, sources, timeout, | |
| 535 | old_time, old_command_timings, build_uuid), | |
| 536 | name = "sessions") | |
| 79839 | 537 | |
| 538 | lazy val table_index: Int = tables.index(table) | |
| 77496 | 539 | } | 
| 540 | ||
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 541 | def read_sessions(db: SQL.Database, build_uuid: String = ""): List[String] = | 
| 77552 | 542 | db.execute_query_statement( | 
| 78218 
a625bfb0e549
clarified signature: more operations and options;
 wenzelm parents: 
78217diff
changeset | 543 | Sessions.table.select(List(Sessions.name), | 
| 78251 | 544 | sql = if_proper(build_uuid, Sessions.build_uuid.where_equal(build_uuid))), | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 545 | List.from[String], res => res.string(Sessions.name)) | 
| 77496 | 546 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 547 | def pull_sessions(db: SQL.Database, build_id: Long, state: State): Sessions = | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 548 | state.sessions.update( | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 549 | read_updates(db, Sessions.table, build_id, state.serial, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 550 |           { res =>
 | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 551 | val name = res.string(Sessions.name) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 552 | val deps = split_lines(res.string(Sessions.deps)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 553 | val ancestors = split_lines(res.string(Sessions.ancestors)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 554 | val options = res.string(Sessions.options) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 555 | val sources_shasum = SHA1.fake_shasum(res.string(Sessions.sources)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 556 | val timeout = Time.ms(res.long(Sessions.timeout)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 557 | val old_time = Time.ms(res.long(Sessions.old_time)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 558 | val old_command_timings_blob = res.bytes(Sessions.old_command_timings) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 559 | val build_uuid = res.string(Sessions.build_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 560 | Build_Job.Session_Context(name, deps, ancestors, options, sources_shasum, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 561 | timeout, old_time, old_command_timings_blob, build_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 562 | }) | 
| 77552 | 563 | ) | 
| 77496 | 564 | |
| 78553 | 565 | def update_sessions( | 
| 566 | db: SQL.Database, | |
| 567 | sessions: Build_Process.Sessions, | |
| 568 | old_sessions: Build_Process.Sessions | |
| 80274 | 569 |     ): Update = {
 | 
| 79837 | 570 | val update = | 
| 80274 | 571 | if (old_sessions.eq(sessions)) Update.empty | 
| 572 | else Update.make(old_sessions.data, sessions.data, kind = Sessions.table_index) | |
| 77496 | 573 | |
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 574 |       if (update.deletes) {
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 575 | db.execute_statement( | 
| 79838 | 576 | Sessions.table.delete(sql = Generic.sql_where(names = update.delete))) | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 577 | } | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 578 | |
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 579 |       if (update.inserts) {
 | 
| 78552 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 wenzelm parents: 
78546diff
changeset | 580 | db.execute_batch_statement(Sessions.table.insert(), batch = | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 581 |           for (name <- update.insert) yield { (stmt: SQL.Statement) =>
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 582 | val session = sessions(name) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 583 | stmt.string(1) = session.name | 
| 77541 | 584 | stmt.string(2) = cat_lines(session.deps) | 
| 585 | stmt.string(3) = cat_lines(session.ancestors) | |
| 77610 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 586 | stmt.string(4) = session.session_prefs | 
| 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 587 | stmt.string(5) = session.sources_shasum.toString | 
| 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 588 | stmt.long(6) = session.timeout.ms | 
| 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 589 | stmt.long(7) = session.old_time.ms | 
| 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 590 | stmt.bytes(8) = session.old_command_timings_blob | 
| 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 wenzelm parents: 
77609diff
changeset | 591 | stmt.string(9) = session.build_uuid | 
| 77541 | 592 | }) | 
| 77496 | 593 | } | 
| 594 | ||
| 79839 | 595 | update | 
| 77496 | 596 | } | 
| 597 | ||
| 77531 | 598 | |
| 599 | /* workers */ | |
| 600 | ||
| 601 |     object Workers {
 | |
| 78173 | 602 | val worker_uuid = Generic.worker_uuid.make_primary_key | 
| 603 | val build_uuid = Generic.build_uuid | |
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 604 |       val start = SQL.Column.date("start")
 | 
| 77531 | 605 |       val stamp = SQL.Column.date("stamp")
 | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 606 |       val stop = SQL.Column.date("stop")
 | 
| 77531 | 607 |       val serial = SQL.Column.long("serial")
 | 
| 608 | ||
| 78266 | 609 | val table = | 
| 610 | make_table(List(worker_uuid, build_uuid, start, stamp, stop, serial), name = "workers") | |
| 79839 | 611 | |
| 612 | lazy val table_index: Int = tables.index(table) | |
| 77531 | 613 | } | 
| 614 | ||
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 615 | def read_serial(db: SQL.Database): Long = | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 616 | db.execute_query_statementO[Long]( | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 617 | Workers.table.select(List(Workers.serial.max)), _.long(Workers.serial)).getOrElse(0L) | 
| 77655 | 618 | |
| 77586 | 619 | def read_workers( | 
| 620 | db: SQL.Database, | |
| 621 | build_uuid: String = "", | |
| 622 | worker_uuid: String = "" | |
| 77657 
a2a4adc268b8
removed redundant State.workers: directly maintained within the database, using with SQL update;
 wenzelm parents: 
77656diff
changeset | 623 |     ): List[Worker] = {
 | 
| 77586 | 624 | db.execute_query_statement( | 
| 77662 | 625 | Workers.table.select( | 
| 626 | sql = Generic.sql_where(build_uuid = build_uuid, worker_uuid = worker_uuid)), | |
| 77586 | 627 | List.from[Worker], | 
| 628 |           { res =>
 | |
| 629 | Worker( | |
| 630 | worker_uuid = res.string(Workers.worker_uuid), | |
| 631 | build_uuid = res.string(Workers.build_uuid), | |
| 632 | start = res.date(Workers.start), | |
| 633 | stamp = res.date(Workers.stamp), | |
| 634 | stop = res.get_date(Workers.stop), | |
| 635 | serial = res.long(Workers.serial)) | |
| 636 | }) | |
| 637 | } | |
| 638 | ||
| 77584 | 639 | def start_worker( | 
| 640 | db: SQL.Database, | |
| 641 | worker_uuid: String, | |
| 642 | build_uuid: String, | |
| 77652 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 643 | serial: Long | 
| 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 644 |     ): Unit = {
 | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 645 | def err(msg: String): Nothing = | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 646 |         error("Cannot start worker " + worker_uuid + if_proper(msg, "\n" + msg))
 | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 647 | |
| 77552 | 648 | val build_stop = | 
| 649 | db.execute_query_statementO( | |
| 77636 | 650 | Base.table.select(List(Base.stop), sql = Base.build_uuid.where_equal(build_uuid)), | 
| 77552 | 651 | res => res.get_date(Base.stop)) | 
| 652 | ||
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 653 |       build_stop match {
 | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 654 | case Some(None) => | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 655 |         case Some(Some(_)) => err("for already stopped build process " + build_uuid)
 | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 656 |         case None => err("for unknown build process " + build_uuid)
 | 
| 77531 | 657 | } | 
| 658 | ||
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 659 | db.execute_statement(Workers.table.insert(), body = | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 660 |         { stmt =>
 | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 661 | val now = db.now() | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 662 | stmt.string(1) = worker_uuid | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 663 | stmt.string(2) = build_uuid | 
| 78172 
43ed2541b758
omit redundant data: already stored in progress database;
 wenzelm parents: 
78170diff
changeset | 664 | stmt.date(3) = now | 
| 
43ed2541b758
omit redundant data: already stored in progress database;
 wenzelm parents: 
78170diff
changeset | 665 | stmt.date(4) = now | 
| 
43ed2541b758
omit redundant data: already stored in progress database;
 wenzelm parents: 
78170diff
changeset | 666 | stmt.date(5) = None | 
| 
43ed2541b758
omit redundant data: already stored in progress database;
 wenzelm parents: 
78170diff
changeset | 667 | stmt.long(6) = serial | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 668 | }) | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 669 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 670 | |
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 671 | def stamp_worker( | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 672 | db: SQL.Database, | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 673 | worker_uuid: String, | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 674 | serial: Long, | 
| 78246 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 675 | stop_now: Boolean = false | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 676 |     ): Unit = {
 | 
| 78246 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 677 | val sql = Workers.worker_uuid.where_equal(worker_uuid) | 
| 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 678 | |
| 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 679 | val stop = | 
| 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 680 | db.execute_query_statementO( | 
| 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 681 | Workers.table.select(List(Workers.stop), sql = sql), _.get_date(Workers.stop)).flatten | 
| 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 682 | |
| 78241 | 683 | db.execute_statement( | 
| 78246 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 684 | Workers.table.update(List(Workers.stamp, Workers.stop, Workers.serial), sql = sql), | 
| 78241 | 685 |         body = { stmt =>
 | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 686 | val now = db.now() | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 687 | stmt.date(1) = now | 
| 78246 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 wenzelm parents: 
78245diff
changeset | 688 | stmt.date(2) = if (stop_now) Some(now) else stop | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 689 | stmt.long(3) = serial | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 690 | }) | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 691 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 692 | |
| 77531 | 693 | |
| 694 | /* pending jobs */ | |
| 695 | ||
| 696 |     object Pending {
 | |
| 697 | val name = Generic.name.make_primary_key | |
| 698 |       val deps = SQL.Column.string("deps")
 | |
| 77661 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 wenzelm parents: 
77660diff
changeset | 699 | val build_uuid = Generic.build_uuid | 
| 77531 | 700 | |
| 79781 | 701 | val table = make_table(List(name, deps, build_uuid), name = "pending") | 
| 79839 | 702 | |
| 703 | lazy val table_index: Int = tables.index(table) | |
| 77531 | 704 | } | 
| 705 | ||
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 706 | def pull_pending(db: SQL.Database, build_id: Long, state: State): State.Pending = | 
| 80274 | 707 | Update.data(state.pending, | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 708 | read_updates(db, Pending.table, build_id, state.serial, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 709 |           { res =>
 | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 710 | val name = res.string(Pending.name) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 711 | val deps = res.string(Pending.deps) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 712 | val build_uuid = res.string(Pending.build_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 713 | Task(name, split_lines(deps), build_uuid) | 
| 77552 | 714 | }) | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 715 | ) | 
| 77372 | 716 | |
| 78553 | 717 | def update_pending( | 
| 718 | db: SQL.Database, | |
| 719 | pending: State.Pending, | |
| 720 | old_pending: State.Pending | |
| 80274 | 721 |     ): Update = {
 | 
| 722 | val update = Update.make(old_pending, pending, kind = Pending.table_index) | |
| 77372 | 723 | |
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 724 |       if (update.deletes) {
 | 
| 77540 | 725 | db.execute_statement( | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 726 | Pending.table.delete(sql = Generic.sql_where(names = update.delete))) | 
| 77372 | 727 | } | 
| 728 | ||
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 729 |       if (update.inserts) {
 | 
| 78552 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 wenzelm parents: 
78546diff
changeset | 730 | db.execute_batch_statement(Pending.table.insert(), batch = | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 731 |           for (name <- update.insert) yield { (stmt: SQL.Statement) =>
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 732 | val task = pending(name) | 
| 77661 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 wenzelm parents: 
77660diff
changeset | 733 | stmt.string(1) = task.name | 
| 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 wenzelm parents: 
77660diff
changeset | 734 | stmt.string(2) = cat_lines(task.deps) | 
| 79781 | 735 | stmt.string(3) = task.build_uuid | 
| 77541 | 736 | }) | 
| 77372 | 737 | } | 
| 738 | ||
| 79839 | 739 | update | 
| 77372 | 740 | } | 
| 741 | ||
| 77531 | 742 | |
| 743 | /* running jobs */ | |
| 744 | ||
| 745 |     object Running {
 | |
| 746 | val name = Generic.name.make_primary_key | |
| 77587 | 747 | val worker_uuid = Generic.worker_uuid | 
| 77634 | 748 | val build_uuid = Generic.build_uuid | 
| 77531 | 749 |       val hostname = SQL.Column.string("hostname")
 | 
| 750 |       val numa_node = SQL.Column.int("numa_node")
 | |
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 751 |       val rel_cpus = SQL.Column.string("rel_cpus")
 | 
| 78841 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 Fabian Huch <huch@in.tum.de> parents: 
78839diff
changeset | 752 |       val start_date = SQL.Column.date("start_date")
 | 
| 77531 | 753 | |
| 78266 | 754 | val table = | 
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 755 | make_table( | 
| 78841 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 Fabian Huch <huch@in.tum.de> parents: 
78839diff
changeset | 756 | List(name, worker_uuid, build_uuid, hostname, numa_node, rel_cpus, start_date), | 
| 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 Fabian Huch <huch@in.tum.de> parents: 
78839diff
changeset | 757 | name = "running") | 
| 79839 | 758 | |
| 759 | lazy val table_index: Int = tables.index(table) | |
| 77531 | 760 | } | 
| 761 | ||
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 762 | def pull_running(db: SQL.Database, build_id: Long, state: State): State.Running = | 
| 80274 | 763 | Update.data(state.running, | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 764 | read_updates(db, Running.table, build_id, state.serial, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 765 |           { res =>
 | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 766 | val name = res.string(Running.name) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 767 | val worker_uuid = res.string(Running.worker_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 768 | val build_uuid = res.string(Running.build_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 769 | val hostname = res.string(Running.hostname) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 770 | val numa_node = res.get_int(Running.numa_node) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 771 | val rel_cpus = res.string(Running.rel_cpus) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 772 | val start_date = res.date(Running.start_date) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 773 | val node_info = Host.Node_Info(hostname, numa_node, Host.Range.from(rel_cpus)) | 
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 774 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 775 | Job(name, worker_uuid, build_uuid, node_info, start_date, None) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 776 | }) | 
| 77552 | 777 | ) | 
| 77372 | 778 | |
| 78553 | 779 | def update_running( | 
| 780 | db: SQL.Database, | |
| 781 | running: State.Running, | |
| 782 | old_running: State.Running | |
| 80274 | 783 |     ): Update = {
 | 
| 784 | val update = Update.make(old_running, running, kind = Running.table_index) | |
| 77372 | 785 | |
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 786 |       if (update.deletes) {
 | 
| 77540 | 787 | db.execute_statement( | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 788 | Running.table.delete(sql = Generic.sql_where(names = update.delete))) | 
| 77372 | 789 | } | 
| 790 | ||
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 791 |       if (update.inserts) {
 | 
| 78552 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 wenzelm parents: 
78546diff
changeset | 792 | db.execute_batch_statement(Running.table.insert(), batch = | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 793 |           for (name <- update.insert) yield { (stmt: SQL.Statement) =>
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 794 | val job = running(name) | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 795 | stmt.string(1) = job.name | 
| 77587 | 796 | stmt.string(2) = job.worker_uuid | 
| 77634 | 797 | stmt.string(3) = job.build_uuid | 
| 798 | stmt.string(4) = job.node_info.hostname | |
| 799 | stmt.int(5) = job.node_info.numa_node | |
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 800 | stmt.string(6) = Host.Range(job.node_info.rel_cpus) | 
| 78841 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 Fabian Huch <huch@in.tum.de> parents: 
78839diff
changeset | 801 | stmt.date(7) = job.start_date | 
| 77541 | 802 | }) | 
| 77372 | 803 | } | 
| 804 | ||
| 79839 | 805 | update | 
| 77372 | 806 | } | 
| 807 | ||
| 77531 | 808 | |
| 809 | /* job results */ | |
| 810 | ||
| 811 |     object Results {
 | |
| 812 | val name = Generic.name.make_primary_key | |
| 77651 | 813 | val worker_uuid = Generic.worker_uuid | 
| 814 | val build_uuid = Generic.build_uuid | |
| 77531 | 815 |       val hostname = SQL.Column.string("hostname")
 | 
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 816 |       val numa_node = SQL.Column.int("numa_node")
 | 
| 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 817 |       val rel_cpus = SQL.Column.string("rel_cpus")
 | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 818 |       val start_date = SQL.Column.date("start_date")
 | 
| 77531 | 819 |       val rc = SQL.Column.int("rc")
 | 
| 820 |       val out = SQL.Column.string("out")
 | |
| 821 |       val err = SQL.Column.string("err")
 | |
| 822 |       val timing_elapsed = SQL.Column.long("timing_elapsed")
 | |
| 823 |       val timing_cpu = SQL.Column.long("timing_cpu")
 | |
| 824 |       val timing_gc = SQL.Column.long("timing_gc")
 | |
| 77651 | 825 |       val output_shasum = SQL.Column.string("output_shasum")
 | 
| 826 |       val current = SQL.Column.bool("current")
 | |
| 77531 | 827 | |
| 828 | val table = | |
| 78266 | 829 | make_table( | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 830 | List(name, worker_uuid, build_uuid, hostname, numa_node, rel_cpus, start_date, | 
| 78266 | 831 | rc, out, err, timing_elapsed, timing_cpu, timing_gc, output_shasum, current), | 
| 832 | name = "results") | |
| 79839 | 833 | |
| 834 | lazy val table_index: Int = tables.index(table) | |
| 77531 | 835 | } | 
| 836 | ||
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 837 | def pull_results(db: SQL.Database, build_id: Long, state: State): State.Results = | 
| 80274 | 838 | Update.data(state.results, | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 839 | read_updates(db, Results.table, build_id, state.serial, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 840 |           { res =>
 | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 841 | val name = res.string(Results.name) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 842 | val worker_uuid = res.string(Results.worker_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 843 | val build_uuid = res.string(Results.build_uuid) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 844 | val hostname = res.string(Results.hostname) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 845 | val numa_node = res.get_int(Results.numa_node) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 846 | val rel_cpus = res.string(Results.rel_cpus) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 847 | val node_info = Host.Node_Info(hostname, numa_node, Host.Range.from(rel_cpus)) | 
| 77651 | 848 | |
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 849 | val start_date = res.date(Results.start_date) | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 850 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 851 | val rc = res.int(Results.rc) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 852 | val out = res.string(Results.out) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 853 | val err = res.string(Results.err) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 854 | val timing = | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 855 | res.timing( | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 856 | Results.timing_elapsed, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 857 | Results.timing_cpu, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 858 | Results.timing_gc) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 859 | val process_result = | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 860 | Process_Result(rc, | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 861 | out_lines = split_lines(out), | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 862 | err_lines = split_lines(err), | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 863 | timing = timing) | 
| 77651 | 864 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 865 | val output_shasum = SHA1.fake_shasum(res.string(Results.output_shasum)) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 866 | val current = res.bool(Results.current) | 
| 77651 | 867 | |
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 868 | Result(name, worker_uuid, build_uuid, node_info, start_date, process_result, | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 869 | output_shasum, current) | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 870 | }) | 
| 77552 | 871 | ) | 
| 77372 | 872 | |
| 78553 | 873 | def update_results( | 
| 874 | db: SQL.Database, | |
| 875 | results: State.Results, | |
| 876 | old_results: State.Results | |
| 80274 | 877 |     ): Update = {
 | 
| 878 | val update = Update.make(old_results, results, kind = Results.table_index) | |
| 77372 | 879 | |
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 880 |       if (update.deletes) {
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 881 | db.execute_statement( | 
| 79838 | 882 | Results.table.delete(sql = Generic.sql_where(names = update.delete))) | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 883 | } | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 884 | |
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 885 |       if (update.inserts) {
 | 
| 78552 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 wenzelm parents: 
78546diff
changeset | 886 | db.execute_batch_statement(Results.table.insert(), batch = | 
| 79831 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 887 |           for (name <- update.insert) yield { (stmt: SQL.Statement) =>
 | 
| 
4611b7b47b42
misc tuning and clarification: prefer explicit type Build_Process.Update;
 wenzelm parents: 
79830diff
changeset | 888 | val result = results(name) | 
| 78552 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 wenzelm parents: 
78546diff
changeset | 889 | val process_result = result.process_result | 
| 77651 | 890 | stmt.string(1) = result.name | 
| 891 | stmt.string(2) = result.worker_uuid | |
| 892 | stmt.string(3) = result.build_uuid | |
| 893 | stmt.string(4) = result.node_info.hostname | |
| 894 | stmt.int(5) = result.node_info.numa_node | |
| 78839 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 Fabian Huch <huch@in.tum.de> parents: 
78635diff
changeset | 895 | stmt.string(6) = Host.Range(result.node_info.rel_cpus) | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 896 | stmt.date(7) = result.start_date | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 897 | stmt.int(8) = process_result.rc | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 898 | stmt.string(9) = cat_lines(process_result.out_lines) | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 899 | stmt.string(10) = cat_lines(process_result.err_lines) | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 900 | stmt.long(11) = process_result.timing.elapsed.ms | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 901 | stmt.long(12) = process_result.timing.cpu.ms | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 902 | stmt.long(13) = process_result.timing.gc.ms | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 903 | stmt.string(14) = result.output_shasum.toString | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 904 | stmt.bool(15) = result.current | 
| 77541 | 905 | }) | 
| 77372 | 906 | } | 
| 907 | ||
| 79839 | 908 | update | 
| 77372 | 909 | } | 
| 910 | ||
| 77531 | 911 | |
| 912 | /* collective operations */ | |
| 913 | ||
| 79904 | 914 |     def pull_state(db: SQL.Database, build_id: Long, worker_uuid: String, state: State): State = {
 | 
| 77655 | 915 | val serial_db = read_serial(db) | 
| 916 | if (serial_db == state.serial) state | |
| 77652 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 917 |       else {
 | 
| 77655 | 918 | val serial = serial_db max state.serial | 
| 77652 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 919 | stamp_worker(db, worker_uuid, serial) | 
| 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 920 | |
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 921 | val sessions = pull_sessions(db, build_id, state) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 922 | val pending = pull_pending(db, build_id, state) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 923 | val running = pull_running(db, build_id, state) | 
| 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 924 | val results = pull_results(db, build_id, state) | 
| 77652 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 925 | |
| 78174 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 wenzelm parents: 
78173diff
changeset | 926 | state.copy(serial = serial, sessions = sessions, pending = pending, | 
| 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 wenzelm parents: 
78173diff
changeset | 927 | running = running, results = results) | 
| 77652 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 928 | } | 
| 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 929 | } | 
| 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 wenzelm parents: 
77651diff
changeset | 930 | |
| 79904 | 931 | def push_state( | 
| 78553 | 932 | db: SQL.Database, | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 933 | build_id: Long, | 
| 78553 | 934 | worker_uuid: String, | 
| 935 | state: State, | |
| 936 | old_state: State | |
| 937 |     ): State = {
 | |
| 79839 | 938 | val updates = | 
| 77416 
d88c12f22ab0
clarified scope of "serial" and "numa_index" within database;
 wenzelm parents: 
77415diff
changeset | 939 | List( | 
| 78553 | 940 | update_sessions(db, state.sessions, old_state.sessions), | 
| 941 | update_pending(db, state.pending, old_state.pending), | |
| 942 | update_running(db, state.running, old_state.running), | |
| 79853 | 943 | update_results(db, state.results, old_state.results) | 
| 944 | ).filter(_.defined) | |
| 77372 | 945 | |
| 79853 | 946 |       if (updates.nonEmpty) {
 | 
| 79839 | 947 | val serial = state.next_serial | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 948 | write_updates(db, build_id, serial, updates) | 
| 79830 | 949 | stamp_worker(db, worker_uuid, serial) | 
| 950 | state.copy(serial = serial) | |
| 951 | } | |
| 952 | else state | |
| 77372 | 953 | } | 
| 954 | } | |
| 78218 
a625bfb0e549
clarified signature: more operations and options;
 wenzelm parents: 
78217diff
changeset | 955 | |
| 
a625bfb0e549
clarified signature: more operations and options;
 wenzelm parents: 
78217diff
changeset | 956 | def read_builds(db: SQL.Database): List[Build] = | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 957 |     private_data.transaction_lock(db, create = true, label = "Build_Process.read_builds") {
 | 
| 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 958 | private_data.read_builds(db) | 
| 78356 | 959 | } | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 960 | |
| 79852 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 961 | def init_build( | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 962 | db: SQL.Database, | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 963 | build_context: isabelle.Build.Context, | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 964 | build_start: Date | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 965 | ): Long = | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 966 |     private_data.transaction_lock(db, create = true, label = "Build_Process.init_build") {
 | 
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 967 | db.listen(private_data.channel) | 
| 79852 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 968 | val build_uuid = build_context.build_uuid | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 969 | val build_id = private_data.get_build_id(db, build_uuid) | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 970 |       if (build_context.master) {
 | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 971 | private_data.start_build(db, build_id, build_uuid, build_context.ml_platform, | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 972 | build_context.sessions_structure.session_prefs, build_start) | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 973 | } | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 974 | build_id | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 975 | } | 
| 77396 | 976 | } | 
| 77372 | 977 | |
| 978 | ||
| 77436 | 979 | |
| 980 | /** main process **/ | |
| 77259 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 wenzelm parents: 
77258diff
changeset | 981 | |
| 77505 | 982 | class Build_Process( | 
| 78421 | 983 | protected final val build_context: Build.Context, | 
| 78372 | 984 | protected final val build_progress: Progress, | 
| 985 | protected final val server: SSH.Server | |
| 77505 | 986 | ) | 
| 77436 | 987 | extends AutoCloseable {
 | 
| 988 | /* context */ | |
| 989 | ||
| 78178 | 990 | protected final val store: Store = build_context.store | 
| 77530 | 991 | protected final val build_options: Options = store.options | 
| 79643 | 992 | protected final val build_deps: isabelle.Sessions.Deps = build_context.deps | 
| 77653 | 993 | protected final val hostname: String = build_context.hostname | 
| 77530 | 994 | protected final val build_uuid: String = build_context.build_uuid | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 995 | |
| 79764 | 996 | private var warning_seen = Set.empty[String] | 
| 997 |   protected def warning(msg: String): Unit = synchronized {
 | |
| 998 |     if (!warning_seen(msg)) {
 | |
| 999 | build_progress.echo_warning(msg) | |
| 1000 | warning_seen += msg | |
| 1001 | } | |
| 1002 | } | |
| 1003 | ||
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1004 | |
| 78413 | 1005 | /* global resources with common close() operation */ | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1006 | |
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1007 | protected val _database_server: Option[SQL.Database] = | 
| 78372 | 1008 |     try { store.maybe_open_database_server(server = server) }
 | 
| 78214 | 1009 |     catch { case exn: Throwable => close(); throw exn }
 | 
| 1010 | ||
| 79682 
1fa1b32b0379
build local log_db, with store/restore via optional database server;
 wenzelm parents: 
79645diff
changeset | 1011 | protected val _heaps_database: Option[SQL.Database] = | 
| 
1fa1b32b0379
build local log_db, with store/restore via optional database server;
 wenzelm parents: 
79645diff
changeset | 1012 |     try { store.maybe_open_heaps_database(_database_server, server = server) }
 | 
| 
1fa1b32b0379
build local log_db, with store/restore via optional database server;
 wenzelm parents: 
79645diff
changeset | 1013 |     catch { case exn: Throwable => close(); throw exn }
 | 
| 
1fa1b32b0379
build local log_db, with store/restore via optional database server;
 wenzelm parents: 
79645diff
changeset | 1014 | |
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1015 | protected val _build_database: Option[SQL.Database] = | 
| 78234 | 1016 |     try {
 | 
| 78372 | 1017 |       for (db <- store.maybe_open_build_database(server = server)) yield {
 | 
| 78577 
a945b541efff
clarified default options: SQLite build_database is unsupported for Isabelle2023, due to lack of proper transaction_lock;
 wenzelm parents: 
78575diff
changeset | 1018 |         if (!db.is_postgresql) {
 | 
| 78893 | 1019 |           error("Distributed build requires PostgreSQL (option build_database_server)")
 | 
| 78577 
a945b541efff
clarified default options: SQLite build_database is unsupported for Isabelle2023, due to lack of proper transaction_lock;
 wenzelm parents: 
78575diff
changeset | 1020 | } | 
| 78389 
41e8ae87184d
clarified signature: eliminate SQL.Tables.empty to avoid confusion (see also 0bd366fad888);
 wenzelm parents: 
78385diff
changeset | 1021 | val store_tables = db.is_postgresql | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1022 | Build_Process.private_data.transaction_lock(db, | 
| 78356 | 1023 | create = true, | 
| 1024 | label = "Build_Process.build_database" | |
| 1025 |         ) {
 | |
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1026 | Build_Process.private_data.clean_build(db) | 
| 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1027 | if (store_tables) Store.private_data.tables.lock(db, create = true) | 
| 78234 | 1028 | } | 
| 78389 
41e8ae87184d
clarified signature: eliminate SQL.Tables.empty to avoid confusion (see also 0bd366fad888);
 wenzelm parents: 
78385diff
changeset | 1029 |         if (build_context.master) {
 | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1030 | db.vacuum(Build_Process.private_data.tables.list) | 
| 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1031 | if (store_tables) db.vacuum(Store.private_data.tables.list) | 
| 78389 
41e8ae87184d
clarified signature: eliminate SQL.Tables.empty to avoid confusion (see also 0bd366fad888);
 wenzelm parents: 
78385diff
changeset | 1032 | } | 
| 78234 | 1033 | db | 
| 1034 | } | |
| 1035 | } | |
| 78214 | 1036 |     catch { case exn: Throwable => close(); throw exn }
 | 
| 77259 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 wenzelm parents: 
77258diff
changeset | 1037 | |
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1038 | protected def build_receive(filter: SQL.Notification => Boolean): List[SQL.Notification] = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1039 | _build_database.flatMap(_.receive(filter)).getOrElse(Nil) | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1040 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1041 | protected def build_send(notification: SQL.Notification): Unit = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1042 | _build_database.foreach(_.send(notification)) | 
| 78406 
2ece6509ad6f
clarified options: accommodate potentially slow database connection;
 wenzelm parents: 
78401diff
changeset | 1043 | |
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1044 | protected def build_cluster: Boolean = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1045 |     _build_database match {
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1046 | case Some(db) => db.is_postgresql | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1047 | case None => false | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1048 | } | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1049 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1050 | protected val build_delay: Time = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1051 | build_options.seconds( | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1052 | if (!build_cluster) "build_delay" | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1053 | else if (build_context.master) "build_delay_master" | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1054 | else "build_delay_worker") | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1055 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1056 | protected val build_expire: Int = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1057 | if (!build_cluster || build_context.master) 1 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1058 |     else build_options.int("build_cluster_expire").max(1)
 | 
| 79883 
6fa259b24deb
proper system option, instead of hardwired default;
 wenzelm parents: 
79881diff
changeset | 1059 | |
| 78844 
c7f436a63108
always use host database and make protected;
 Fabian Huch <huch@in.tum.de> parents: 
78842diff
changeset | 1060 | protected val _host_database: SQL.Database = | 
| 
c7f436a63108
always use host database and make protected;
 Fabian Huch <huch@in.tum.de> parents: 
78842diff
changeset | 1061 |     try { store.open_build_database(path = Host.private_data.database, server = server) }
 | 
| 78214 | 1062 |     catch { case exn: Throwable => close(); throw exn }
 | 
| 78213 
fd0430a7b7a4
avoid repeated open_database_server: synchronized transaction_lock;
 wenzelm parents: 
78205diff
changeset | 1063 | |
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1064 |   protected val (progress, worker_uuid) = synchronized {
 | 
| 79717 | 1065 | if (_build_database.isEmpty) (build_progress, UUID.random_string()) | 
| 78569 | 1066 |     else {
 | 
| 1067 |       try {
 | |
| 79873 | 1068 | val db = store.open_build_database(Database_Progress.private_data.database, server = server) | 
| 78569 | 1069 | val progress = | 
| 1070 | new Database_Progress(db, build_progress, | |
| 1071 | input_messages = build_context.master, | |
| 1072 | hostname = hostname, | |
| 1073 | context_uuid = build_uuid, | |
| 1074 | kind = "build_process", | |
| 79883 
6fa259b24deb
proper system option, instead of hardwired default;
 wenzelm parents: 
79881diff
changeset | 1075 | timeout = Some(build_delay), | 
| 
6fa259b24deb
proper system option, instead of hardwired default;
 wenzelm parents: 
79881diff
changeset | 1076 | tick_expire = build_expire) | 
| 78569 | 1077 | (progress, progress.agent_uuid) | 
| 1078 | } | |
| 1079 |       catch { case exn: Throwable => close(); throw exn }
 | |
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1080 | } | 
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1081 | } | 
| 77638 | 1082 | |
| 79852 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1083 | protected val log: Logger = Logger.make_system_log(progress, build_options) | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1084 | |
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1085 | protected val build_start: Date = build_context.build_start getOrElse progress.now() | 
| 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1086 | |
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1087 | protected val build_id: Long = | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1088 |     _build_database match {
 | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1089 | case None => 0L | 
| 79852 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1090 | case Some(db) => Build_Process.init_build(db, build_context, build_start) | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1091 | } | 
| 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1092 | |
| 79627 | 1093 | protected def open_build_cluster(): Build_Cluster = | 
| 1094 | Build_Cluster.make(build_context, progress = build_progress).open() | |
| 78430 
0461fc9d43e8
more build_cluster management: open SSH connections in parallel, but synchronously;
 wenzelm parents: 
78424diff
changeset | 1095 | |
| 79701 
e8122e84aa58
tuned signature: fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79698diff
changeset | 1096 | protected val _build_cluster: Build_Cluster = | 
| 78413 | 1097 |     try {
 | 
| 78434 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 wenzelm parents: 
78430diff
changeset | 1098 | if (build_context.master && _build_database.isDefined) open_build_cluster() | 
| 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 wenzelm parents: 
78430diff
changeset | 1099 | else Build_Cluster.none | 
| 78413 | 1100 | } | 
| 1101 |     catch { case exn: Throwable => close(); throw exn }
 | |
| 1102 | ||
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1103 |   def close(): Unit = synchronized {
 | 
| 78214 | 1104 | Option(_database_server).flatten.foreach(_.close()) | 
| 79682 
1fa1b32b0379
build local log_db, with store/restore via optional database server;
 wenzelm parents: 
79645diff
changeset | 1105 | Option(_heaps_database).flatten.foreach(_.close()) | 
| 78214 | 1106 | Option(_build_database).flatten.foreach(_.close()) | 
| 78844 
c7f436a63108
always use host database and make protected;
 Fabian Huch <huch@in.tum.de> parents: 
78842diff
changeset | 1107 | Option(_host_database).foreach(_.close()) | 
| 78434 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 wenzelm parents: 
78430diff
changeset | 1108 | Option(_build_cluster).foreach(_.close()) | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1109 |     progress match {
 | 
| 79760 
dbdb8ba05b2b
more robust: assume that database is exclusive for this Progress instance --- always close on exit (see also bf377e10ff3b);
 wenzelm parents: 
79717diff
changeset | 1110 | case db_progress: Database_Progress => db_progress.close() | 
| 78159 | 1111 | case _ => | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1112 | } | 
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1113 | } | 
| 77436 | 1114 | |
| 78413 | 1115 | |
| 77437 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 wenzelm parents: 
77436diff
changeset | 1116 | /* global state: internal var vs. external database */ | 
| 77436 | 1117 | |
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1118 | protected var _state: Build_Process.State = Build_Process.State() | 
| 77437 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 wenzelm parents: 
77436diff
changeset | 1119 | |
| 78356 | 1120 | protected def synchronized_database[A](label: String)(body: => A): A = | 
| 1121 |     synchronized {
 | |
| 1122 |       _build_database match {
 | |
| 1123 | case None => body | |
| 1124 | case Some(db) => | |
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1125 |           Build_Process.private_data.transaction_lock(db, label = label) {
 | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79869diff
changeset | 1126 | val old_state = | 
| 79904 | 1127 | Build_Process.private_data.pull_state(db, build_id, worker_uuid, _state) | 
| 78553 | 1128 | _state = old_state | 
| 78356 | 1129 | val res = body | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1130 | _state = | 
| 79904 | 1131 | Build_Process.private_data.push_state( | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79848diff
changeset | 1132 | db, build_id, worker_uuid, _state, old_state) | 
| 78356 | 1133 | res | 
| 1134 | } | |
| 1135 | } | |
| 77522 
a1d30297cd61
more complete coverage of non-final Progress methods, notably for Server.Connection_Progress;
 wenzelm parents: 
77521diff
changeset | 1136 | } | 
| 
a1d30297cd61
more complete coverage of non-final Progress methods, notably for Server.Connection_Progress;
 wenzelm parents: 
77521diff
changeset | 1137 | |
| 77505 | 1138 | |
| 77437 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 wenzelm parents: 
77436diff
changeset | 1139 | /* policy operations */ | 
| 77333 | 1140 | |
| 78394 
761d12b043d0
proper running limit, based on this worker process;
 wenzelm parents: 
78393diff
changeset | 1141 |   protected def next_jobs(state: Build_Process.State): List[String] = {
 | 
| 78529 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 wenzelm parents: 
78510diff
changeset | 1142 |     val limit = {
 | 
| 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 wenzelm parents: 
78510diff
changeset | 1143 |       if (progress.stopped) { if (build_context.master) Int.MaxValue else 0 }
 | 
| 79616 | 1144 | else build_context.jobs - state.build_running.length | 
| 78529 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 wenzelm parents: 
78510diff
changeset | 1145 | } | 
| 79020 
ef76705bf402
clarified ready vs. next ready;
 Fabian Huch <huch@in.tum.de> parents: 
78969diff
changeset | 1146 | if (limit > 0) state.next_ready.sortBy(_.name)(state.sessions.ordering).take(limit).map(_.name) | 
| 78394 
761d12b043d0
proper running limit, based on this worker process;
 wenzelm parents: 
78393diff
changeset | 1147 | else Nil | 
| 
761d12b043d0
proper running limit, based on this worker process;
 wenzelm parents: 
78393diff
changeset | 1148 | } | 
| 77259 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 wenzelm parents: 
77258diff
changeset | 1149 | |
| 78842 
eb572f7b6689
prefer extensible next_node_info in build process over process_options in build engine (which needs the final node info anyway);
 Fabian Huch <huch@in.tum.de> parents: 
78841diff
changeset | 1150 |   protected def next_node_info(state: Build_Process.State, session_name: String): Host.Node_Info = {
 | 
| 80110 | 1151 | val available_nodes = build_context.numa_nodes | 
| 1152 | val used_nodes = | |
| 78842 
eb572f7b6689
prefer extensible next_node_info in build process over process_options in build engine (which needs the final node info anyway);
 Fabian Huch <huch@in.tum.de> parents: 
78841diff
changeset | 1153 | Set.from(for (job <- state.running.valuesIterator; i <- job.node_info.numa_node) yield i) | 
| 80110 | 1154 | val numa_node = Host.next_numa_node(_host_database, hostname, available_nodes, used_nodes) | 
| 78842 
eb572f7b6689
prefer extensible next_node_info in build process over process_options in build engine (which needs the final node info anyway);
 Fabian Huch <huch@in.tum.de> parents: 
78841diff
changeset | 1155 | Host.Node_Info(hostname, numa_node, Nil) | 
| 
eb572f7b6689
prefer extensible next_node_info in build process over process_options in build engine (which needs the final node info anyway);
 Fabian Huch <huch@in.tum.de> parents: 
78841diff
changeset | 1156 | } | 
| 
eb572f7b6689
prefer extensible next_node_info in build process over process_options in build engine (which needs the final node info anyway);
 Fabian Huch <huch@in.tum.de> parents: 
78841diff
changeset | 1157 | |
| 78500 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 1158 | protected def start_session( | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 1159 | state: Build_Process.State, | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 1160 | session_name: String, | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 1161 | ancestor_results: List[Build_Process.Result] | 
| 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 wenzelm parents: 
78440diff
changeset | 1162 |   ): Build_Process.State = {
 | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 1163 | val sources_shasum = state.sessions(session_name).sources_shasum | 
| 80124 | 1164 | val input_shasum = ML_Process.make_shasum(ancestor_results.map(_.output_shasum)) | 
| 80118 | 1165 | val store_heap = build_context.store_heap || state.sessions.store_heap(session_name) | 
| 77469 | 1166 | val (current, output_shasum) = | 
| 78374 | 1167 | store.check_output(_database_server, session_name, | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 1168 | sources_shasum = sources_shasum, | 
| 77469 | 1169 | input_shasum = input_shasum, | 
| 80128 | 1170 | build_thorough = build_context.sessions_structure(session_name).build_thorough, | 
| 77469 | 1171 | fresh_build = build_context.fresh_build, | 
| 1172 | store_heap = store_heap) | |
| 1173 | ||
| 78195 | 1174 | val finished = current && ancestor_results.forall(_.current) | 
| 1175 | val skipped = build_context.no_build | |
| 1176 | val cancelled = progress.stopped || !ancestor_results.forall(_.ok) | |
| 77257 | 1177 | |
| 78196 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 wenzelm parents: 
78195diff
changeset | 1178 |     if (!skipped && !cancelled) {
 | 
| 79698 | 1179 |       for (db <- _database_server orElse _heaps_database) {
 | 
| 1180 | val hierarchy = | |
| 1181 | (session_name :: ancestor_results.map(_.name)) | |
| 1182 | .map(store.output_session(_, store_heap = true)) | |
| 1183 | ML_Heap.restore(db, hierarchy, cache = store.cache.compress) | |
| 1184 | } | |
| 78196 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 wenzelm parents: 
78195diff
changeset | 1185 | } | 
| 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 wenzelm parents: 
78195diff
changeset | 1186 | |
| 77651 | 1187 | val result_name = (session_name, worker_uuid, build_uuid) | 
| 1188 | ||
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1189 | val start = progress.now() | 
| 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1190 | |
| 78195 | 1191 |     if (finished) {
 | 
| 77467 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 wenzelm parents: 
77466diff
changeset | 1192 | state | 
| 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 wenzelm parents: 
77466diff
changeset | 1193 | .remove_pending(session_name) | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1194 | .make_result(result_name, Process_Result.ok, output_shasum, start, current = true) | 
| 77260 | 1195 | } | 
| 78195 | 1196 |     else if (skipped) {
 | 
| 77521 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 wenzelm parents: 
77514diff
changeset | 1197 |       progress.echo("Skipping " + session_name + " ...", verbose = true)
 | 
| 77467 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 wenzelm parents: 
77466diff
changeset | 1198 | state. | 
| 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 wenzelm parents: 
77466diff
changeset | 1199 | remove_pending(session_name). | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1200 | make_result(result_name, Process_Result.error, output_shasum, start) | 
| 77260 | 1201 | } | 
| 78195 | 1202 |     else if (cancelled) {
 | 
| 79887 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1203 | progress.echo(session_name + " CANCELLED") | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1204 | state | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1205 | .remove_pending(session_name) | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1206 | .make_result(result_name, Process_Result.undefined, output_shasum, start) | 
| 77452 | 1207 | } | 
| 1208 |     else {
 | |
| 79814 | 1209 |       val build_log_verbose = build_options.bool("build_log_verbose")
 | 
| 1210 | ||
| 79819 | 1211 | val start_time = start - build_start | 
| 79814 | 1212 | val start_time_msg = build_log_verbose | 
| 77551 | 1213 | |
| 79812 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1214 | val node_info = next_node_info(state, session_name) | 
| 79821 | 1215 | val node_info_msg = node_info.numa || build_log_verbose | 
| 78575 | 1216 | |
| 77551 | 1217 | progress.echo( | 
| 1218 | (if (store_heap) "Building " else "Running ") + session_name + | |
| 79812 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1219 | if_proper(start_time_msg || node_info_msg, | 
| 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1220 |             " (" +
 | 
| 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1221 | if_proper(start_time_msg, "started " + start_time.message_hms) + | 
| 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1222 | if_proper(start_time_msg && node_info_msg, " ") + | 
| 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1223 | if_proper(node_info_msg, "on " + node_info.toString) + | 
| 
9d484c5d3a63
additional build_log column "session_start", with implicit upgrade of database schema;
 wenzelm parents: 
79811diff
changeset | 1224 | ")") + " ...") | 
| 77260 | 1225 | |
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 1226 | val session = state.sessions(session_name) | 
| 79822 | 1227 | val background = build_deps.background(session_name) | 
| 78237 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 wenzelm parents: 
78234diff
changeset | 1228 | |
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 1229 | val build = | 
| 78372 | 1230 | Build_Job.start_session(build_context, session, progress, log, server, | 
| 79822 | 1231 | background, sources_shasum, input_shasum, node_info, store_heap) | 
| 77630 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 wenzelm parents: 
77629diff
changeset | 1232 | |
| 79822 | 1233 | state.add_running( | 
| 1234 | Build_Process.Job(session_name, worker_uuid, build_uuid, node_info, start, Some(build))) | |
| 77260 | 1235 | } | 
| 1236 | } | |
| 77257 | 1237 | |
| 77436 | 1238 | |
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1239 | /* build process roles */ | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1240 | |
| 77654 | 1241 | final def is_session_name(job_name: String): Boolean = | 
| 1242 | !Long_Name.is_qualified(job_name) | |
| 77648 | 1243 | |
| 78356 | 1244 |   protected final def stop_build(): Unit = synchronized_database("Build_Process.stop_build") {
 | 
| 78203 | 1245 |     for (db <- _build_database) {
 | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1246 | Build_Process.private_data.stop_build(db, build_uuid) | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1247 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1248 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1249 | |
| 78356 | 1250 |   protected final def start_worker(): Unit = synchronized_database("Build_Process.start_worker") {
 | 
| 78203 | 1251 |     for (db <- _build_database) {
 | 
| 79868 | 1252 | _state = _state.copy(serial = _state.next_serial) | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1253 | Build_Process.private_data.start_worker(db, worker_uuid, build_uuid, _state.serial) | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1254 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1255 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1256 | |
| 78356 | 1257 |   protected final def stop_worker(): Unit = synchronized_database("Build_Process.stop_worker") {
 | 
| 78203 | 1258 |     for (db <- _build_database) {
 | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1259 | Build_Process.private_data.stamp_worker(db, worker_uuid, _state.serial, stop_now = true) | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1260 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1261 | } | 
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1262 | |
| 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1263 | |
| 79710 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1264 | /* prepare */ | 
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1265 | |
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1266 |   def prepare(): Unit = {
 | 
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1267 |     for (name <- build_context.clean_sessions) {
 | 
| 79711 
5044f1d9196d
more thorough Store.clean_output (amending 1fa1b32b0379);
 wenzelm parents: 
79710diff
changeset | 1268 | store.clean_output(_database_server orElse _heaps_database, name, progress = progress) | 
| 79710 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1269 | } | 
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1270 | } | 
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1271 | |
| 
32ca3d1283de
clarified signature: Build_Process tells how to clean sessions;
 wenzelm parents: 
79701diff
changeset | 1272 | |
| 77436 | 1273 | /* run */ | 
| 77372 | 1274 | |
| 79771 | 1275 |   protected def finished(): Boolean = synchronized {
 | 
| 79763 | 1276 | if (!build_context.master && progress.stopped) _state.build_running.isEmpty | 
| 1277 | else _state.pending.isEmpty | |
| 79770 | 1278 | } | 
| 79763 | 1279 | |
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1280 | private var _build_tick: Long = 0L | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1281 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1282 | protected def build_action(): Boolean = | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1283 |     Isabelle_Thread.interrupt_handler(_ => progress.stop()) {
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1284 | val received = build_receive(n => n.channel == Build_Process.private_data.channel) | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1285 | val ready = received.contains(Build_Process.private_data.channel_ready) | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1286 |       val reactive = ready && synchronized { !_state.busy_running(build_context.jobs) }
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1287 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1288 |       val finished = synchronized { _state.finished_running() }
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1289 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1290 |       def sleep: Boolean = {
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1291 | build_delay.sleep() | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1292 |         val expired = synchronized { _build_tick += 1; _build_tick % build_expire == 0 }
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1293 | expired || reactive || progress.stopped | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1294 | } | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1295 | |
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1296 | finished || sleep | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1297 | } | 
| 79763 | 1298 | |
| 80109 
dbcd6dc7f70f
back to static numa_nodes (reverting part of c2c59de57df9);
 wenzelm parents: 
79904diff
changeset | 1299 | protected def init_unsynchronized(): Unit = | 
| 79848 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1300 |     if (build_context.master) {
 | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1301 | val sessions1 = | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1302 | _state.sessions.init(build_context, _database_server, progress = build_progress) | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1303 | val pending1 = | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1304 |         sessions1.iterator.foldLeft(_state.pending) {
 | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1305 | case (map, session) => | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1306 | if (map.isDefinedAt(session.name)) map | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1307 | else map + Build_Process.Task.entry(session, build_context) | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1308 | } | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1309 | _state = _state.copy(sessions = sessions1, pending = pending1) | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1310 | } | 
| 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1311 | |
| 79771 | 1312 |   protected def main_unsynchronized(): Unit = {
 | 
| 79887 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1313 |     for (job <- _state.running.valuesIterator; build <- job.build if build.is_finished) {
 | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1314 | val result = build.join | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1315 | val result_name = (job.name, worker_uuid, build_uuid) | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1316 | _state = _state. | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1317 | remove_pending(job.name). | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1318 | remove_running(job.name). | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1319 | make_result(result_name, | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1320 | result.process_result, | 
| 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1321 | result.output_shasum, | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79887diff
changeset | 1322 | job.start_date, | 
| 79887 
17220dc05991
revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
 wenzelm parents: 
79886diff
changeset | 1323 | node_info = job.node_info) | 
| 79771 | 1324 | } | 
| 1325 | ||
| 1326 |     for (name <- next_jobs(_state)) {
 | |
| 1327 |       if (is_session_name(name)) {
 | |
| 1328 |         if (build_context.sessions_structure.defined(name)) {
 | |
| 1329 |           _state.ancestor_results(name) match {
 | |
| 1330 | case Some(results) => _state = start_session(_state, name, results) | |
| 1331 |             case None => warning("Bad build job " + quote(name) + ": no ancestor results")
 | |
| 1332 | } | |
| 1333 | } | |
| 1334 |         else warning("Bad build job " + quote(name) + ": no session info")
 | |
| 1335 | } | |
| 1336 |       else warning("Bad build job " + quote(name))
 | |
| 1337 | } | |
| 1338 | } | |
| 1339 | ||
| 78440 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 wenzelm parents: 
78434diff
changeset | 1340 |   def run(): Build.Results = {
 | 
| 79770 | 1341 | val vacuous = | 
| 1342 |       synchronized_database("Build_Process.init") {
 | |
| 79851 | 1343 | _build_cluster.init() | 
| 79848 
dc517696e5ff
clarified signature: init_state vs. init_unsynchronized;
 wenzelm parents: 
79845diff
changeset | 1344 | init_unsynchronized() | 
| 79770 | 1345 | build_context.master && _state.pending.isEmpty | 
| 78571 | 1346 | } | 
| 79770 | 1347 |     if (vacuous) {
 | 
| 77335 | 1348 |       progress.echo_warning("Nothing to build")
 | 
| 79852 
15948836fa90
more robust init_built: get_build_id and start_build within the same transaction;
 wenzelm parents: 
79851diff
changeset | 1349 | if (build_context.master) stop_build() | 
| 78440 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 wenzelm parents: 
78434diff
changeset | 1350 | Build.Results(build_context) | 
| 77335 | 1351 | } | 
| 1352 |     else {
 | |
| 78241 | 1353 | start_worker() | 
| 78434 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 wenzelm parents: 
78430diff
changeset | 1354 | _build_cluster.start() | 
| 77578 
149d48a4801b
support for "isabelle build -j0": require external workers to make progress;
 wenzelm parents: 
77561diff
changeset | 1355 | |
| 77538 | 1356 |       try {
 | 
| 79770 | 1357 |         while (!finished()) {
 | 
| 79771 | 1358 |           synchronized_database("Build_Process.main") {
 | 
| 79790 | 1359 | if (progress.stopped) _state.build_running.foreach(_.cancel()) | 
| 79771 | 1360 | main_unsynchronized() | 
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1361 |             if (build_context.master && _state.exists_ready) {
 | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1362 | build_send(Build_Process.private_data.channel_ready) | 
| 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1363 | } | 
| 79771 | 1364 | } | 
| 79886 
7ae25372ab04
database performance tuning: prefer light-weight IPC over heavy-duty transactions, following bf377e10ff3b;
 wenzelm parents: 
79885diff
changeset | 1365 |           while(!build_action()) {}
 | 
| 77396 | 1366 | } | 
| 77310 | 1367 | } | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1368 |       finally {
 | 
| 78434 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 wenzelm parents: 
78430diff
changeset | 1369 | _build_cluster.stop() | 
| 77580 
32f9e75c92e9
clarified worker state: always maintain database content via worker_uuid;
 wenzelm parents: 
77579diff
changeset | 1370 | stop_worker() | 
| 77579 
69d3547206db
clarified signature: prefer Build_Process.Context for parameters;
 wenzelm parents: 
77578diff
changeset | 1371 | if (build_context.master) stop_build() | 
| 77546 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 wenzelm parents: 
77545diff
changeset | 1372 | } | 
| 77467 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 wenzelm parents: 
77466diff
changeset | 1373 | |
| 78356 | 1374 |       synchronized_database("Build_Process.result") {
 | 
| 78440 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 wenzelm parents: 
78434diff
changeset | 1375 | val results = for ((name, result) <- _state.results) yield name -> result.process_result | 
| 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 wenzelm parents: 
78434diff
changeset | 1376 | Build.Results(build_context, results = results, other_rc = _build_cluster.rc) | 
| 77257 | 1377 | } | 
| 1378 | } | |
| 1379 | } | |
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1380 | |
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1381 | |
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1382 | /* snapshot */ | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1383 | |
| 78356 | 1384 |   def snapshot(): Build_Process.Snapshot = synchronized_database("Build_Process.snapshot") {
 | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1385 | val (builds, workers) = | 
| 78203 | 1386 |       _build_database match {
 | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1387 | case None => (Nil, Nil) | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1388 | case Some(db) => | 
| 78396 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1389 | (Build_Process.private_data.read_builds(db), | 
| 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 wenzelm parents: 
78394diff
changeset | 1390 | Build_Process.private_data.read_workers(db)) | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1391 | } | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1392 | Build_Process.Snapshot( | 
| 77660 | 1393 | builds = builds, | 
| 77659 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1394 | workers = workers, | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1395 | sessions = _state.sessions, | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1396 | pending = _state.pending, | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1397 | running = _state.running, | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1398 | results = _state.results) | 
| 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 wenzelm parents: 
77658diff
changeset | 1399 | } | 
| 78156 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1400 | |
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1401 | |
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1402 | /* toString */ | 
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1403 | |
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1404 | override def toString: String = | 
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1405 | "Build_Process(worker_uuid = " + quote(worker_uuid) + ", build_uuid = " + quote(build_uuid) + | 
| 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 wenzelm parents: 
78154diff
changeset | 1406 | if_proper(build_context.master, ", master = true") + ")" | 
| 77238 | 1407 | } |